Variables usage is all but clear

Copied from GitHub Issue: https://github.com/boltops-tools/terraspace/issues/273

Hello,
the usage of env and terrspace vars in the application needs clarity:
For example:

  1. How can env var be used in stack tf files?
  2. How can env variable be used in terraform.tfvars file?
  3. How terraspace specific variables can be accessed in stacks tf files and tfvars?
  4. What is the rule for using a single vs double quote symbol when referencing a variable?

Here are the examples:
config/app.rb:

Terraspace.configure do |config|
  config.cloud.project = "InfraIAC" 
end

stack/demo/terraform.tfvars:

aws_region = "<%= expansion(':ENV') %>"
client_abbr = "<%= expansion(":CLIENT_ABBR") %>"
project_abbr = "<%= expansion(':APP') %>"

cached version:

aws_region = "dev"
client_abbr = ":CLIENT_ABBR"
project_abbr = ""
  1. Consistency in accessing vars:
    Can’t locate at the moment, but in some parts of the documentation access to vars is:
ENV['FOO']

at others :

 "<%= expansion(':ENV') %>"

when to use what is not obvious and not clearly documented.

Not a documentation, but a usage impediment:

the variables used in the code (.tf, rb and tfvars ) and their values should be printed during the “plan” stage, so that a user can inspect their value or absence of it.

Think understanding a little bit about how Terraspace uses Ruby for building tf files will help with a lot of these questions. :+1: Hopefully this helps :grinning_face_with_smiling_eyes:

How Terraspace Works Summary

  • Terraspace pre-processes tf files like main.tf and allows you to use ERB (Evaluated Ruby) to compile down and generate different tf files.
  • Ruby is called as part of the processing.
  • In the Ruby world, you can access environment variables generally with <%= ENV['FOO'] %>. This is a pure Ruby thing. In node, it’s process.env.FOO. In python, it’s os.environ['FOO'], In golang, it’s os.Getenv("FOO").
  • Terraspace also adds some helper methods that allow you to access the env variables in a more convenient and pretty manner. This is a Terraspace thing. IE: "<%= expansion(':FOO') %>"

Answers

RE: 1. How can env var be used in stack tf files?

By using ERB. You can access it with pure Ruby via <%= ENV['FOO'] %>. Or use a terraspace helper like expansion, IE: "<%= expansion(':FOO') %>" The terraspace expansion method extracts and expands out the string and will replace it if an env variable is found. Source code: https://github.com/boltops-tools/terraspace/blob/16af51ac22c5fc5e20202b5786994ad392cb9726/lib/terraspace/plugin/expander/interface.rb#L84 This feature was added in terraspace v2. https://github.com/boltops-tools/terraspace/pull/239 The expansion method is a little smarter and can expand more than env vars, IE TS_ENV and ENV both work. In one of your examples the APP is blank because it needs to be set, IE TS_APP=demo More docs App and Role Layering - Terraspace

RE: 2. How can env variable be used in terraform.tfvars file?

Same as #1.

RE: 3. How terraspace specific variables can be accessed in stacks tf files and tfvars?

Same as #1.

RE: 4. What is the rule for using a single vs double quote symbol when referencing a variable?

Anything within the ERB callout, IE: <%= ... %> is evaluated as Ruby. Believe that some other languages, like golang, only support double quotes for String. With Ruby, you can use either single or double quote notation

$ irb
3.1.3 :001 > "string1"
 => "string1" 
3.1.3 :002 > 'string2'
 => "string2" 
3.1.3 :003 > 

With Ruby, strings within single quotes do not also perform Ruby String interpolation. They are literal strings. Some say it’s faster with single quotes, but don’t think it really matters for most things. The docs use single quotes to make it look a little prettier in some cases. IE: "<%= expansion(':ENV') %>" vs "<%= expansion(":ENV") %>". The double quotes outside and within the ERB seem to confuse some folks.

RE: Not a documentation, but a usage impediment: the variables used in the code (.tf, rb and tfvars ) and their values should be printed during the “plan” stage, so that a user can inspect their value or absence of it.

The terraform plan stage happens after terraspace has built/compiled/generated the terraform code from ERB. Feel it’s a different beast and think it makes more sense to build the files and then inspect them on the file system. Example:

terraspace build demo
ls .terraspace-cache/us-west-2/dev/stacks/demo/