Skip to content

Instantly share code, notes, and snippets.

@farhad-taran
Last active December 23, 2023 11:21
Show Gist options
  • Save farhad-taran/2f79a5a2129f514de0a6aed63509ebe4 to your computer and use it in GitHub Desktop.
Save farhad-taran/2f79a5a2129f514de0a6aed63509ebe4 to your computer and use it in GitHub Desktop.
Parsing a single tfvars file into lambda resource and nodejs app

I dislike having multiple copies of the same env file, for example when trying to run some integration tests I needed to access the same env variables that I had to load into a lambda resource in terraform.

to make this easier I place the app related env variables in a tfvars file and loop and load them into the lambda env variables like so:

locals {
  node-env     = "test"
  app_env_vars = { 
    for line in split("\n", file("app.tfvars")):
      trimspace(split("=", line)[0]) => trimspace(split("=", line)[1])
      if strcontains(line, "=")
  }
}

esource "aws_lambda_function" "test_lambda" {

  ......

  environment {
    variables = tomap(merge(
    {
      LOG_LEVEL               = 20
      ENV                     = local.node-env
      NODE_ENV                = local.node-env
    },
    local.app_env_vars
  ))
  }
}

and on the app side or in the npm scripts, I need to trim the tfvars from any spaces and load them into the bash env:

export $(cat infra/app.tfvars | tr -d '[:blank:]')

or you could load them up as part of app startup:

export const isProduction = () => {
  return process.env.NODE_ENV === "production";
};

export function loadEnv(): Record<string, string> {
  return isProduction() ? process.env : parseVarsFile("infra/app.tfvars");
}

function parseVarsFile(fileLocation: string): Record<string, string> {
  const vars = {};
  readFileSync(fileLocation, "utf-8")
    .split(/\r?\n/)
    .forEach(function (line) {
      if (!/\S/.test(line)) return; //skip if line is empty
      const parts = line.split("=");
      const key = parts[0].trim();
      if (key.startsWith("//") || key.startsWith("#")) return; // skip if line is commented
      const value = parts[1]
        .replace(/( |\t)+\#.*/g, "") // replace any comments or spaces after the value
        .replace(/( |\t)+\/{2}.*/g, "") // replace any comments or spaces after the value
        .trim(); // replace all spaces before and after final value
      vars[key] = value;
    });
  return vars;
}

example tfvars:

LOG_LEVEL        = 20 # log debug - change to 30 info to reduce noise once stable
YUM_USERNAME_KEY = order_status_lambda/yum_api_username
YUM_PASSWORD_KEY = order_status_lambda/yum_api_password
SECRETS_CACHE_DURATION_SECS = 900
APP_AWS_REGION=eu-central-1
STUB=false // used for integration tests in CI and locally to bypass stubbing of external services
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment