Merge pull request #9751 from hashicorp/b-true-true
terraform: consistent variable values for booleans
This commit is contained in:
commit
e8f5e4b292
|
@ -0,0 +1,10 @@
|
|||
// At the time of writing Terraform doesn't formally support a boolean
|
||||
// type, but historically this has magically worked. Lots of TF code
|
||||
// relies on this so we test it now.
|
||||
variable "a" {
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "b" {
|
||||
default = false
|
||||
}
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/terraform/config"
|
||||
"github.com/hashicorp/terraform/config/module"
|
||||
"github.com/hashicorp/terraform/helper/hilmapstructure"
|
||||
)
|
||||
|
||||
// Variables returns the fully loaded set of variables to use with
|
||||
|
@ -104,10 +105,25 @@ func Variables(
|
|||
}
|
||||
|
||||
switch schema.Type() {
|
||||
case config.VariableTypeList:
|
||||
result[k] = v
|
||||
case config.VariableTypeMap:
|
||||
varSetMap(result, k, v)
|
||||
case config.VariableTypeString:
|
||||
// Convert to a string and set. We don't catch any errors
|
||||
// here because the validation step later should catch
|
||||
// any type errors.
|
||||
var strVal string
|
||||
if err := hilmapstructure.WeakDecode(v, &strVal); err == nil {
|
||||
result[k] = strVal
|
||||
} else {
|
||||
result[k] = v
|
||||
}
|
||||
default:
|
||||
result[k] = v
|
||||
panic(fmt.Sprintf(
|
||||
"Unhandled var type: %T\n\n"+
|
||||
"THIS IS A BUG. Please report it.",
|
||||
schema.Type()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,15 +83,64 @@ func TestVariables(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
|
||||
"bools: config only": {
|
||||
"vars-basic-bool",
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
map[string]interface{}{
|
||||
"a": "1",
|
||||
"b": "0",
|
||||
},
|
||||
},
|
||||
|
||||
"bools: override with string": {
|
||||
"vars-basic-bool",
|
||||
nil,
|
||||
map[string]interface{}{
|
||||
"a": "foo",
|
||||
"b": "bar",
|
||||
},
|
||||
false,
|
||||
map[string]interface{}{
|
||||
"a": "foo",
|
||||
"b": "bar",
|
||||
},
|
||||
},
|
||||
|
||||
"bools: override with env": {
|
||||
"vars-basic-bool",
|
||||
map[string]string{
|
||||
"TF_VAR_a": "false",
|
||||
"TF_VAR_b": "true",
|
||||
},
|
||||
nil,
|
||||
false,
|
||||
map[string]interface{}{
|
||||
"a": "false",
|
||||
"b": "true",
|
||||
},
|
||||
},
|
||||
|
||||
"bools: override with bool": {
|
||||
"vars-basic-bool",
|
||||
nil,
|
||||
map[string]interface{}{
|
||||
"a": false,
|
||||
"b": true,
|
||||
},
|
||||
false,
|
||||
map[string]interface{}{
|
||||
"a": "0",
|
||||
"b": "1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
if name != "override partial map" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Wrapped in a func so we can get defers to work
|
||||
func() {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
// Set the env vars
|
||||
for k, v := range tc.Env {
|
||||
defer tempEnv(t, k, v)()
|
||||
|
@ -107,8 +156,8 @@ func TestVariables(t *testing.T) {
|
|||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, tc.Expected) {
|
||||
t.Fatalf("%s: expected: %#v\n\ngot: %#v", name, tc.Expected, actual)
|
||||
t.Fatalf("%s\n\nexpected: %#v\n\ngot: %#v", name, tc.Expected, actual)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,6 +159,53 @@ VALUE
|
|||
}
|
||||
```
|
||||
|
||||
### Booleans
|
||||
|
||||
Although it appears Terraform supports boolean types, they are instead
|
||||
silently converted to string types. The implications of this are subtle and
|
||||
should be completely understood if you plan on using boolean values.
|
||||
|
||||
It is instead recommended you avoid using boolean values for now and use
|
||||
explicit strings. A future version of Terraform will properly support
|
||||
booleans and using the current behavior could result in backwards-incompatibilities
|
||||
in the future.
|
||||
|
||||
For a configuration such as the following:
|
||||
|
||||
```
|
||||
variable "active" {
|
||||
default = false
|
||||
}
|
||||
```
|
||||
|
||||
The false is converted to a string `"0"` when running Terraform.
|
||||
|
||||
Then, depending on where you specify overrides, the behavior can differ:
|
||||
|
||||
* Variables with boolean values in a `tfvars` file will likewise be
|
||||
converted to "0" and "1" values.
|
||||
|
||||
* Variables specified via the `-var` command line flag will be literal
|
||||
strings "true" and "false", so care should be taken to explicitly use
|
||||
"0" or "1".
|
||||
|
||||
* Variables specified with the `TF_VAR_` environment variables will
|
||||
be literal string values, just like `-var`.
|
||||
|
||||
A future version of Terraform will fully support first-class boolean
|
||||
types which will make the behavior of booleans consistent as you would
|
||||
expect. This may break some of the above behavior.
|
||||
|
||||
When passing boolean-like variables as parameters to resource configurations
|
||||
that expect boolean values, they are converted consistently:
|
||||
|
||||
* "1", "true", "t" all become `true`
|
||||
* "0", "false", "f" all become `false`
|
||||
|
||||
The behavior of conversion above will likely not change in future
|
||||
Terraform versions. Therefore, simply using string values rather than
|
||||
booleans for variables is recommended.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Environment variables can be used to set the value of a variable.
|
||||
|
|
Loading…
Reference in New Issue