Edit this page on GitHub

Home > docs > plugins > Terraform Task

Terraform Task

Concord supports interaction with the infrastructure provisioning tool Terraform with the terraform task as part of any flow.

Usage

To be able to use the task in a Concord flow, it must be added as a dependency:

configuration:
  dependencies:
  - mvn://com.walmartlabs.concord.plugins:terraform-task:1.32.3

This adds the task to the classpath and allows you to invoke it in any flow.

The task requires the process to run as a part of a Concord project.

Common Parameters

  • action - (mandatory) action to perform:
    • plan - plan the changes
    • apply - apply the changes with or without using a previously created plan file
    • destroy -destroy an environment
    • output - save the output variables
  • backend - type of a state backend to use:
    • concord - (default) use the backend provided by Concord
    • none - use the default file-based backend or the backend configuration provided by the user
    • remote - run on on Terraform Cloud or Terraform Enterprise
  • debug - boolean value, if true the plugin logs additional debug information
  • extraEnv - key-value pairs, extra environment variables provided to the terraform process
  • extraVars - variables provided to the terraform process
  • ignoreErrors - boolean value, if true any errors that occur during the execution will be ignored and stored in the result variable
  • ignoreLocalBinary - boolean value, if true the plugin won’t use a terraform binary from $PATH. See the Terraform Version section for more details
  • stateId - string value, the name of a state file to use. See the State Backends section for more details
  • toolUrl - URL to a specific terraform bundle or version (.zip format). See the Terraform Version section for more details
  • toolVersion - Terraform version to use, mutually exclusive with toolUrl. See the Terraform Version section for more details
  • varFiles - list of files to add as -var-file.

Planning the Changes

The plan action executes terraform plan in the process’ working directory or in a directory specified in dir parameter:

# run `terraform plan` in `${workDir}`
- task: terraform
  in:
    action: plan

# run `terraform plan` to generate a destroy plan
- task: terraform
  in:
    action: plan
    destroy: true

# run `terraform plan` in a specific directory
- task: terraform
  in:
    action: plan
    dir: "myTFStuff"

The plugin automatically creates the necessary backend configuration and runs terraform init when necessary.

Parameters:

  • dir - string value, path to a directory with *.tf files. The path must be relative to the process’ ${workDir};
  • plan - string value, path to a previosly created plan file. The path must be relative to the process’ ${workDir};
  • destroy - boolean value, if true destroy plan is generated. By default, apply plan is generated;
  • gitSsh - see GIT modules.

The output is stored in a result variable that has the following structure:

  • ok - boolean value, true if the execution is successful;
  • hasChanges - boolean value, true if terraform plan detected any changes in the enviroment;
  • output - string value, output of terraform plan (stdout);
  • planPath - string value, path to the created plan file. The plugin stored such files as process attachments so they "survive" suspending/resuming the process or restoring from a checkpoint. The path is relative to the process’ ${workDir};
  • error - string value, error of the last terraform execution (stderr).

The execution’s output (stored as ${result.output}) can be used to output the plan into the process’ log, used in an approval form, Slack notification, etc.

Applying the Changes

The apply action executes terraform apply in the process’ working directory, in a directory specified in dir parameter or using a previously created plan file:

Run terraform apply in ${workDir}:

- task: terraform
  in:
    action: apply

Run terraform apply in a specific directory

- task: terraform
  in:
    action: apply
    dir: "myTFStuff"

Run terraform apply using a plan file

- task: terraform
  in:
    action: apply
    dir: "myTFStuff"
    plan: "${result.planPath}" # created by previously executed `plan` action

As with the plan action, the plugin automatically runs terraform init when necessary.

Parameters:

  • dir - string value, path to a directory with *.tf files. The path must be relative to the process’ ${workDir};
  • plan - string value, path to a previosly created plan file. The path must be relative to the process’ ${workDir}. When using plan, the original dir must be specified as well;
  • gitSsh - see GIT modules.
  • saveOutput - boolean value, if true the terraform output command will be automatically executed after the apply is completed and the result will be saved in the result variable.

The action’s output is stored in a result variable that has the following structure:

  • ok - boolean value, true if the execution is successful;
  • output - string value, output of terraform apply (stdout);
  • error - string value, error of the last terraform execution (stderr);
  • data - map (dict) value, contains the output values. Only if saveOutput is true.

Destroying Infrastructure

The destroy action executes terraform destroy in the process’ working directory or in a directory specified in dir parameter. This is provided in addition to applying a plan generated with the destroy argument which is problematic with some modules and providers.

When used with the remote backend the CONFIRM_DESTROY environment variable must be created in the relavent Cloud/Enterprise workspace.

Run terraform destroy in ${workDir}:

- task: terraform
  in:
    action: destroy
    extraEnv: 
      CONFIRM_DESTROY: 1

Run terraform destroy in a specific directory

- task: terraform
  in:
    action: destroy 
    dir: "myTFStuff"
    extraEnv: 
      CONFIRM_DESTROY: 1

Input Variables

Input variables can be specified using the extraVars parameter:

- task: terraform
  in:
    action: plan
    extraVars:
      aVar: "someValue"
      nestedVar:
        x: 123

The extraVars parameter expects regular java.util.Map<String, Object> objects and supports all JSON-compatible data structures (nested objects, lists, etc).

Specifying extraVars is an equivalent of running terraform [action] -var-file=/path/to/file.json.

Environment Variables

OS-level environment variables can be specified using extraEnv parameter:

- task: terraform
  in:
    action: plan
    extraEnv:
      HTTPS_PROXY: http://proxy.example.com
      TF_LOG: TRACE

External Variable Files

Paths to an external files with variables can be added to plan or apply actions using varFiles parameter:

- task: terraform
  in:
    action: apply
    varFiles:
      - "path/to/my-vars.json"
      - "another/path/to/other/vars.json"

Paths must be relative to the current process’ ${workDir}.

Output Variables

There are two ways how output values can be saved - using the output action or by adding saveOutput to the apply action parameters:

- task: terraform
  in:
    action: output
    dir: "myTFStuff" # optional path to *.tf files

# all output values will be saved as a ${result.data} variable
- log: "${result.data}" 
- task: terraform
  in:
    action: apply
    saveOutput: true
    # the rest of the parameters are the same as with the regular `apply`

- log: "${result.data}"

State Backends

Concord uses its own state backend by default, but any of the standard Terraform state backends can be configured for use.

When using the Concord state backend, on by default, the state is stored in Concord’s internal JSON store using the tfState-${projectName}_${repositoryName} template for the name. If you want to use a custom name for storing the state, the name can be overridden using the stateId parameter:

- task: terraform
  in:
    action: plan
    stateId: "myInventory"

To completely remove the state, you can use the JSON Store API.

Concord also supports the use of all Terraform’s backend types. To instruct the plugin to use the s3 backend for storing state, use something like the following:

- task: terraform
  in:
    backend:
      s3:
        bucket: "tfstate"
        key: "project"
        region: "us-west-2"
        encrypt: true
        dynamodb_table: "project-lock"

You can also disable the use of all state backends by specifying a backend of none. This is effectively the same as the default command line behavior that uses the filesystem to store state in the terraform.tfstate. To instruct the plugin to use no backend for storing state, use something like the following:

- task: terraform
  in:
    action: plan
    backend: none

Terraform Enterprise / Cloud

Remote is a special backend that runs jobs on Terraform Enterprise (TFE) or Terraform Cloud. Concord will create .terraformrc and *.override.tfvars.json configurations to access the module registry and trigger execution.

It is preferrable to configure a Terraform Version in the TFE / Cloud workspace (workspace->settings->general->Terraform Version) and provide a matching toolUrl so concord and TFE use the same executable and bundled modules.

- task: terraform
  in:
    action: apply
    toolUrl: https://releases.hashicorp.com/terraform/tfe-configured-version/terraform_tfe-version_linux_amd64.zip
    backend:
      remote:
        hostname: "app.terraform.io"
        organization:  "ExampleOrg"
        token: "Use_A_Crypto_Task_To_Protect_Token"
        workspaces: 
          name: "ExampleWorkspace"

GIT Modules

Using Generic GIT repositories as modules may require SSH key authentication. The plugin provides a couple ways to configure the keys.

Using private key files directly:

- task: terraform
  in:
    gitSsh:
      privateKeys:
        - "relative/path/to/a/private/key.file"
        - "another/private/key.file"

The path must be relative to the process ${workDir}.

An alternative (and recommended) way is to use Concord Secrets:

- task: terraform
  in:
    gitSsh:
      secrets:
        - org: "myOrg" # optional
          secretName: "myKeyPairSecret"
          password: "myS3cr3t" # optional

Multiple private key files and Concord Secrets can be used simultaneously.

When running separate plan and apply actions, only the plan part requires the key configuration.

Terraform Version

The plugin tries to find a terraform binary using the following methods:

  • looks for ${workDir}/.terraform/terraform first;
  • next, if toolUrl is provided, the plugin downloads the specified URL and extracts it into ${workDir}/.terraform directory. The terraform binary should be in the top-level directory of the archive;
  • looks for terraform in $PATH unless ignoreLocalBinary: true is specified;
  • downloads the binary’s archive from the standard location (releases.hashicorp.com). In this case, the toolVersion parameter can be used.

Examples