Merge pull request #18508 from hashicorp/jbardin/config-nulls

always use Null for unset configuration values
pull/18527/head
James Bardin 8 years ago committed by GitHub
commit 2b2a4b6ebd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -58,9 +58,7 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
switch {
case ty.HasAttribute(name):
val = in.GetAttr(name)
case attrS.Computed:
val = cty.UnknownVal(attrS.Type)
case attrS.Optional:
case attrS.Computed || attrS.Optional:
val = cty.NullVal(attrS.Type)
default:
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("attribute %q is required", name)

@ -342,6 +342,22 @@ func TestCoerceValue(t *testing.T) {
cty.DynamicVal,
`.foo: number required`,
},
"unset computed value": {
&Block{
Attributes: map[string]*Attribute{
"foo": {
Type: cty.String,
Optional: true,
Computed: true,
},
},
},
cty.ObjectVal(map[string]cty.Value{}),
cty.ObjectVal(map[string]cty.Value{
"foo": cty.NullVal(cty.String),
}),
``,
},
}
for name, test := range tests {

@ -2,7 +2,6 @@ package configschema
import (
"github.com/hashicorp/hcl2/hcldec"
"github.com/zclconf/go-cty/cty"
)
var mapLabelNames = []string{"key"}
@ -11,9 +10,8 @@ var mapLabelNames = []string{"key"}
// using the facilities in the hcldec package.
//
// The returned specification is guaranteed to return a value of the same type
// returned by method ImpliedType, but it may contain null or unknown values if
// any of the block attributes are defined as optional and/or computed
// respectively.
// returned by method ImpliedType, but it may contain null values if any of the
// block attributes are defined as optional and/or computed respectively.
func (b *Block) DecoderSpec() hcldec.Spec {
ret := hcldec.ObjectSpec{}
if b == nil {
@ -21,30 +19,10 @@ func (b *Block) DecoderSpec() hcldec.Spec {
}
for name, attrS := range b.Attributes {
switch {
case attrS.Computed && attrS.Optional:
// In this special case we use an unknown value as a default
// to get the intended behavior that the result is computed
// unless it has been explicitly set in config.
ret[name] = &hcldec.DefaultSpec{
Primary: &hcldec.AttrSpec{
Name: name,
Type: attrS.Type,
},
Default: &hcldec.LiteralSpec{
Value: cty.UnknownVal(attrS.Type),
},
}
case attrS.Computed:
ret[name] = &hcldec.LiteralSpec{
Value: cty.UnknownVal(attrS.Type),
}
default:
ret[name] = &hcldec.AttrSpec{
Name: name,
Type: attrS.Type,
Required: attrS.Required,
}
ret[name] = &hcldec.AttrSpec{
Name: name,
Type: attrS.Type,
Required: attrS.Required,
}
}

@ -55,6 +55,11 @@ func TestBlockDecoderSpec(t *testing.T) {
Optional: true,
Computed: true,
},
"optional_computed_unknown": {
Type: cty.String,
Optional: true,
Computed: true,
},
},
},
hcltest.MockBody(&hcl.BodyContent{
@ -67,14 +72,19 @@ func TestBlockDecoderSpec(t *testing.T) {
Name: "optional_computed_overridden",
Expr: hcltest.MockExprLiteral(cty.True),
},
"optional_computed_unknown": {
Name: "optional_computed_overridden",
Expr: hcltest.MockExprLiteral(cty.UnknownVal(cty.String)),
},
},
}),
cty.ObjectVal(map[string]cty.Value{
"optional": cty.NullVal(cty.Number),
"required": cty.StringVal("5"), // converted from number to string
"computed": cty.UnknownVal(cty.List(cty.Bool)),
"optional_computed": cty.UnknownVal(cty.Map(cty.Bool)),
"computed": cty.NullVal(cty.List(cty.Bool)),
"optional_computed": cty.NullVal(cty.Map(cty.Bool)),
"optional_computed_overridden": cty.True,
"optional_computed_unknown": cty.UnknownVal(cty.String),
}),
0,
},

Loading…
Cancel
Save