correctly verify planned nested object values
The validation for nested object types with computed attributes was using the incorrect function call.
This commit is contained in:
parent
fee0bffed3
commit
7ca6be8285
|
@ -424,7 +424,7 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
|
|||
if !prior.IsNull() && prior.HasIndex(idx).True() {
|
||||
priorEV = prior.Index(idx)
|
||||
}
|
||||
moreErrs := assertPlannedObjectValid(schema, priorEV, configEV, plannedEV, path)
|
||||
moreErrs := assertPlannedAttrsValid(schema.Attributes, priorEV, configEV, plannedEV, path)
|
||||
errs = append(errs, moreErrs...)
|
||||
}
|
||||
for it := config.ElementIterator(); it.Next(); {
|
||||
|
|
|
@ -1222,6 +1222,137 @@ func TestAssertPlanValid(t *testing.T) {
|
|||
}),
|
||||
[]string{`.bloop: planned value cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"blop":cty.StringVal("ok")})}) for a non-computed attribute`},
|
||||
},
|
||||
"computed in nested objects": {
|
||||
&configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"map": {
|
||||
NestedType: &configschema.Object{
|
||||
Nesting: configschema.NestingMap,
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"name": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// When an object has dynamic attrs, the map may be
|
||||
// handled as an object.
|
||||
"map_as_obj": {
|
||||
NestedType: &configschema.Object{
|
||||
Nesting: configschema.NestingMap,
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"name": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"list": {
|
||||
NestedType: &configschema.Object{
|
||||
Nesting: configschema.NestingList,
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"name": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"set": {
|
||||
NestedType: &configschema.Object{
|
||||
Nesting: configschema.NestingSet,
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"name": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"single": {
|
||||
NestedType: &configschema.Object{
|
||||
Nesting: configschema.NestingSingle,
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"name": {
|
||||
Type: cty.DynamicPseudoType,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cty.NullVal(cty.Object(map[string]cty.Type{
|
||||
"map": cty.Map(cty.Object(map[string]cty.Type{
|
||||
"name": cty.String,
|
||||
})),
|
||||
"map_as_obj": cty.Map(cty.Object(map[string]cty.Type{
|
||||
"name": cty.DynamicPseudoType,
|
||||
})),
|
||||
"list": cty.List(cty.Object(map[string]cty.Type{
|
||||
"name": cty.String,
|
||||
})),
|
||||
"set": cty.Set(cty.Object(map[string]cty.Type{
|
||||
"name": cty.String,
|
||||
})),
|
||||
"single": cty.Object(map[string]cty.Type{
|
||||
"name": cty.String,
|
||||
}),
|
||||
})),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"map": cty.MapVal(map[string]cty.Value{
|
||||
"one": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
"map_as_obj": cty.ObjectVal(map[string]cty.Value{
|
||||
"one": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.DynamicPseudoType),
|
||||
}),
|
||||
}),
|
||||
"list": cty.ListVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
"set": cty.SetVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
"single": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"map": cty.MapVal(map[string]cty.Value{
|
||||
"one": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
"map_as_obj": cty.ObjectVal(map[string]cty.Value{
|
||||
"one": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.StringVal("computed"),
|
||||
}),
|
||||
}),
|
||||
"list": cty.ListVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
"set": cty.SetVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
"single": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
nil,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
|
@ -1256,3 +1387,85 @@ func TestAssertPlanValid(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAssertPlanValidTEST(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
Schema *configschema.Block
|
||||
Prior cty.Value
|
||||
Config cty.Value
|
||||
Planned cty.Value
|
||||
WantErrs []string
|
||||
}{
|
||||
"computed in map": {
|
||||
&configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"items": {
|
||||
NestedType: &configschema.Object{
|
||||
Nesting: configschema.NestingMap,
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"name": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
cty.NullVal(cty.Object(map[string]cty.Type{
|
||||
"items": cty.Map(cty.Object(map[string]cty.Type{
|
||||
"name": cty.String,
|
||||
})),
|
||||
})),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"items": cty.MapVal(map[string]cty.Value{
|
||||
"one": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.NullVal(cty.String),
|
||||
//"name": cty.StringVal("computed"),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"items": cty.MapVal(map[string]cty.Value{
|
||||
"one": cty.ObjectVal(map[string]cty.Value{
|
||||
"name": cty.StringVal("computed"),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
nil,
|
||||
},
|
||||
}
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
errs := AssertPlanValid(test.Schema, test.Prior, test.Config, test.Planned)
|
||||
|
||||
wantErrs := make(map[string]struct{})
|
||||
gotErrs := make(map[string]struct{})
|
||||
for _, err := range errs {
|
||||
gotErrs[tfdiags.FormatError(err)] = struct{}{}
|
||||
}
|
||||
for _, msg := range test.WantErrs {
|
||||
wantErrs[msg] = struct{}{}
|
||||
}
|
||||
|
||||
t.Logf(
|
||||
"\nprior: %sconfig: %splanned: %s",
|
||||
dump.Value(test.Planned),
|
||||
dump.Value(test.Config),
|
||||
dump.Value(test.Planned),
|
||||
)
|
||||
for msg := range wantErrs {
|
||||
if _, ok := gotErrs[msg]; !ok {
|
||||
t.Errorf("missing expected error: %s", msg)
|
||||
}
|
||||
}
|
||||
for msg := range gotErrs {
|
||||
if _, ok := wantErrs[msg]; !ok {
|
||||
t.Errorf("unexpected extra error: %s", msg)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue