Input Variables
The terms page introduced variables as
one of the config primitives; this page is the full treatment. So far you have
hardcoded resource argument values. Input variables parameterize a
configuration so you can standardize the code but still customize attributes at
run time - the same .tf files run with different values without editing the
source. Variables separate source code from value assignments.
Take a bucket whose name, location, and storage_class are hardcoded. Declare
any of them as a variable and supply the value at run time instead:
Declaring an input variable
A variable is declared in a variable block. Best practice is to keep all
declarations in a separate file named variables.tf. The label after the
variable keyword names it.
A variable name must be unique within a module, and it cannot be a
keyword. There are no required arguments, so a variable block can be
empty - Terraform then deduces the type and default from usage.
Referencing a variable
Access a declared variable with the expression var.<variable_name>. The
name in the variable block must match the reference in the resource block:
Variable arguments
Four meta-arguments configure a variable: type, default,
description, and sensitive.
type
type restricts the accepted value types. Terraform supports three primitive
types:
bool- a binary value,trueorfalse(no quotes).number- a numeric value.string- a sequence of Unicode characters.
default
default assigns a fallback value, used when no value is set by any other
method. The default shows up in the execution plan when you run terraform plan:
description
description documents the variable's purpose and expected value. Terraform
displays it at run time whenever the variable has no assigned value and it
prompts you on the CLI. Because the string often lands in generated
documentation, write it from the user's perspective, not the maintainer's -
use comments for maintainer notes.
sensitive
sensitive = true hides the value from the output of terraform plan and
terraform apply, and from log files. Use it for database credentials, API
tokens, and other secrets to eliminate accidental exposure.
When a resource uses a variable marked sensitive, the attributes fed by it are
also redacted in plan/apply output. In the example, foo's name and
address are shown as (sensitive) because user_information is sensitive.
Assigning values at run time
Once a variable is declared, there are several ways to set its value. Each
overrides the default.
.tfvarsfiles - version and switch between whole sets of variables (recommended).- CLI
-varoption - good for quick examples and automation. - Environment variables (
TF_VAR_<name>) - useful in scripts and pipelines. - CLI prompt - the fallback when a required variable was not set by any of the above.
Definition files (.tfvars)
When there are too many values to pass on the command line, put them in a
definitions file with a .tfvars or .tfvars.json extension. Contents use
HCL syntax but hold only name assignments:
Terraform auto-loads a definitions file only when it is named exactly
terraform.tfvars, terraform.tfvars.json, *.auto.tfvars, or
*.auto.tfvars.json. Any other name - including a .tf extension or a
custom name like my-vars.tfvars - must be passed explicitly with
-var-file on the command line.
Precedence
If the same variable is set by multiple methods, the -var (and -var-file)
option wins over everything else. This is what lets you reuse a .tfvars file
and still override individual values at deploy time.
-var / -var-file take the highest precedence over all other assignment
methods, which is why they suit automation that sources values from the
environment. If a required variable is not set by any method, Terraform
prompts you on the CLI during the plan phase rather than failing.
Validating variable values
Add a validation sub-block inside the variable block to enforce a rule on
the assigned value. It takes a condition (the rule) and an
error_message shown when the condition is false. Here contains() checks
the storage class is one of the accepted values:
Supplying a disallowed value (ZONAL) fails the plan with your error message:
Best practices
Once you know how variables parameterize a configuration, a handful of conventions keep
them maintainable: expose only what genuinely varies, feed values through a committed
.tfvars file, name variables clearly (with units), and always describe them. These are
the habits the exam expects from a well-authored module.
Parameterize only when necessary
Only parameterize values that vary for each instance or environment. Before exposing a variable, make sure you have a concrete use case for changing it - if there's only a small chance it might be needed, don't expose it. Every variable is surface area that future maintainers must understand.
Changing or adding a variable with a default value is backward-compatible - existing callers keep working. Removing a variable is not backward-compatible: anything that set it now fails. Bias toward the smallest set of variables you can, because you can add later far more easily than you can take away.
Provide values in a .tfvars file
For root modules, provide values by using a .tfvars variables file rather than
passing them on the command line. A default variables file lives beside your configuration
and is checked into source control, so applies are predictable and reproducible.
terraform.tfvars
Avoid - values on the command line
Command-line options are ephemeral and easy to forget, and they cannot be checked into
source control. Mixing -var/-var-file flags with a default variables file makes it
unclear where a value actually came from. Keep values in the .tfvars file.
Give variables descriptive names
Give variables descriptive names relevant to their usage or purpose. Two rules make names unambiguous:
- Numeric values must carry their unit in the name - for example disk or RAM sizes. Google
Cloud APIs don't have standard units, so a name like
ram_size_gbtells the maintainer exactly what to pass. - Boolean variables get positive names to simplify conditional logic, for example
enable_external_access(notdisable_external_access).
Provide meaningful descriptions
Variables must have descriptions. Descriptions are automatically included in the
generated documentation and give new developers the context to use a variable
correctly. A vague description paired with a vague name (myregion, "Specify the region.")
leaves the reader guessing which region and why.