Configuration management strategies

When building pipelines, there are many strategies for structuring your configuration in source control and in pipeline design. No single method can cover all situations. This topic presents some of the possibilities and their uses so that you can choose the best approach for your situation.

Single repository for each foundation

This is the simplest approach, and it's the default assumed in all of the examples in these topics, unless there is a clear reason to use a different approach. It entails using a single Git repository for each foundation.

Tracking foundation changes are simple, getting started is easy, duplicating foundations involves only cloning a repository, and configuration files are not difficult to understand.

This is the strategy used in Install Tanzu Operations Manager and Upgrading an existing Tanzu Operations Manager.

This example configuration repository uses the "Single Repository for each Foundation" pattern:

├── auth.yml
├── pas.yml
├── director.yml
├── download-opsman.yml
├── download-product-configs
│   ├── healthwatch.yml
│   ├── opsman.yml
│   ├── pas-windows.yml
│   ├── pas.yml
│   └── telemetry.yml
├── env.yml
├── healthwatch.yml
├── opsman.yml
└── pas-windows.yml

Notice that there is only one subdirectory and that all other files are in the base directory. This minimizes parameter mapping in the platform-automation tasks. For example, in the configure-director step:

- task: configure-director
  image: platform-automation-image
  file: platform-automation-tasks/tasks/configure-director.yml
  input_mapping:
    config: configuration
    env: configuration

You map the config files to the expected input named env of the configure-director task. Because the configure-director task's default ENV parameter is env.yml, it automatically uses the env.yml file in the configuration repo. You do not need to explicitly name the ENV parameter for the task. This also works for director.yml.

Another option for mapping resources to inputs is discussed in Matching resource names and input names.

For reference, here is the configure-director task:

The inputs, outputs, params, filename, and filepath of this task file are part of its semantically versioned API. See www.semver.org for information about semantic versioning.


---
platform: linux

inputs:
- name: platform-automation-tasks
- name: config # contains the director configuration file
- name: env # contains the env file with target OpsMan Information
- name: vars # variable files to be made available
  optional: true
- name: secrets
  # secret files to be made available
  # separate from vars, so they can be store securely
  optional: true
- name: ops-files # operations files to custom configure the product
  optional: true

params:
  VARS_FILES:
  # - Optional
  # - Filepath to the Ops Manager vars YAML file
  # - The path is relative to root of the task build,
  #   so `vars` and `secrets` can be used.

  OPS_FILES:
  # - Optional
  # - Filepath to the Ops Manager operations YAML files
  # - The path is relative to root of the task build

  ENV_FILE: env.yml
  # - Required
  # - Filepath of the env config YAML
  # - The path is relative to root of the `env` input

  DIRECTOR_CONFIG_FILE: director.yml
  # - Required
  # - Filepath to the director configuration YAML file
  # - The path is relative to the root of the `config` input

run:
  path: platform-automation-tasks/tasks/configure-director.sh

Multiple foundations with one repository

Multiple foundations can use a single Git configuration source, but have different variables loaded from a foundation-specific vars file, CredHub, and so on.

This strategy can reduce foundation drift and streamline the configuration promotion process between foundations.

This is the strategy used in the reference pipeline.

Overview

The reference pipeline uses a public config repo with all secrets stored in the CredHub belonging to Concourse.

The design considerations for this strategy, as implemented, are:

  • Prioritization of ease of configuration promotion is prioritized over minimization of configuration file duplication between foundations.

  • Global, non-public variables can be overwritten by foundation-specific variables based on VARS_FILES ordering.

  • Product configuration can differ between product versions, so the entire configuration file is promoted between foundations.

  • No outside tooling or additional preparation tasks are required to use this strategy. It makes use of only concepts and workflows built in to Platform Automation and Concourse.

  • There are no significant differences between the required setup of the foundations.

    This doesn't mean that this strategy cannot be used with more complicated differences. If the pipelines need to be different for one reason or another, you might want the pipelines directory to be at the foundation level and for the pipeline.yml to be foundation-specific.

    The reference pipeline handles the different environments via a fly variable. The pipeline set script is found in the scripts directory.

Structure

A simplified view of the config-repo is represented below:

├── download-product-pivnet
│   ├── download-opsman.yml
│   └── download-pks.yml
├── foundations
│   ├── config
│   │   ├── auth.yml
│   │   └── env.yml
│   ├── development
│   │   ├── config
│   │   │   ├── director.yml
│   │   │   ├── download-opsman.yml
│   │   │   ├── download-pks.yml
│   │   │   ├── opsman.yml
│   │   │   └── pks.yml
│   │   └── vars
│   │       ├── director.yml
│   │       ├── pks.yml
│   │       └── versions.yml
│   ├── sandbox
│   │   ├── config
│   │   │   ├── director.yml
│   │   │   ├── download-opsman.yml
│   │   │   ├── download-pks.yml
│   │   │   ├── opsman.yml
│   │   │   └── pks.yml
│   │   └── vars
│   │       ├── director.yml
│   │       ├── pks.yml
│   │       └── versions.yml
│   └── vars
│       └── director.yml
├── pipelines
│   ├── download-products.yml
│   └── pipeline.yml
└── scripts
    └── update-reference-pipeline.sh

Starting with with the top-level folders:

  • download-product-pivnet contains config files for downloading products from the Broadcom Support portal and uploading these products to a blobstore.
  • foundations contains all of the configuration files and variable files for all foundations.
  • pipelines contains the pipeline files for the resources pipeline and the foundation pipelines.
  • scripts contains the BASH script for setting all of the pipelines.

foundations

The foundations folder contains all of the foundations plus two additional folders:

  • config contains any global config files, in this case, env.yml and auth.yml. These files are used by om and their structure is not foundation-dependent, so each foundation pipeline fills out the parameterized variables from the Concourse credential manager.
  • vars contains foundation-independent variables for any of the configuration files. In this example, all of the foundations are on a single IAAS, so the common vars tend to be IAAS-specific. These files can also include any other variables determined to be consistently the same across foundations.

foundations/

For each foundation, there are two folders:

  • config contains the configuration files that om uses for:
    • Downloading products from a blobstore; specified with the prefix download-
    • Configuring a product; specified by <product-name>.yml
    • Configuring the BOSH director; specified with director.yml
    • Configuring the Tanzu Operations Manager VM; specified with opsman.yml
  • vars contains any foundation-specific variables used by Platform Automation tasks. These variables fill in any variables ((parameterized)) in config files that are not stored in Concourse's credential manager.

Config promotion example

This example, shows how to update PKS from 1.3.8 to 1.4.3. We will start with updating this tile in our sandbox foundation and then promote the configuration to the development foundation.

This procedure assumes that you are viewing this example from the root of the Platform Automation Reference Pipeline Configs repo.

  1. Update download-product-pivnet/download-pks.yml:

    - product-version-regex: ^1\.3\..*$
    + product-version-regex: ^1\.4\..*$
    
  2. Commit this change and run the resource pipeline. This downloads the 1.4.3 PKS tile and makes it available on S3.

  3. Update the versions file for sandbox:

    - pks-version: 1.3.8
    + pks-version: 1.4.3
    
  4. Run the upload-and-stage-pks job, but do not run the configure-pks or apply-product-changes jobs.

    This ensures that the apply-changes step doesn't automatically fail if there are configuration changes between what what is currently deployed and the new tile.

  5. Log in to the Tanzu Operations Manager UI. If the tile has unconfigured properties:

    1. Manually configure the tile and deploy it.

    2. Re-export the staged-config:

      om -e env.yml staged-config --include-credentials -p pivotal-container-service
      
    3. Merge the resulting config with the existing foundations/sandbox/config/pks.yml.

      Doing a diff of the previous pks.yml against the new one makes this process much easier.

    4. Pull out the new parametrizable variables and store them in foundations/vars/pks.yml or foundations/sandbox/vars/pks.yml, or directly into CredHub. Note that there may be nothing new to parameterize. This is okay, and makes the process go faster.

    5. Commit any changes.

  6. Run the configure-pks and apply-product-changes jobs on the sandbox pipeline.

  7. Assuming the sandbox pipeline is all green, copy the foundations/sandbox/config folder into foundations/development/config.

  8. Modify the foundations/development/vars/versions.yml and foundations/development/vars/pks.yml files to have all of the property references that exist in their sandbox counterparts and the foundation-specific values.

  9. Commit these changes and run the development pipeline all the way through.

A quicker development deploy process: Since all of the legwork is done manually in the sandbox environment, there is no need to log in to the development Tanzu Operations Manager environment.
If there are no configuration changes, the only file that needs to be promoted is versions.yml.

Advanced pipeline design

Matching resource names and input names

As an alternative to input_mapping, you can create resources that match the input names on the tasks. Even if these resources map to the same git repository and branch, they can be declared as separate inputs.

- name: config
  type: git
  source:
    private_key: ((repo-key.private_key))
    uri: ((repo-uri))
    branch: develop

- name: env
  type: git
  source:
    private_key: ((repo-key.private_key))
    uri: ((repo-uri))
    branch: develop

As long as each of these resources have an associated get: <resource-name> in the job, they will automatically be mapped to the inputs of the tasks in that job:

- name: configure-director
  serial: true
  plan:
    - aggregate:
      - get: platform-automation-image
        params:
          unpack: true
      - get: platform-automation-tasks
        params:
          unpack: true
      - get: config
        passed: [previous-job]
      - get: env
        passed: [previous-job]
    - task: configure-director
      image: platform-automation-image
      file: platform-automation-tasks/tasks/configure-director.yml
If you have two resources defined with the same git repository, such as env and config, and have a passed constraint on only one of them, there is a possibility that they will not be at the same SHA for any given job in your pipeline.

Example:


   - get: config
   - get: env
     passed: [previous-job]
  

Modifying resources in-place

This section uses a Concourse feature that allows inputs and outputs to have the same name. This feature is only available in Concourse 5+. The example that follows does not work with Concourse v4.

In certain circumstances, resources can be modified by one task in a job for use later in that same job. A few tasks that offer this ability include:

For each of these tasks, output_mapping can be used to overwrite an input with a modified input for use with tasks later in that job.

In the following example, prepare-tasks-with-secrets takes in the platform-automation-tasks input and modifies it for the download-product task. For a more detailed explanation see Secrets Handling.

- name: configure-director
  serial: true
  plan:
    - aggregate:
      - get: platform-automation-image
        params:
          unpack: true
      - get: platform-automation-tasks
        params:
          unpack: true
      - get: config
      - get: env
    - task: prepare-tasks-with-secrets
      image: platform-automation-image
      file: platform-automation-tasks/tasks/prepare-tasks-with-secrets.yml
      input_mapping:
        tasks: platform-automation-tasks
      output_mapping:
        tasks: platform-automation-tasks
      params:
        CONFIG_PATHS: config
    - task: download-product
      image: platform-automation-image
      # The following platform-automation-tasks have been modified
      # by the prepare-tasks-with-secrets task
      file: platform-automation-tasks/tasks/download-product.yml
      params:
        CONFIG_FILE: download-ops-manager.yml
check-circle-line exclamation-circle-line close-line
Scroll to top icon