Skip to content
This repository has been archived by the owner on Nov 13, 2023. It is now read-only.

Working with Team Configuration

Timothy Johnson edited this page Feb 21, 2023 · 2 revisions

Overview

Zowe CLI (and other apps using the Imperative framework) reads user-specified configuration property values from a team configuration file. Team configurations replace the older "user profiles" of previous releases (see Deprecated User Profiles). In previous release, users issued commands from the zowe profiles group to create, edit, and manage user profiles. Each profile contained the host, port, username, and password for a specific mainframe service instance. While that approach was effective, users often needed to duplicate values across profiles and spend time managing many profiles separately.

Team configuration simplifies profile management by letting you edit, store, and share mainframe configuration details in one location. You can use a text editor to populate configuration files with connection details for your mainframe services. The name "team configuration" is meant to reinforce the idea that the team config files can be easily shared among the members of a team at a customer site. A team config is a JSON file which contains the configuration properties used by Zowe CLI commands, plug-in commands, and numerous VS Code extensions.

A team config can contain "typed" profile objects. These profiles contain properties for a specific type of remote subsystem or application, like z/OSMF, CICS, Endevor, etc. When a CLI or plug-in command group defines one or more profiles, it is a "typed" profile and it has a profile-type name. A command's definition specifies the set of profile types that it uses. The properties of such a profile type can be specified in a typed profile within a team config.

Benefits

Team configuration can improve your Zowe CLI experience in the following ways:

  • As a Zowe user, you can manage your connection details efficiently in one location.
  • As a team leader, you can share a configuration file with your team members so that they can easily access mainframe services. You can add the file directly to your project in an SCM.
  • As a new team member, you can onboard quickly by consuming your team's configuration file.

The following article on medium.com describes why we created team configuration files and how an end user would operate on his/her team configuration: Zowe CLI — Getting Started, Made Easy!

In the sections below, we identify team configuration capabilities, describe how a user creates and edits a team configuration, and provide examples for several use cases.

Team Configuration concepts

The items below identify key characteristics and operational considerations related to Team Configuration. The intent is to provide an understanding of a broad range of Team Configuration capabilities. Details of how to specify and use those capabilities are contained in other sections of this document or in other documents referenced by this document.

  • All types of profile property values for every service are all stored in one file.
    • This makes it easier for one person to share a configuration with many other people.
  • A team configuration is a JSON file named zowe.config.json.
    • It is intended that end-users will directly edit a team configuration file to modify property values and to add new profiles or properties.
    • Profiles and properties can be specified at various levels of JSON object nesting.
      • This enables specification of common properties at a higher level which apply to all lower levels of nesting. Host name is a good example.
    • Comments are permitted in this JSON file.
      • Enables you to supply your own notes.
      • You can comment out a property value while temporarily using a different value.
  • The "zowe config init" command creates a "starter" team config file.
    • The starter config structure organizes services by LPAR.
    • The starter config includes important profile properties for core CLI commands and for plugins that are installed on the machine.
    • Plugins can specify which of their profile properties should be included in the starter config.
    • The starter config is secure by default.
      • You are prompted for values for any properties in the starter config which are marked as secure.
      • The values are stored in the secure credential store, not in plain text within the team config.
      • Since credentials are not stored in the team config, the team config is safer and easier to share.
  • A schema file is created when a team config file is created.
    • The schema enables IntelliSense type of prompting when editing the team config in the Visual Studio Code editor or other editors that support a JSON schema.
    • A customer site can host a schema file in a common location for all users.
    • A team config file must point to the schema file.
  • Global team config
    • A global team config is simply a team config file that resides in the .zowe directory under your OS HOME directory.
    • If a global team config file exists, it will be used when you are in any directory on your computer (as long another team config file does not exist inside that particular directory).
    • A global team config is useful when you want to personally control your own profile properties and typically want the same property values to apply for every action that you take in any directory.
    • If you temporarily want a different set of values, you edit you global team config with the values that you want, and you set them back later.
    • You might create a global team config that another team member could use. You can email your team config (and its schema) to that colleague, or you could share the two files on a server.
      • That teammate could simply place the two files into his/her .zowe directory.
      • Assuming that the second teammate needed the exact same services, that teammate would not have to edit the team config file at all.
      • Not only does the second teammate not have to do any editing, but (s)he would be spared the even more difficult task of finding the location, port, and other more obscure properties of each desired service.
  • Project team config
    • A project team config is a team config file that resides in a specific directory. When your current directory is that directory, or any directory beneath it, your Zowe commands will use that project team configuration file.
    • One use case for a project team config is when multiple developers are working on a development project that uses Zowe technology. The entire directory tree of source files are likely managed by a source control system like GitHub.
      • By placing a team config into the root directory of such a development project, all of the relevant connection and application properties will be used when building and testing that development project.
      • By committing the team config file into the source control system, that project team config is automatically shared with all other developers on that project.
      • If a developer periodically switches into another such project to do some work, the team config of that project will be used while working on that project. All of that developer's profile properties values would be automatically changed appropriately for the other project, without the developer having to edit any property values in the process.
  • User config
    • A user config file is used to override values from a shared team config file with values specific to the user.
      • If a property exists in the user config which does not exist in the shared team config, then the property value from the user config is used (for that user) as if the property did exist in the shared team config.
      • If the same property exists in both the shared team config and the user config, then the user config value is used (for that user) instead of the value in the shared team config.
    • The user config file has the same JSON format as the shared team config and is named zowe.config.user.json.
    • A user config file can reside with either a global team config or a project team config. It overrides the values of the team config file with which it is paired.
    • The user config is most valuable when a project team config is shared with other team members in a source control system.
      • The user config would not be committed to source control, so that its values would override the project team config only for the individual user.
      • If a site used plain text passwords, those passwords could be stored in each user's user config. Thus, the shared project team config would contain no passwords. We recommend against using plain text passwords. Instead, allow the built-in secure credential manager to manage secure properties in a team configuration. No credentials will be stored in the shared team config file, making it quite safe to share in a source control system.
      • Another use case for a user config is when one developer on a project needs to use a special copy of a service (perhaps to test a destructive operation). That developer may need to run his/her own copy of the service, possibly on a different host with a different port.
        • By specifying those special values in a user config, there is little risk of accidentally changing those values for other team members.
        • The user config is largely empty (except for the overrides), so special override values will not be hard to find as they might be within the much larger set of values contained in a project team config.
  • How global and project team config properties are merged.
    • If you are in a directory that contains a team config, and a team config also exists in your .zowe directory, values from the two team config files will be merged.
    • If any property is contained in both config files, then the value in the project team config will be used.
    • If the global team config contains a property that does not exist in the project config, then the property and value from the global team config will be available to the Zowe operation.

Team Configuration setup techniques

Install Zowe CLI apps

Follow these steps:

  1. Meet the software requirements for Zowe CLI.

  2. To install or update the core CLI, open a command-line window and issue the following command:

    npm install -g @zowe/cli
    
  3. Meet the software requirements for each plug-in.

  4. (Optional) Issue the following command to install each desired plugin (substituting the plugin name):

    zowe plugins install @zowe/<plugin-name>
    

Zowe CLI and optional plug-ins are installed!

Remove unused artifacts from a previous zowe-v1-lts release

If you re-installed the latest version of Zowe onto a machine that already had a zowe-v1-lts version of Zowe installed, perform these additional steps:

  1. If you previously had the Secure Credential Store (SCS) plug-in installed, issue the following command so that the SCS plugin de-registers itself as a credential manager provider:

    zowe scs revert --force
    
  2. The Zowe Secure Credential Store is now automatically available as part of the Zowe CLI. Uninstall the old Secure Credential Store (SCS) plug-in to avoid unexpected behavior. Issue the following command:

    zowe plugins uninstall @zowe/secure-credential-store-for-zowe-cli
    
  3. If you previously created profiles with a zowe-v1-lts version of Zowe CLI, those profiles will be ignored if zowe.config.json is found globally, at the project level, or up the directory structure. Conversely, if no zowe.config.json is found, Zowe CLI will use your old profiles. To avoid this confusion, take the following actions to ensure that zowe-v1-lts configuration items are not used.

    • Rename your ~/.zowe/settings/imperative.json file to a name like .zowe/settings/imperative_v1.json
    • Rename your ~/.zowe/profiles directory to a name like ~/.zowe/profiles_v1

    You may decide to experiment with team configuration for a while, but later return to your zowe-v1-lts profiles because you are not yet prepared to completely convert that particular machine. To restore zowe-v1-lts profile usage, you can:

    • Rename profiles_v1 and imperative_v1.json back to their original names.
    • Rename any zowe.config.json file that you have created to a name like zowe.config_disabled.json

You can now configure the CLI and issue commands.

Initialize a global team configuration

Zowe takes an approach of "secure by default". As a result, some secure credential operations will automatically occur as you issue some of the commands below. See Managing Secure Properties for more information about how Zowe manages any properties that you define as secure.

To begin, define a connection to z/OSMF and initialize your configuration files. We recommend the following method for getting started, but you can choose create the team configuration files manually if desired.

Follow these steps:

  1. Issue the following command:

    zowe config init --global-config
    

    The CLI provides a series of prompts.

  2. Respond to the prompts to enter a username and password for a mainframe service such as z/OSMF. The config init command ensures that your credentials are stored securely on your computer by default.

    After you respond to the prompts, the following file is added to your local .zowe directory:

    • zowe.config.json - A global configuration file. This is the primary location where your MF service connection details such as host and port are defined. Use this configuration file for the following procedures.
  3. Edit the zowe.config.json file to change the name of the LPAR, to supply a value for the host name, and to change the port number if needed.

  4. Issue a Zowe CLI command to test that you can access z/OSMF. For example, list all data sets under your user ID:

    zowe zos-files list data-set "MY.DATASET.*"
    

    A list of data sets is returned. You successfully configured Zowe CLI to access a z/OSMF instance!

    If the CLI returns an error message, verify that you have access to the target system. Examine your configuration files in a text editor to verify that the information you entered is correct.

Important!: After the configuration files are in place (either via the zowe config init command or by manually creating the files), the old zowe profiles commands will no longer function. Expect to see errors if you attempt to make use of old profiles.

(Optional) Initializing user-specific configuration

Additionally, you can generate a user-specific configuration file. In your user config, you can override values that are defined in the global zowe.config.json.

Issue the command zowe config init --global-config --user-config to generate both global (zowe.config.json) and user (zowe.config.user.json) config files.

In your user-specific file, notice that the top level defaults, plugins, and secure fields are empty. The profiles do not have any properties. You can add your connection details as properties here to override properties in zowe.config.json, or add new connections.

Editing configuration

After the initial setup, you can define additional mainframe services to your global or user config.

Open the ~/.zowe/zowe.config.json file in a text editor or IDE on your computer. The profiles object should contain connection and other frequently needed information for accessing various services. For example:

{
    "$schema": "./zowe.schema.json",
    "profiles": {
        "lpar1": {
            "properties": {
                "host": "example1.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 443
                    }
                }
            },
            "secure": [
                "user",
                "password"
            ]
        }
    },
    "defaults": {
        "zosmf": "lpar1.zosmf"
    },
    "plugins": []
}

From here, you can edit the details as needed and save the file. For example, you might change the host or port fields if those values changed.

To add a new service, for example add a new instance of z/OSMF that runs on a different mainframe LPAR, you can build on the existing array as follows:

{
    "$schema": "./zowe.schema.json",
    "profiles": {
        "lpar1": {
            "properties": {
                "host": "example1.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 443
                    }
                }
            },
            "secure": [
                "user",
                "password"
            ]
        },
        "lpar2": {
            "properties": {
                "host": "example2.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 1443
                    }
                }
            },
            "secure": [
                // See below about tips for using base profile to avoid duplicating these
                "user",
                "password"
            ]
        }
    },
    "defaults": {
        // Change to lpar2.zosmf if you wish to change default profile
        "zosmf": "lpar1.zosmf"
    },
    "plugins": []
}

You can continue to add more LPARs, and more services within each LPAR. After you make changes, save the file and issue a Zowe CLI command to the service to verify connection.

Tips for efficient configuration

There are several methods you can employ to more efficiently update and maintain your configuration.

Zowe CLI uses a "command option order of precedence" that lets your service definitions inherit option values. You can use this to your advantage, because it lets you avoid duplicating the same option value in several places.

The CLI checks for option values in the following order. If not found, the next location is checked:

  1. Options you define explicitly on the command-line
  2. Environment variables
  3. Service type profiles
  4. Base type profiles
  5. If no value is found, the default value for the option is used.

In the following example, the user and password fields are not supplied in the "zosmf" service profiles for either LPAR1 or LPAR2 to allow them to inherit values from the base profile (see the array of "secure" property names near the end of the example).

{
    "$schema": "./zowe.schema.json",
    "profiles": {
        "lpar1": {
            "properties": {
                "host": "example1.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 443
                    }
                }
            }
        },
        "lpar2": {
            "properties": {
                "host": "example2.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 1443
                    }
                }
            }
        },
        "my_base": {
            "type": "base",
            "properties": {
                "rejectUnauthorized": true
            },
            "secure": [
                "user",
                "password"
            ]
        }
    },
    "defaults": {
        "zosmf": "lpar1.zosmf",
        "base": "my_base"
    },
    "plugins": []
}

Tips for using the base profile

The base profile is a useful tool for sharing option values between services. You might define options to the base profile in the following situations:

  • You have multiple services that share the same username, password, or other value.
  • You want to store a web security token to access all services through Zowe API Mediation Layer.
  • You want to trust a known self-signed certificate, or your site does not have server certificates configured. You can define reject-unauthorized in the base profile with a value of false to apply to all services. Understand the security implications of accepting self-signed certificates at your site before you use this method.

Sharing a team configuration

You might want to share a team configuration in the following scenarios:

  • Share a global team config with developers so that they can begin working with a defined set of mainframe services. The recipient of the file manually places it in their local ~/.zowe folder before issuing CLI commands.
  • Add a team config to your project directory in an SCM tool such as GitHub. This lets other developers pull the project to their local machine and make use of the defined configuration. Zowe CLI commands that you issue from within the project directory automatically use the project's team config.
  • Enable test automation and CI/CD, letting your pipelines make use of the project team configuration.

Example configurations

In this example configuration, the settings are accessing multiple services directly on multiple LPARs that share the same username and password.

{
    "$schema": "./zowe.schema.json",
    "profiles": {
        "lpar1": {
            "properties": {
                "host": "example1.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 443
                    }
                },
                "tso": {
                    "type": "tso",
                    "properties": {
                        "account": "ACCT#",
                        "codePage": "1047",
                        "logonProcedure": "IZUFPROC"
                    }
                },
                "ssh": {
                    "type": "ssh",
                    "properties": {
                        "port": 22
                    }
                }
            }
        },
        "lpar2": {
            "properties": {
                "host": "example2.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 1443
                    }
                }
            }
        },
        "my_base": {
            "type": "base",
            "properties": {
                "rejectUnauthorized": true
            },
            "secure": [
                "user",
                "password"
            ]
        }
    },
    "defaults": {
        "zosmf": "lpar2.zosmf",
        "tso": "lpar1.tso",
        "ssh": "lpar1.ssh",
        "base": "my_base"
    },
    "plugins": []
}

In this example configuration, the settings are accessing multiple services directly on LPAR1 and LPAR2 where username and password varies between the LPAR1 and LPAR2 services. This example is identical to the first example except that LPAR1 and LPAR2 each contain a secure array, instead of just one secure array in the "my_base" profile.

{
    "$schema": "./zowe.schema.json",
    "profiles": {
        "lpar1": {
            "properties": {
                "host": "example1.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 443
                    }
                },
                "tso": {
                    "type": "tso",
                    "properties": {
                        "account": "ACCT#",
                        "codePage": "1047",
                        "logonProcedure": "IZUFPROC"
                    }
                },
                "ssh": {
                    "type": "ssh",
                    "properties": {
                        "port": 22
                    }
                }
            },
            "secure": [
                "user",
                "password"
            ]
        },
        "lpar2": {
            "properties": {
                "host": "example2.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 1443
                    }
                }
            },
            "secure": [
                "user",
                "password"
            ]
        },
        "my_base": {
            "type": "base",
            "properties": {
                "rejectUnauthorized": true
            }
        }
    },
    "defaults": {
        "zosmf": "lpar2.zosmf",
        "tso": "lpar1.tso",
        "ssh": "lpar1.ssh",
        "base": "my_base"
    },
    "plugins": []
}

In this example configuration, the settings are accessing multiple services via the API ML (where MFA/SSO is achievable via token-based authorization).

{
    "$schema": "./zowe.schema.json",
    "profiles": {
        "lpar1": {
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "basePath": "api/v1"
                    }
                },
                "cics": {
                    "type": "cics",
                    "properties": {
                        "basePath": "api/v1/my_cics"
                    }
                },
                "db2": {
                    "type": "db2",
                    "properties": {
                        "basePath": "api/v1/my_db2"
                    }
                }
            }
        },
        "my_base": {
            "type": "base",
            "properties": {
                "host": "example1.com",
                "port": 443,
                "rejectUnauthorized": true
            },
            "secure": [
                "authToken"
            ]
        }
    },
    "defaults": {
        "zosmf": "lpar1.zosmf",
        "cics": "lpar1.cics",
        "db2": "lpar1.db2",
        "base": "my_base"
    },
    "plugins": []
}

In this example configuration, API ML is leveraged to access production services but services on a dev-test environment can be accessed directly.

{
    "$schema": "./zowe.schema.json",
    "profiles": {
        "prod": {
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "basePath": "api/v1"
                    }
                },
                "cics": {
                    "type": "cics",
                    "properties": {
                        "basePath": "api/v1/my_cics"
                    }
                },
                "db2": {
                    "type": "db2",
                    "properties": {
                        "basePath": "api/v1/my_db2"
                    }
                }
            }
        },
        "dev": {
            "properties": {
                "host": "example1.com"
            },
            "profiles": {
                "zosmf": {
                    "type": "zosmf",
                    "properties": {
                        "port": 443
                    }
                },
                "tso": {
                    "type": "tso",
                    "properties": {
                        "account": "ACCT#",
                        "codePage": "1047",
                        "logonProcedure": "IZUFPROC"
                    }
                },
                "ssh": {
                    "type": "ssh",
                    "properties": {
                        "port": 22
                    }
                }
            },
            "secure": [
                "user",
                "password"
            ]
        },
        "my_base": {
            "type": "base",
            "properties": {
                "host": "example1.com",
                "port": 443,
                "rejectUnauthorized": true
            },
            "secure": [
                "authToken"
            ]
        }
    },
    "defaults": {
        "zosmf": "prod.zosmf",
        "cics": "prod.cics",
        "db2": "prod.db2",
        "tso": "dev.tso",
        "ssh": "dev.ssh",
        "base": "my_base"
    },
    "plugins": []
}