Reputation: 471
I have a variable that the user will input during run time. Let's say the variable name is region. However, I want the execution to be only successful if the user picks a value from one of the values defined in a list/ choices.
how can I restrict it so the user's selection has to match values that are considered acceptable in the variable definition?
Upvotes: 47
Views: 47816
Reputation: 273
Your problem is still is a valid situation that many Terraform users might face. Therefore, I will provide a more up to date answer.
In order to restrict an input variable to a list of possible choices you can now do the following:
variable "create_mode" {
type = string
description = "Some description"
default = "Default"
validation {
condition = contains(["Default", "PointInTimeRestore", "Replica"], var.create_mode)
error_message = "Valid values for create_mode are (Default, PointInTimeRestore, Replica)"
}
}
In the example above I have the variable create_mode
. The valid options are: "Default", "PointInTimeRestore", "Replica". So in order to restrict the input I'm adding the validation block which contains the condition and the error message to display in case somebody tries to use an invalid value for the variable.
Now if I try to initiatiate this variable to let's say create_mode = "Random"
I will get the following error when I do terraform plan
or terraform validate
.
daniel:~$tfplan
╷
│ Error: Invalid value for variable
│
│ on main.tf line 91, in module "pg_fs_database":
│ 91: create_mode = "Random"
│ ├────────────────
│ │ var.create_mode is "Random"
│
│ Valid values for create_mode are (Default, PointInTimeRestore, Replica)
│
│ This was checked by the validation rule at ../postgresql-flexible-server/variables.tf:56,3-13.
Have a look here for more details.
Upvotes: 6
Reputation: 36354
Stumbled across this question.
Since v0.13.0 input validation has been possible directly via the input variables. Thus you can actually achieve this with a snippet such as below.
variable "test_variable" {
type = string
description = "some test value"
validation {
condition = contains(["item1", "item2", "item3"], var.test_variable)
error_message = "Valid values for var: test_variable are (item1, item2, item3)."
}
}
Read more here - https://www.hashicorp.com/blog/custom-variable-validation-in-terraform-0-13
Upvotes: 98
Reputation: 74239
Terraform currently has no first-class feature for this, but you can achieve the desired effect (albeit with a less-helpful error message) by asking Terraform to look the value up in a map:
variable "example" {
description = "must be a, b, or c"
}
locals {
allowed_example_values = { for v in ["a", "b", "c"] : v => v }
checked_example = local.allowed_example_values[var.example] # will fail if var.example is invalid
}
Because the values in the allowed_example_values
map are the same as the keys, you can then use local.checked_example
in place of var.example
everywhere else in the module to set up the dependency graph such that it's impossible for an invalid value to be used.
Some caveats/limitations:
You can't customize the error message that Terraform will return when the value is invalid. Instead, Terraform will return the generic error about the key not matching any element in the map. However, it will include the source code snippet from the affected line in the error message (in Terraform 0.12 or later) so the comment at the end of that line should be visible in the error message and thus provide an additional clue to the user as to what might be wrong.
This works fully only for string values, because map keys are always strings in Terraform. Using other primitive types can work as a result of Terraform's automatic conversions from bool and number to string, but you should be sure to explicitly declare the type of the variable (using e.g. type = number
) to ensure that Terraform will normalize incoming values into the expected type before looking them up in the map. This technique will not work at all for collection and structural types.
I wouldn't suggest using strings "true"
and "false"
since Terraform has a bool
type which can represent that more intuitively. If you are using Terraform 0.11 and earlier then it's not possible to constrain to bool, but in Terraform 0.12 and later you can declare a variable as type = bool
and then Terraform will handle the validation automatically.
Upvotes: 0
Reputation: 8701
One solution:
variable "values_list" {
description = "acceptable values"
type = "list"
default = ["true", "false"]
}
variable "somevar" {
description = "must be true or false"
}
resource "null_resource" "is_variable_value_valid" {
count = "${contains(var.values_list, var.somevar) == true ? 0 : 1}"
"ERROR: The somevar value can only be: true or false" = true
}
If you pass a value different than "true" or "false" for the "somevar" variable, Terraform will throw an error and stop. The disadvantage is that you have to list all values in the default
block of values_list
.
Source: https://stackoverflow.com/a/54256780/1364793
Upvotes: 4