Merge pull request #9751 from hashicorp/b-true-true

terraform: consistent variable values for booleans
This commit is contained in:
Mitchell Hashimoto 2016-10-31 13:23:37 -07:00 committed by GitHub
commit e8f5e4b292
4 changed files with 130 additions and 8 deletions

View File

@ -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
}

View File

@ -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()))
}
}
}

View File

@ -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)
}
}()
})
}
}

View File

@ -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.