sorry for the basic question, new to terraform. I am running through some sample examples in terraform where lots of example show declaration of local variable, i.e. locals, by name it sounds like the scope of it, is local to the file. instead of locals, we should be able to pass this list as variable right? such as .also, the examples use for_each construct or locals.names[count.index] , where count.index = length(locals.names) , what is the best way to pass and iterate such list in terraform?
variable "name_list"{
names = ["luke", "Tom", ...]
type = ...
}
file - main.tf
locals{
names = ["luke", "Tom", "Jerry"]
}
resource "aws..." "example..."{
foreach
}
I have tried it as locals but want to pass the list as variable.
If you are familiar with general-purpose programming languages then it may be helpful to think of a Terraform module as being similar to a function, and then the three different kinds of named values within a module also have analogies:
The analogy isn't perfect because e.g. in many languages a function can only return one value, but Terraform allows a module to return many separate named values. But hopefully this does still make it easier to imagine the scope and purpose of each of these.
Elsewhere in your module, expressions can refer both to input variables and to local values:
var.name_list
refers to the variable "name_list"
declaration you showed in your example.local.names
refers to the names
local value you showed in your example.You mentioned wanting to use this with for_each
, and the important thing for for_each
is that the value you assign to it must be either a map or a set of strings. for_each
primarily wants to work with maps, but if you assign a set like toset(["a", "b"])
then as a convenience for_each
will interpret it as if you had written tomap({"a" = "a", "b" = "b"})
, so you you can write this more concisely when you have a situation where there isn't any useful value to associate with each of your elements.
Since you've shown a collection of unique names in your example it seems like a set of strings would be sufficient for your purposes, and so the following two examples show how to declare a set of strings and use it in for_each
, first with a local value and then with an input variable.
locals {
names = toset(["Luke", "Tom", "Jerry"])
}
resource "example" "example" {
for_each = local.names
# ...
}
variable "names" {
type = set(string)
}
resource "example" "example" {
for_each = var.names
# ...
}
If you use the second example in your root Terraform module then you'll need to set the names
value from outside the module when you run terraform apply
. There are various different ways to do that, but an easy one for the sake of example here is to create a file named example.tfvars
and write the following content into it:
names = ["Luke", "Tom", "Jerry"]
Then you can run terraform apply -var-file=example.tfvars
to apply this configuration with that set of names. Note that you don't need to (and must not) write toset(...)
in the .tfvars
file, because for input variables it's the responsibility of the module itself to decide the type, as we did by writing type = set(string)
in the configuration above. Terraform will therefore automatically effectively pass this value through toset
before passing it into the module.
You should typically only use root module input variables for values you expect will need to change between runs without editing the module's own source code. A local value is a better choice for something that is fixed as part of the definition of the module.