Overriding environment variables per env

Hi,

I’m attempting to build infrastructure described with terraform. My terraform configuration builds for multiple environments, for the case of this explination lets say: dev and prod.

So as mentioned, i have a single terraform configuration, into which I pass variables which determine the difference between a deployed environment. Within my terraform configuration I have a variables.tf which, for example, declares a variable:

variable "rds_connect_string" {}

I would like to set the value of this variable depending on the environment I’m deploying to, so within my circleci environment variables page (in the ui) I’ve created two environment variables:
RDS_CONNECTION_STRING_DEV=xxxxxxx
and
RDS_CONNECTION_STRING_PROD=xxxxxx

Then in my .circleci/config.yml I’m attempting to map them like this:

version: 2.1
orbs:
  terraform: circleci/terraform@3.1
jobs:
  dev:
    executor: terraform/default
    environment:
      TF_VAR_rds_connection_string: $RDS_CONNECTION_STRING_DEV   <---- here
    steps:
      - checkout
      - terraform/fmt:
          path: .
      - terraform/validate:
          path: .
      - terraform/init:
          backend_config: "bucket=$BUCKET,key=$SERVICE_NAME/dev/state.tfstate,region=$REGION"
          path: .
      - terraform/plan:
          backend_config: "bucket=$BUCKET,key=$SERVICE_NAME/dev/state.tfstate,region=$REGION"
          path: .
      - terraform/apply:
          backend_config: "bucket=$BUCKET,key=$SERVICE_NAME/dev/state.tfstate,region=$REGION"
          path: .
  prod:
    executor: terraform/default
    environment:
      TF_VAR_rds_connection_string: $RDS_CONNECTION_STRING_PROD <--- here
    steps:
      - checkout
      - terraform/fmt:
          path: .
      - terraform/validate:
          path: .
      - terraform/init:
          backend_config: "bucket=$BUCKET,key=$SERVICE_NAME/dev/state.tfstate,region=$REGION"
          path: .
      - terraform/plan:
          backend_config: "bucket=$BUCKET,key=$SERVICE_NAME/dev/state.tfstate,region=$REGION"
          path: .
      - terraform/apply:
          backend_config: "bucket=$BUCKET,key=$SERVICE_NAME/dev/state.tfstate,region=$REGION"
          path: .

note the lines:
TF_VAR_rds_connection_string: $RDS_CONNECTION_STRING_DEV
and
TF_VAR_rds_connection_string: $RDS_CONNECTION_STRING_PROD

My intent here is to override the variable terraform expects by setting TF_VAR_rds_connection_string seperatly for each environment.

However, when I run my pipeline, terraform complains with something similar to this:

var.rds_connection_string is "$RDS_CONNECTION_STRING_DEV"

Which suggests to me circleci isn’t replacing the $RDS_CONNECTION_STRING_DEV environment variable with the actual value.

I can achieve this functionality by simply replacing $RDS_CONNECTION_STRING_DEV with the actual value rather than the environment variable reference but in doing this I’m forced to store a secure string in version control (this is not an option).

Is my syntax correct? Is this even possible? Or is there a better way to achieve this?

Thanks in advance

-Mark

Sadly, environment variables and parameters do not work as you would expect so when you pass the name of an environment variable as a parameter it is the name that is passed, not the value of the parameter.

There are a number of workarounds that get listed here depending on the exact situation, with the following one being the most likely to work for you.

 https://circleci.com/docs/2.0/using-dynamic-configuration

You basically write a yml file from within bash which allows the environment variables to be expanded out to their correct value and then the yml file can then be called. While the provided example shows the writing of the yml file, a better bet is to have a template that can be copied and then use substitution to insert the correct values.

You are not alone in finding this limitation an issue as it is often raised in the forums.