Skip to content

Task Reference

Pivotal Platform Automation Tasks

This document lists each Pivotal Platform Automation task, and provides information about their intentions, inputs, and outputs.

The tasks are presented, in their entirety, as they are found in the product.

The docker image can be used to invoke the commands in each task locally. Use --help for more information. To learn more see the running-commands-locally section.

apply-changes

Triggers an install on the Ops Manager described by the auth file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information

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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" apply-changes

apply-director-changes

apply-changes can also be used to trigger an install for just the BOSH Director with the --skip-deploy-products/-sdp flag.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information

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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" apply-changes \
       --skip-deploy-products

assign-multi-stemcell

assign-multi-stemcell assigns multiple stemcells to a provided product. This feature is only available in OpsMan 2.6+. For more information on how to utilize this workflow, check out the Stemcell Handling topic.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# This feature is only available in OpsMan 2.6+.
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information
- name: config # contains the configuration file for assign-multi-stemcell command
  # - Example config:
  # ---
  # product: cf
  # stemcell:
  # - ubuntu-trusty:1234.6
  # - ubuntu-xenial:latest

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

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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" assign-multi-stemcell \
       --config config/"$CONFIG_FILE"

assign-stemcell

assign-stemcell assigns a stemcell to a provided product. For more information on how to utilize this workflow, check out the Stemcell Handling topic.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information
- name: config # contains the configuration file for assign-stemcell command
  # - Can consume the output of `download-product` task directly
  # - Example config:
  # ---
  # product: cf
  # stemcell: 3468.86

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

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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" assign-stemcell \
       --config config/"$CONFIG_FILE"

configure-authentication

Configures Ops Manager with an internal userstore and admin user account. See configure-saml-authentication to configure an external SAML user store, and configure-ldap-authentication to configure with LDAP.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information
- name: config # contains the auth configuration

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

  AUTH_CONFIG_FILE: auth.yml
  # - Required
  # - Filepath of the authorization config YAML
  # - The path is relative to root of the `config` input

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" configure-authentication \
       --config config/"${AUTH_CONFIG_FILE}"

For details on the config file expected in the config input, please see Generating an Auth File.

configure-director

Configures the BOSH Director with settings from a config file. See staged-director-config, which can extract a config file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
---
platform: linux

inputs:
- 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: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    vars_files_args=("")
    for vf in ${VARS_FILES}
    do
      vars_files_args+=("--vars-file ${vf}")
    done

    ops_files_args=("")
    for of in ${OPS_FILES}
    do
      ops_files_args+=("--ops-file ${of}")
    done

    # ${vars_files_args[@] needs to be globbed to pass through properly
    # ${ops_files_args[@] needs to be globbed to pass through properly
    # shellcheck disable=SC2068
    om --env env/"${ENV_FILE}" configure-director \
       --config "config/${DIRECTOR_CONFIG_FILE}" \
       ${vars_files_args[@]} \
       ${ops_files_args[@]}

GCP with service account

For GCP, if service account is used, the property associated_service_account has to be set explicitly in the iaas_configuration section.

configure-ldap-authentication

Configures Ops Manager with an external LDAP user store and admin user account. See configure-authentication to configure an internal user store, and configure-saml-authentication to configure with SAML.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information
- name: config # contains the auth configuration

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

  AUTH_CONFIG_FILE: auth.yml
  # - Required
  # - Filepath of the authorization config YAML
  # - The path is relative to root of the `config` input

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" configure-ldap-authentication \
    --config config/"${AUTH_CONFIG_FILE}"

For more details on using LDAP, please refer to the Ops Manager documentation.

For details on the config file expected in the config input, please see Generating an Auth File.

configure-product

Configures an individual, staged product with settings from a config file.

Not to be confused with Ops Manager's built-in import, which reads all deployed products and configurations from a single opaque file, intended for import as part of backup/restore and upgrade lifecycle processes.

See staged-config, which can extract a config file, and upload-and-stage-product, which can stage a product that's been uploaded.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
---
platform: linux

inputs:
- name: config # contains the product 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:
  CONFIG_FILE:
  # - Required
  # - Filepath to the product configuration yaml file
  # - The path is relative to the root of the `config` input

  VARS_FILES:
  # - Optional
  # - Filepath to the product configuration 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 product configuration 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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    vars_files_args=("")
    for vf in ${VARS_FILES}
    do
      vars_files_args+=("--vars-file ${vf}")
    done

    ops_files_args=("")
    for of in ${OPS_FILES}
    do
      ops_files_args+=("--ops-file ${of}")
    done

    # ${vars_files_args[@] needs to be globbed to pass through properly
    # ${ops_files_args[@] needs to be globbed to pass through properly
    # shellcheck disable=SC2068
    om --env env/"${ENV_FILE}" configure-product \
       --config "config/${CONFIG_FILE}" \
       ${vars_files_args[@]} \
       ${ops_files_args[@]}

configure-saml-authentication

Configures Ops Manager with an external SAML user store and admin user account. See configure-authentication to configure an internal user store, and configure-ldap-authentication to configure with LDAP.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information
- name: config # contains the auth configuration

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

  AUTH_CONFIG_FILE: auth.yml
  # - Required
  # - Filepath of the authorization config YAML
  # - The path is relative to root of the `config` input

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" configure-saml-authentication \
    --config config/"${AUTH_CONFIG_FILE}"

Configuring SAML has two different auth flows for the UI and the task. The UI will have a browser based login flow. The CLI will require client-id and client-secret as it cannot do a browser login flow.

For more details on using SAML, please refer to the Ops Manager documentation

For details on the config file expected in the config input, please see Generating an Auth File.

create-vm

Creates an unconfigured Ops Manager VM.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
---
platform: linux

inputs:
- name: state # contains the state for the vm
- name: config # contains the product configuration file
- name: image # contains the image file to be installed
- 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

outputs:
- name: generated-state #contains the updated state file


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.

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

  STATE_FILE: state.yml
  # - Required
  # - Filepath of the state yaml file
  # - The path is relative to root of the `state` input

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    vars_files_args=("")
    for vf in ${VARS_FILES}
    do
      vars_files_args+=("--vars-file ${vf}")
    done

    generated_state_path="generated-state/$(basename "$STATE_FILE")"
    if [ -e "state/$STATE_FILE" ]; then
      cp "state/$STATE_FILE" "$generated_state_path"
    fi

    export IMAGE_FILE
    IMAGE_FILE="$(find image/*.{yml,ova,raw} 2>/dev/null | head -n1)"

    if [ -z "$IMAGE_FILE" ]; then
      echo "No image file found in image input."
      echo "Contents of image input:"
      ls -al image
      exit 1
    fi

    # ${vars_files_args[@] needs to be globbed to split properly
    # shellcheck disable=SC2068
    p-automator create-vm \
    --config config/"${OPSMAN_CONFIG_FILE}" \
    --image-file "${IMAGE_FILE}"  \
    --state-file "$generated_state_path" \
    ${vars_files_args[@]}

This task requires a config file specific to the IaaS being deployed to. Please see the configuration page for more specific examples.

The task does specific CLI commands for the creation of the Ops Manager VM on each IAAS. See below for more information:

AWS

  1. Requires the image YAML file from Pivnet
  2. Validates the existence of the VM if defined in the statefile, if so do nothing
  3. Chooses the correct ami to use based on the provided image YAML file from Pivnet
  4. Creates the vm configured via opsman config and the image YAML. This only attaches existing infrastructure to a newly created VM. This does not create any new resources
  5. The public IP address, if provided, is assigned after successful creation

Azure

  1. Requires the image YAML file from Pivnet
  2. Validates the existence of the VM if defined in the statefile, if so do nothing
  3. Copies the image (of the OpsMan VM from the specified region) as a blob into the specified storage account
  4. Creates the Ops Manager image
  5. Creates a VM from the image. This will use unmanaged disk (if specified), and assign a public and/or private IP. This only attaches existing infrastructure to a newly createdVM. This does not create any new resources.

GCP

  1. Requires the image YAML file from Pivnet
  2. Validates the existence of the VM if defined in the statefile, if so do nothing
  3. Creates a compute image based on the region specific Ops Manager source URI in the specified Ops Manager account
  4. Creates a VM from the image. This will assign a public and/or private IP address, VM sizing, and tags. This does not create any new resources.

Openstack

  1. Requires the image YAML file from Pivnet
  2. Validates the existence of the VM if defined in the statefile, if so do nothing
  3. Recreates the image in openstack if it already exists to validate we are using the correct version of the image
  4. Creates a VM from the image. This does not create any new resources
  5. The public IP address, if provided, is assigned after successful creation

Vsphere

  1. Requires the OVA image from Pivnet
  2. Validates the existence of the VM if defined in the statefile, if so do nothing
  3. Build ipath from the provided datacenter, folder, and vmname provided in the config file. The created VM is stored on the generated path. If folder is not provided, the vm will be placed in the datacenter.
  4. Creates a VM from the image provided to the create-vm command. This does not create any new resources

credhub-interpolate

Interpolate credhub entries into configuration files

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
---
platform: linux

inputs:
- name: files
# contains YAML files with extension `.yml`.
# Each one of these files will have their values interpolated from credhub.
# For examples, run: `credhub interpolate --help`
# (minimum version >= 2.1.0 required)

outputs:
- name: interpolated-files
# Contains only yaml files found and interpolated by this task.
# Maintains the filestructure of the `files` input.

# all params are required to be filled out
params:

  CREDHUB_CLIENT:
  CREDHUB_SECRET:
  CREDHUB_SERVER:
  # - Required
  # - Credentials to talk to credhub server

  CREDHUB_CA_CERT:
  # - Optional
  # - This is only necessary if your Concourse worker
  #   is not already configured to trust the CA used for Credhub.
  # - If more than one CA cert is required (ie the UAA),
  #   the CA certs can be concatenated together and separated by a newline.
  #   For example,
  #   CREDHUB_CA_CERT: |
  #     -----BEGIN CERTIFICATE-----
  #     ...credhub cert...
  #     -----END CERTIFICATE-----
  #     -----BEGIN CERTIFICATE-----
  #     ...UAA cert...
  #     -----END CERTIFICATE-----

  PREFIX:
  # - Required
  # - Prefix flag used by credhub interpolate

  INTERPOLATION_PATHS: '.'
  # - Required
  # - Path the contains the files to read from
  # - This is a space separated list of directories
  #   the paths are all evaluated relative to files/

  SKIP_MISSING: true
  # Optional
  # Change to false to have strict interpolation
  # and fail if params are missing from vars

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -euo pipefail

    # NOTE: The credhub cli does not ignore empty/null environment variables.
    # https://github.com/cloudfoundry-incubator/credhub-cli/issues/68
    if [ -z "$CREDHUB_CA_CERT" ]; then
      unset CREDHUB_CA_CERT
    fi

    credhub --version

    if [ -z "$PREFIX" ]; then
      echo "Please specify a PREFIX. It is required."
      exit 1
    fi

    # $INTERPOLATION_PATHS needs to be globbed to read multiple files
    # shellcheck disable=SC2086
    files=$(cd files && find $INTERPOLATION_PATHS -type f -name '*.yml' -follow)

    if [ "$SKIP_MISSING" == "true" ]; then
      export SKIP_MISSING="--skip-missing"
    else
      export SKIP_MISSING=""
    fi

    for file in $files; do
      echo "interpolating files/$file"
      mkdir -p interpolated-files/"$(dirname "$file")"
      credhub interpolate --prefix "$PREFIX" \
      --file files/"$file" $SKIP_MISSING \
      > interpolated-files/"$file"
    done

This task requires a valid credhub with UAA client and secret. For information on how to set this up, see Secrets Handling

delete-installation

Delete the Ops Manager Installation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information

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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" delete-installation --force

delete-vm

Deletes the Ops Manager VM instantiated by create-vm.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
---
platform: linux

inputs:
- name: state # contains the state for the vm
- name: config # contains the product configuration file
- 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

outputs:
- name: generated-state #contains the updated state file

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.

  STATE_FILE: state.yml
  # - Required
  # - Filepath of the state yaml file
  # - The path is relative to root of the `state` input

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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    vars_files_args=("")
    for vf in ${VARS_FILES}
    do
      vars_files_args+=("--vars-file ${vf}")
    done

    generated_state_path="generated-state/$(basename "$STATE_FILE")"
    cp "state/$STATE_FILE" "$generated_state_path"

    # ${vars_files_args[@] needs to be globbed to split properly
    # shellcheck disable=SC2068
    p-automator delete-vm \
    --state-file "$generated_state_path" \
    --config config/"$OPSMAN_CONFIG_FILE" \
    ${vars_files_args[@]}

This task requires the state file generated create-vm.

The task does specific CLI commands for the deletion of the Ops Manager VM and resources on each IAAS. See below for more information:

AWS

  1. Deletes the VM

Azure

  1. Deletes the VM
  2. Attempts to delete the associated disk
  3. Attempts to delete the associated nic
  4. Attempts to delete the associated image

GCP

  1. Deletes the VM
  2. Attempts to delete the associated image

Openstack

  1. Deletes the VM
  2. Attempts to delete the associated image

vSphere

  1. Deletes the VM

download-product

Ops Manager 2.5

The filename for the artifact downloaded from Ops Manager is changed! If your resources or pipelines have a regex for the Ops Manager filename, you may be affected. (Please see Ops Manager's official notice for more information)

Downloads a product specified in a config file from Pivnet. Optionally, also downloads the latest stemcell for that product.

Downloads are cached, so files are not re-downloaded each time.

Outputs can be persisted to an S3-compatible blobstore using a put to an appropriate resource for later use with the download-product-s3, or used directly as inputs to upload-and-stage-product and upload-stemcell tasks.

This task requires a download-product config file.

If stemcell-iaas is specified in the download-product config file, and the specified product is a .pivotal file, download-product will attempt to download the stemcell for the product. It will retrieve the latest compatible stemcell for the specified IaaS. The valid IaaSs are:

  • aws
  • azure
  • google
  • openstack
  • vsphere

If S3 configuration is present in the download-product config file, the slug and version of the downloaded product file will be prepended in brackets to the filename.
For example:

  • original-pivnet-filenames:

    1
    2
    ops-manager-aws-2.5.0-build.123.yml
    cf-2.5.0-build.45.pivotal
    

  • download-product-filenames if S3 configuration is present:

    1
    2
    [ops-manager,2.5.0]ops-manager-aws-2.5.0-build.123.yml
    [elastic-runtime,2.5.0]cf-2.5.0-build.45.pivotal
    

This is to allow the same config parameters that let us select a file from Pivnet select it again when pulling from S3. Note that the filename will be unchanged if S3 keys are not present in the configuration file. This avoids breaking current pipelines.

When using the s3 resource in concourse

If you are using a regexp in your s3 resource definition that explicitly requires the pivnet filename to be the start of the regex, (i.e., the pattern starts with ^) this won't work when using S3 config. The new file format preserves the original filename, so it is still possible to match on that - but if you need to match from the beginning of the filename, that will have been replaced by the prefix described above.

When specifying Pivotal Application Service-Windows

This task will automatically download and inject the winfs for pas-windows.

When specifying Pivotal Application Service-Windows on Vsphere

This task cannot download the stemcell for pas-windows on vSphere. To build this stemcell manually, please reference the Creating a vSphere Windows Stemcell guide in Pivotal Documentation.

When only downloading from Pivnet

When the download product config only has Pivnet credentials, it will not add the prefix to the downloaded product. For example, example-product.pivotal from Pivnet will be outputed as example-product.pivotal.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
---
platform: linux

inputs:
- name: config # contains download-file config file
- 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

outputs:
- name: downloaded-product
- name: downloaded-stemcell
- name: assign-stemcell-config

caches:
- path: downloaded-files

params:
  CONFIG_FILE: download-config.yml
  # - Required
  # - Filepath to the product configuration yaml file
  # - The path is relative to the root of the `config` input

  VARS_FILES:
  # - Optional
  # - Filepath to the product configuration vars yaml file
  # - The path is relative to root of the task build,
  #   so `vars` and `secrets` can be used.

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    vars_files_args=("")
    for vf in ${VARS_FILES}
    do
      vars_files_args+=("--vars-file ${vf}")
    done

    # ${vars_files_args[@] needs to be globbed to pass through properly
    # shellcheck disable=SC2068
    om download-product \
       --config config/"${CONFIG_FILE}" ${vars_files_args[@]} \
       --output-directory downloaded-files

    { printf "\nReading product details..."; } 2> /dev/null
    # shellcheck disable=SC2068
    product_slug=$(om interpolate \
      --config config/"${CONFIG_FILE}" ${vars_files_args[@]} \
      --path /pivnet-product-slug)

    product_file=$(om interpolate \
      --config downloaded-files/download-file.json \
      --path /product_path)

    stemcell_file=$(om interpolate \
      --config downloaded-files/download-file.json \
      --path /stemcell_path?)

    { printf "\nChecking if product needs winfs injected..."; } 2> /dev/null
    if [ "$product_slug" == "pas-windows" ]; then
      TILE_FILENAME="$(basename "$product_file")"

      # The winfs-injector determines the necessary windows image,
      # and uses the CF-foundation dockerhub repo
      # to pull the appropriate Microsoft-hosted foreign layer.
      winfs-injector \
      --input-tile "$product_file" \
      --output-tile "downloaded-product/${TILE_FILENAME}"
    else
      cp "$product_file" downloaded-product
    fi

    if [ -e "$stemcell_file" ]; then
      cp "$stemcell_file" downloaded-stemcell
    fi

    if [ -e downloaded-files/assign-stemcell.yml ]; then
      cp downloaded-files/assign-stemcell.yml assign-stemcell-config/config.yml
    fi

download-product-s3

Downloads a product specified in a config file from an S3-compatible blobstore. This is useful when retrieving assets in an offline environment.

Downloads are cached, so files are not re-downloaded each time.

This is intended to be used with files downloaded from Pivnet by download-product and then persisted to a blobstore using a put step.

Outputs can be used directly as an input to upload-and-stage-product and upload-stemcell tasks.

This task requires a download-product config file. The same configuration file should be used with both this task and download-product. This ensures that the same file is being captured with both tasks.

The product files uploaded to s3 for download with this task require a specific prefix: [product-slug,semantic-version]. This prefix is added by the download-product task when S3 keys are present in the configuration file. This is the meta information about the product from Pivnet, which is not guaranteed to be in the original filename. This tasks uses the meta information to be able to perform consistent downloads from s3 as defined in the provided download config. For example:

  • original-pivnet-filenames:

    1
    2
    ops-manager-aws-2.5.0-build.123.yml
    cf-2.5.0-build.45.pivotal
    

  • filenames expected by download-product-s3 in a bucket:

    1
    2
    [ops-manager,2.5.0]ops-manager-aws-2.5.0-build.123.yml
    [elastic-runtime,2.5.0]cf-2.5.0-build.45.pivotal
    

When only downloading from Pivnet

When the download product config only has Pivnet credentials, it will not add the prefix to the downloaded product. For example, example-product.pivotal from Pivnet will be outputed as example-product.pivotal.

Info

It's possible to use IAM instance credentials instead of providing S3 creds in the config file. See download-product config file for details.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
---
platform: linux

inputs:
- name: config # contains download-file config file
- 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

outputs:
- name: downloaded-product
- name: downloaded-stemcell
- name: assign-stemcell-config

caches:
- path: downloaded-files

params:
  CONFIG_FILE: download-config.yml
  # - Required
  # - Filepath to the product configuration yaml file
  # - The path is relative to the root of the `config` input

  VARS_FILES:
  # - Optional
  # - Filepath to the product configuration vars yaml file
  # - The path is relative to root of the task build,
  #   so `vars` and `secrets` can be used.

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    vars_files_args=("")
    for vf in ${VARS_FILES}
    do
      vars_files_args+=("--vars-file ${vf}")
    done

    # ${vars_files_args[@] needs to be globbed to pass through properly
    # shellcheck disable=SC2068
    om download-product \
       --config config/"${CONFIG_FILE}" ${vars_files_args[@]} \
       --output-directory downloaded-files \
       --source s3

    product_file=$(om interpolate \
    --config downloaded-files/download-file.json \
    --path /product_path)

    stemcell_file=$(om interpolate \
      --config downloaded-files/download-file.json \
      --path /stemcell_path?)

    cp "$product_file" downloaded-product

    if [ -e "$stemcell_file" ]; then
      cp "$stemcell_file" downloaded-stemcell
    fi

    if [ -e downloaded-files/assign-stemcell.yml ]; then
      cp downloaded-files/assign-stemcell.yml assign-stemcell-config/config.yml
    fi

export-installation

Exports an existing Ops Manager to a file.

This is the first part of the backup/restore and upgrade lifecycle processes. This task is used on a fully installed and healthy Ops Manager to export settings to an upgraded version of Ops Manager.

To use with non-versioned blobstore, you can override INSTALLATION_FILE param to include $timestamp, then the generated installation file will include a sortable timestamp in the filename.

example:

1
2
params:
  INSTALLATION_FILE: installation-$timestamp.zip

Info

The timestamp is generated using the time on concourse worker. If the time is different on different workers, the generated timestamp may fail to sort correctly. Changing the time or timezone on workers might interfere with ordering.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information

outputs:
- name: installation # will contain the exported installation

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

  INSTALLATION_FILE: installation-$timestamp.zip
  # - Required
  # - Filepath of the installation ZIP file
  # - The path is relative to root of the `installation` output
  # - if the filename includes "$timestamp",
  #   for example "installation-$timestamp.zip",
  #   the final filename will include the current timestamp.
  #   - this is necessary if using an "S3 compatible" blobstore
  #     that doesn't support versioned blobs
  #   - timestamped filenames will need to be represented
  #     with a glob-style wildcard in the `upgrade-opsman` task configuration
  #     (the default will work with the example provided above).

run:
  path: bash
  args:
  - -c
  - |
    cat /var/version && echo ""
    set -eux

    timestamp="$(date '+%Y%m%d.%-H%M.%S+%Z')"
    export timestamp

    # '$timestamp' must be a literal, because envsubst uses it as a filter
    # this allows us to avoid accidentally interpolating anything else.
    # shellcheck disable=SC2016
    OUTPUT_FILE_NAME="$(echo "$INSTALLATION_FILE" | envsubst '$timestamp')"

    om --env env/"${ENV_FILE}" export-installation \
       --output-file installation/"$OUTPUT_FILE_NAME"

Warning

It is recommended to persist the zip file exported from export-installation to an external file store (eg S3) on a regular basis. The exported installation can restore the Ops Manager to a working state if it is non-functional.

import-installation

Imports a previously exported installation to Ops Manager.

This is a part of the backup/restore and upgrade lifecycle processes. This task is used after an installation has been exported and a new Ops Manager has been deployed, but before the new Ops Manager is configured.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
---
platform: linux

inputs:
- name: env # contains the environment information about the OpsMan
- name: installation # contains the installation to be imported

params:
  ENV_FILE: env.yml
  # - Required
  # - Filepath of the environment config YAML
  # - The path is relative to root of the `env` input
  # - The env file _must_ contain the `decryption-passphrase`
  #   while it's optional for other tasks, this one requires it.

  INSTALLATION_FILE: installation*.zip
  # - Required
  # - Filepath of the installation ZIP file
  # - The filepath provided can be wildcard expanded.
  # - The path is relative to root of the `installation` input

run:
  path: bash
  args:
  - -c
  - |
    cat /var/version && echo ""
    set -eux

    # INSTALLATION_FILE needs to be globbed
    # shellcheck disable=SC2086
    om --env env/"${ENV_FILE}" import-installation \
       --installation installation/$INSTALLATION_FILE

make-git-commit

Copies a single file into a repo and makes a commit. Useful for persisting the state output of tasks that manage the vm, such as:

Also useful for persisting the configuration output from:

Info

This commits all changes present in the repo used for the repository input, in addition to copying in a single file.

Info

This does not perform a git push! You will need to put the output of this task to a git resource to persist it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
---
platform: linux

inputs:
  - name: repository
  # - This must be an initialized git repository.
  # - Note that any changes present in this input
  #   will be committed along with the file copied in
  #   by this task.
  - name: file-source
  # - This is the input folder containing the file to be committed.
  #   Typically, this will from some other task
  #   with an output that needs to be persisted.
outputs:
  - name: repository-commit

params:
  FILE_SOURCE_PATH:
  # - Required
  # - Filepath to be copied into the git repo
  #   before a commit is created
  # - Relative to the root of the `file-source` input

  FILE_DESTINATION_PATH:
  # - Required
  # - Filepath to write the file specified by FILE_SOURCE_PATH
  # - Relative to the root of the `repository` input

  GIT_AUTHOR_NAME:
  # - Required
  # - Used to configure the human-readable
  #   name in the `author` field of the commit

  GIT_AUTHOR_EMAIL:
  # - Required
  # - Used to configure the email address
  #   in the `author` field of the commit

  COMMIT_MESSAGE:
  # - Required
  # - Specify a commit message to be used
  #   for all commits made by this task.

run:
  path: bash
  args:
    - "-c"
    - |
      cat /var/version && echo ""
      set -eu
      git config --global user.email "$GIT_AUTHOR_EMAIL"
      git config --global user.name "$GIT_AUTHOR_NAME"

      git clone repository repository-commit

      cp file-source/"$FILE_SOURCE_PATH" \
         repository-commit/"$FILE_DESTINATION_PATH"
      cd repository-commit
      git add -A
      git commit -m "$COMMIT_MESSAGE" --allow-empty

stage-product

Staged a product to the Ops Manager specified in the config file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
---
platform: linux

inputs:
- name: product # contains the product file to be uploaded and staged
- name: env # contains the env file with target OpsMan Information

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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    product_name="$(om tile-metadata \
      --product-path product/*.pivotal \
      --product-name)"
    product_version="$(om tile-metadata \
      --product-path product/*.pivotal \
      --product-version)"

    om --env env/"${ENV_FILE}" stage-product \
       --product-name "$product_name" \
       --product-version "$product_version"

staged-config

Downloads the configuration for a product from Ops Manager.

Not to be confused with Ops Manager's built-in export, which puts all deployed products and configurations into a single file, intended for import as part of backup/restore and upgrade lifecycle processes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information

outputs:
- name: generated-config # will contain the staged product config

params:
  PRODUCT_NAME:
  # - Required
  # - The name of the product config to be exported

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

  SUBSTITUTE_CREDENTIALS_WITH_PLACEHOLDERS: true
  # - Optional
  # - Replace credentials with interpolatable variable names
  # - If set to false, **literal credentials** will be included in the output

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    flag=$(if "$SUBSTITUTE_CREDENTIALS_WITH_PLACEHOLDERS";
           then echo '--include-placeholders';
           else echo '--include-credentials';
           fi
          )

    om --env env/"${ENV_FILE}" staged-config \
       --product-name "$PRODUCT_NAME" \
       "$flag" > generated-config/"$PRODUCT_NAME".yml

staged-director-config

Ops Manager 2.5

The filename for the artifact downloaded from Ops Manager is changed! If your resources or pipelines have a regex for the Ops Manager filename, you may be affected. (Please see Ops Manager's official notice for more information)

Downloads configuration for the BOSH director from Ops Manager.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information

outputs:
- name: generated-config # will contain the staged product config

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

run:
  path: bash
  args:
  - -c
  - |
    cat /var/version && echo ""
    set -eux
    om --env env/"${ENV_FILE}" staged-director-config \
       --include-placeholders > generated-config/director.yml

The configuration is exported to the generated-config output. It does not extract credentials from Ops Manager and replaced them all with YAML interpolation (()) placeholders. This is to ensure that credentials are never written to disk. The credentials need to be provided from an external configuration when invoking configure-director.

Info

staged-director-config will not be able to grab all sensitive fields in your Ops Manager installation (for example: vcenter_username and vcenter_password if using vsphere). To find these missing fields, please refer to the Ops Manager API Documentation

test

An example task to ensure the assets and docker image are setup correctly in your concourse pipeline.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
---
platform: linux

run:
  path: bash
  args:
  - "-c"
  - |
    echo "Platform Automation for PCF version:"
    cat /var/version && echo ""

    printf "\\np-automator version:"
    p-automator -v

    printf "\\nom version:"
    om -v

    set -eux
    p-automator --help
    om --help
    { echo "Successfully validated tasks and image!"; } 2> /dev/null

test-interpolate

An example task to ensure that all required vars are present when interpolating into a base file. For more instruction on this topic, see the variables section

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
---
platform: linux

inputs:
- name: config # contains the base configuration file
- name: vars # variable files to be made available
  optional: true

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

  CONFIG_FILE: base.yml
  # - Required
  # - Filepath to the base yaml file to interpolate from
  # - The path is relative to root of the task build

  SKIP_MISSING: true
  # - Optional
  # - Change to false to have strict interpolation
  #   and fail if params are missing from vars

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    vars_files_args=("")
    for vf in ${VARS_FILES}
    do
      vars_files_args+=("--vars-file ${vf}")
    done

    if [ "$SKIP_MISSING" ]; then
      export SKIP_MISSING="--skip-missing"
    else
      export SKIP_MISSING=""
    fi

    # ${vars_files_args[@] needs to be globbed to pass through properly
    # shellcheck disable=SC2068
    om interpolate --config "config/$CONFIG_FILE" "$SKIP_MISSING" ${vars_files_args[@]}

upgrade-opsman

Upgrades an existing Ops Manager to a new given Ops Manager version

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
---
platform: linux

inputs:
- name: state # contains the state for the vm
- name: config # contains the OpsMan configuration file
- name: image # contains the image file to be installed
- name: installation # contains the installation to be imported
- name: env # contains the environment information for OpsMan
- 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 stored securely
  optional: true

outputs:
- name: generated-state #contains the updated state file

params:
  VARS_FILES:
  # - Optional
  # - space-seperated array of filepaths to YAML vars files
  #   to be loaded with the OPSMAN_CONFIG_FILE
  # - relative to root of the task build,
  #   so both `vars` and `secrets` can be used.

  ENV_FILE: env.yml
  # - Required
  # - filepath of the env config YAML
  # - relative to root of the `env` input

  OPSMAN_CONFIG_FILE: opsman.yml
  # - Required
  # - filepath of the opsman config YAML
  # - relative to root of the `config` input

  STATE_FILE: state.yml
  # - Required
  # - filepath of the state YAML file
  # - relative to root of the `state` input

  INSTALLATION_FILE: installation*.zip
  # - Required
  # - filepath of the installation ZIP file
  # - can be wildcard expanded
  # - relative to root of the `installation` input

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    p-automator -v
    set -eux

    vars_files_args=("")
    for vf in ${VARS_FILES}
    do
      vars_files_args+=("--vars-file ${vf}")
    done

    generated_state_path="generated-state/$(basename "$STATE_FILE")"
    cp "state/$STATE_FILE" "$generated_state_path"

    # ${vars_files_args[@] needs to be globbed to split properly (SC2068)
    # INSTALLATION_FILE needs to be globbed (SC2086)
    # shellcheck disable=SC2068,SC2086
    p-automator upgrade-opsman \
    --config config/"${OPSMAN_CONFIG_FILE}" \
    --env-file env/"${ENV_FILE}" \
    --image-file "$(find image/*.{yml,ova,raw} | head -n1)"  \
    --state-file "$generated_state_path" \
    --installation installation/$INSTALLATION_FILE \
    ${vars_files_args[@]}

For more information about this task and how it works, see the upgrade page.

upload-and-stage-product

Uploads and stages product to the Ops Manager specified in the config file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
---
platform: linux

inputs:
- name: product # contains the product file to be uploaded and staged
- name: env # contains the env file with target OpsMan Information
- name: config # contains the product configuration file
  optional: true

params:
  CONFIG_FILE:
  # - Optional
  # - Path to the config file for the product
  # - Relative to the root of the config input
  # - If empty, no config will be used; version and sha256 will not be checked
  # - Example config:
  # ---
  # product-version: 1.2.3-build.4
  # sha256: 6daededd8fb4c341d0cd437a669d732d2fde62cb89716498e6b16f34607a1498

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

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    if [ -z "$CONFIG_FILE" ]; then
        om --env env/"${ENV_FILE}" upload-product \
           --product product/*.pivotal
    else
      om --env env/"${ENV_FILE}" upload-product \
         --product product/*.pivotal --config "config/$CONFIG_FILE"
    fi

    product_name="$(om tile-metadata \
      --product-path product/*.pivotal \
      --product-name)"
    product_version="$(om tile-metadata \
      --product-path product/*.pivotal \
      --product-version)"

    om --env env/"${ENV_FILE}" stage-product \
       --product-name "$product_name" \
       --product-version "$product_version"

upload-product

Uploads a product to the Ops Manager specified in the config file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
---
platform: linux

inputs:
- name: product # contains the product file to be uploaded and staged
- name: env # contains the env file with target OpsMan Information
- name: config # contains the product configuration file
  optional: true

params:
  CONFIG_FILE:
  # - Optional
  # - Path to the config file for the product
  # - Relative to the root of the `config` input
  # - If empty, no config will be used; version and sha256 will not be checked
  # - Example config:
  # ---
  # product-version: 1.2.3-build.4
  # shasum: 6daededd8fb4c341d0cd437a669d732d2fde62cb89716498e6b16f34607a1498
  ENV_FILE: env.yml
  # - Required
  # - Filepath of the env config YAML
  # - Relative to root of the `env` input

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    export OPTIONAL_CONFIG_FLAG=""
    if [ -n "$CONFIG_FILE" ]; then
      export OPTIONAL_CONFIG_FLAG="--config config/$CONFIG_FILE"
    fi
    # shellcheck disable=SC2086
    om --env env/"${ENV_FILE}" upload-product \
       --product product/*.pivotal \
       $OPTIONAL_CONFIG_FLAG

upload-stemcell

Uploads a stemcell to Ops Manager.

Note that the filename of the stemcell must be exactly as downloaded from Pivnet. Ops Manager parses this filename to determine the version and OS of the stemcell.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
---
platform: linux

inputs:
- name: env # contains the env file with target OpsMan Information
- name: stemcell # contains the stemcell tarball
# - The stemcell filename is important and must be preserved.
#   if using the bosh.io concourse resource,
#   set `params.preserve_filename: true` on your GET.

params:
  CONFIG_FILE:
  # - Optional
  # - Path to the config file for the product
  # - Relative to the root of the `config` input
  # - If empty, no config will be used; version and sha256 will not be checked
  # - Example config:
  # ---
  # shasum: 6daededd8fb4c341d0cd437a669d732d2fde62cb89716498e6b16f34607a1498

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

  FLOATING_STEMCELL: true
  # - Optional
  # - Assigns the stemcell to all compatible products
  # - If false, a user is required to run the assign-stemcell task

run:
  path: bash
  args:
  - "-c"
  - |
    cat /var/version && echo ""
    set -eux

    export OPTIONAL_CONFIG_FLAG=""
    if [ -n "$CONFIG_FILE" ]; then
      export OPTIONAL_CONFIG_FLAG="--config config/$CONFIG_FILE"
    fi
    # shellcheck disable=SC2086
    om --env env/"${ENV_FILE}" upload-stemcell \
       --floating="$FLOATING_STEMCELL" \
       --stemcell "$PWD"/stemcell/*.tgz \
       $OPTIONAL_CONFIG_FLAG