The following is an example Stacks directory structure as full as it can get, with annotations as to the specific freedoms/constraints you get.
|-- environments/ # The environments folder must be named after the value of the STACKS_ENVIRONMENTS_DIR environment variable, which defaults to "environments".
| `-- production/ # Environment names must follow the ^[a-zA-Z0-9-]{,254}$ regular expression.
| `-- env.tfvars # Environments can only have one env.tfvars file to define environment-specific variables.
`-- stacks/ # The stacks folder must be named after the value of the STACKS_STACKS_DIR environment variable, which defaults to "stacks".
|-- ec2/ # Stack names must follow the ^[a-zA-Z0-9-]{,254}$ regular expression.
| |-- base/ # The stack base folder must be named after the value of the STACKS_BASE_DIR environment variable, which defaults to "base".
| | |-- backend.tf # The base folder contains a Terraform root module, you can use Jinja on any one of its *.tf files.
| | `-- modules/... # You can also have folders here for stuff like local modules, but those don't get Jinja support unless added to the var.stacks_jinja_enabled_modules special variable.
| |-- layers/ # The layers folder must be named after the value of the STACKS_LAYERS_DIR environment variable, which defaults to "layers".
| | |-- production/ # Stack layers must be named after an existing environment. Stacks must run within one of these layer directories.
| | | |-- layer.tfvars # Layers can contain any number of *.tfvars files, which are sorted alphabetically for preference (i.e. a.tfvars is overriden by z.tfvars).
| | | `-- stacks.out/ # Stacks operations that produce output code store it in stacks.out (or the value of the STACKS_OUTPUT_DIR environment variable). Make sure to exclude this directory from version control.
| | `-- production_foo/ # If you want to deploy your stack multiple times per environment you can use layer instances, which are represented by a layer suffixed by an underscore followed by a string that must follow the ^[a-zA-Z0-9-]{,254}$ regular expression.
| | `-- .keep # Technically, you don't have to have anything in layer directories, but make sure your version control checks out empty directories, otherwise you can create something like an empty ".keep" file like so.
| `-- stack.tfvars # Stacks can contain any number of *.tfvars files, which are sorted alphabetically for preference (i.e. a.tfvars is overriden by z.tfvars).
|-- global.tf # The stacks folder can contain any number of *.tf files, which are joined with the stack base code for cross-stack Terraform code reusability (for example, to define state backends and providers).
`-- globals.tfvars # The stacks folder can contain any number of *.tfvars files, which are sorted alphabetically for preference (i.e. a.tfvars is overriden by z.tfvars).
Variable values of the environments' env.tfvars
are overriden by those in stacks/*.tfvars
, which are overriden by those in the stack's *.tfvars
, which are overriden by those in the layer's *.tfvars
.
Overrides are performed by joining two adjacent data structures with deepmerge.always_merger.merge(...)
, so:
bool
/number
/string
values are replaced:- if
stack.tfvars
sayscolor = "red"
- and
layer.tfvars
sayscolor = "blue"
- the result is
color = "blue"
- if
list
/set
values are joined:- if
stack.tfvars
sayscolors = ["red", "blue"]
- and
layer.tfvars
sayscolors = ["green", "yellow"]
- the result is
colors = ["red", "blue", "green", "yellow"]
- if
map
values are joined:- if
stack.tfvars
sayscolors = { red = "#ff0000", blue = "#00ffff" }
- and
layer.tfvars
sayscolors = { blue = "#0000ff", green = "#00ff00" }
- the result is
colors = { red = "#ff0000", blue = "#0000ff", green = "#00ff00" }
- if
You can also have *.tfvars.jinja
files anywhere you can have *.tfvars
files, which support Jinja templating, but be careful not to put yourself into a cyclical reference.