helper/schema: computed bool fields should not crash
Fixes #7715 If a bool field was computed and the raw value was not convertable to a boolean, helper/schema would crash. The correct behavior is to try not to read the raw value when the value is computed and to simply mark that it is computed. This does that (and matches the behavior of the other primitives).
This commit is contained in:
parent
13483b574e
commit
7834cf7190
|
@ -223,6 +223,9 @@ func stringToPrimitive(
|
|||
returnVal = false
|
||||
break
|
||||
}
|
||||
if computed {
|
||||
break
|
||||
}
|
||||
|
||||
v, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
|
|
|
@ -49,6 +49,71 @@ func TestConfigFieldReader(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
// This contains custom table tests for our ConfigFieldReader
|
||||
func TestConfigFieldReader_custom(t *testing.T) {
|
||||
schema := map[string]*Schema{
|
||||
"bool": &Schema{
|
||||
Type: TypeBool,
|
||||
},
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
Addr []string
|
||||
Result FieldReadResult
|
||||
Config *terraform.ResourceConfig
|
||||
Err bool
|
||||
}{
|
||||
"basic": {
|
||||
[]string{"bool"},
|
||||
FieldReadResult{
|
||||
Value: true,
|
||||
Exists: true,
|
||||
},
|
||||
testConfig(t, map[string]interface{}{
|
||||
"bool": true,
|
||||
}),
|
||||
false,
|
||||
},
|
||||
|
||||
"computed": {
|
||||
[]string{"bool"},
|
||||
FieldReadResult{
|
||||
Exists: true,
|
||||
Computed: true,
|
||||
},
|
||||
testConfigInterpolate(t, map[string]interface{}{
|
||||
"bool": "${var.foo}",
|
||||
}, map[string]ast.Variable{
|
||||
"var.foo": ast.Variable{
|
||||
Value: config.UnknownVariableValue,
|
||||
Type: ast.TypeString,
|
||||
},
|
||||
}),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
r := &ConfigFieldReader{
|
||||
Schema: schema,
|
||||
Config: tc.Config,
|
||||
}
|
||||
out, err := r.ReadField(tc.Addr)
|
||||
if err != nil != tc.Err {
|
||||
t.Fatalf("%s: err: %s", name, err)
|
||||
}
|
||||
if s, ok := out.Value.(*Set); ok {
|
||||
// If it is a set, convert to a list so its more easily checked.
|
||||
out.Value = s.List()
|
||||
}
|
||||
if !reflect.DeepEqual(tc.Result, out) {
|
||||
t.Fatalf("%s: bad: %#v", name, out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigFieldReader_DefaultHandling(t *testing.T) {
|
||||
schema := map[string]*Schema{
|
||||
"strWithDefault": &Schema{
|
||||
|
|
|
@ -2455,6 +2455,42 @@ func TestSchemaMap_Diff(t *testing.T) {
|
|||
|
||||
Err: false,
|
||||
},
|
||||
|
||||
// GH-7715
|
||||
"computed value for boolean field": {
|
||||
Schema: map[string]*Schema{
|
||||
"foo": &Schema{
|
||||
Type: TypeBool,
|
||||
ForceNew: true,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
|
||||
State: &terraform.InstanceState{},
|
||||
|
||||
Config: map[string]interface{}{
|
||||
"foo": "${var.foo}",
|
||||
},
|
||||
|
||||
ConfigVariables: map[string]ast.Variable{
|
||||
"var.foo": interfaceToVariableSwallowError(
|
||||
config.UnknownVariableValue),
|
||||
},
|
||||
|
||||
Diff: &terraform.InstanceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"foo": &terraform.ResourceAttrDiff{
|
||||
Old: "",
|
||||
New: "false",
|
||||
NewComputed: true,
|
||||
RequiresNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Err: false,
|
||||
},
|
||||
}
|
||||
|
||||
for tn, tc := range cases {
|
||||
|
|
Loading…
Reference in New Issue