Suppose the same module must launch an AWS instance in different subnets. An input value supplies the subnet ID for one use of that module; the module’s input variable declares where that value enters. This lets users change the instance’s configuration without editing the module. An input variable is therefore different from an output, which shares information outward, or a local, which stays inside the module. section 3.2 section 3.3
Declare an input with a `variable` block, then read its value inside the module as `var.name`. For an instance module, `var.subnet_id` can supply the `subnet_id` argument of an `aws_instance` resource. A `type` restriction helps catch an unsuitable value; a `default` supplies one when the user provides none. Descriptions document the input, while validation can check a more specific requirement, such as the expected subnet ID pattern. section 3.3.1 section 3.8.2
Listing 3.32 Adding variables.tf to our module
variable "instance_type" {
type = string #1
description = "The type of instance to launch." #2
default = "t3.micro" #3
}
variable "subnet_id" {
type = string #4
description = "The ID of the Subnet to launch the instance into."
validation { #5
condition = length(regexall("^subnet-[\\d|\\w]+$", var.subnet_id))
== 1 #6
error_message = "The subnet_id must match the pattern ^subnet-[
\\d|\\w]+$" #7
}
}
#1 We limit the possible values to the string type.
#2 A description helps users know what our input does.
#3 Providing a default value makes this input optional.
#4 We also want a string here.
#5 This validation block lets us ensure the subnet id is the right format.
#6 Here we use functions to run a regular expression check. Functions are covered in the next chapter.
#7 This message is displayed if the validation check fails.
The `variables.tf` listing shows a string subnet ID with validation beside an instance type with a default. Compare what callers must supply with what the module can supply itself. section 3.8.2
Pass a value from a calling module
A calling module can set `subnet_id = data.aws_subnets.default.ids[0]` in its `module` block. The instance type can be omitted because its declaration has a default. Inside the called module, `subnet_id = var.subnet_id` passes the supplied value to the instance resource. The caller can obtain an input value from a data lookup rather than typing a fixed ID. section 3.8.4 section 3.8.2
For a root module, choose how to supply values when planning:
- Let Terraform prompt for missing values during testing. Use `terraform plan -input=false` when missing inputs should cause an error instead, particularly in automation. section 5.4.1
- Pass simple values with repeated `-var` flags. Shell quoting and escaping make this less convenient for complex data. section 5.4.2
- Keep values in HCL `.tfvars` or JSON `.tfvars.json` files. Use `-var-file=production.tfvars`, or an automatically loaded filename such as `terraform.tfvars`. HCL variable files contain literal `key = value` assignments, not functions or transformations. section 5.4.3
Root-level input values can make the same code produce different environments: the values affect the generated resource graph, which Terraform compares with state to produce a plan. They can also select features, while inputs to smaller modules can control details such as instance count. Validate values where a module has clear constraints, and prefer repeatable value files over repeated manual prompts for established environments. section 5.4 section 4.1.3 section 5.4.1













