terraformterragrunt

Convert .env file to object list using Terraform


Using Terragrunt, I am trying to provision a Terraform module which has the following variable:

variable "param_list" {
  type = list(object({
    name  = string
    type  = string
    value = string
  }))
  description = "List of environment variables."
}

The application that is responsible for provisioning the module contains .env files

.env       -- Baseline
.env.local -- Local environment
.env.qa    -- All QA environments
.env.qa.qa1-- All QA1 specific environments

These files look like:

PRODUCTION="false"
APP_URL="app.localhost.com"
SOME_KEY="abc=123"
...

Any environment variable in baseline is applied to all environments. These can be overwritten by specific configurations. For example, if the above snippet was for baseline and .env.qa contained:

APP_URL="app.qa.com"

Then the APP_URL should be app.qa.com for all qa environments. If it did not contain APP_URL it would just use "app.localhost.com".

When Terragrunt is called the environment type (e.g. qa) and the specific environment (e.g. qa1) are set in locals variables:

locals {
  env_name = get_env("ENV_NAME")
  env_type = trim(local.env_name, "1234567890")
}

How do I convert the .env file to a list of objects using Terraform and supply it as a param for the module? This should happen in a terragrunt.hcl file. If possible, I would rather contain the logic to this file and not use a bash script to convert the file beforehand.

Note: The terraform module pushes the param_list to the AWS param store. The name is the key (PRODUCTION) and the value would be (false). Type will always be string for this case (secure strings will be handled separately for now).


Solution

  • I was able to achieve this via this function incase anyone else is trying to do something similar. This only creates a map as opposed to a list of objects however could be converted. I updated the module to accept a map since I am not using secure strings for this at the moment so type will always be the same.

    locals {      
          env_files = [
            "${local.env_files_dir}.env.tfvars",
            "${local.env_files_dir}.env.${local.env_type}.tfvars",
            "${local.env_files_dir}.env.${local.env_type}.${local.env_name}.tfvars"
          ]
          param_list = merge([
            for filename in local.env_files : {
              for param in [
                for param in split("\n", file(filename)) :
                regex("^([^=]+)=\"(.*)\"|([^\"].*)$", param) if trimspace(param) != ""
              ] :
              param[0] => replace(coalesce(param[1], param[2], "empty-value"), "<<env>>", "${local.env_name}")
            }
            if fileexists(filename)
          ]...)
    }