Merge pull request #28941 from hashicorp/jbardin/objchange-unknown-blocks

handle unexpected changes to unknown block
This commit is contained in:
James Bardin 2021-06-14 10:31:31 -04:00 committed by GitHub
commit 2ecdf44918
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 118 additions and 0 deletions

View File

@ -69,7 +69,20 @@ func assertPlanValid(schema *configschema.Block, priorState, config, plannedStat
// Easy path: nothing has changed at all
continue
}
if !configV.IsKnown() {
// An unknown config block represents a dynamic block where the
// for_each value is unknown, and therefor cannot be altered by the
// provider.
errs = append(errs, path.NewErrorf("planned value %#v for unknown dynamic block", plannedV))
continue
}
if !plannedV.IsKnown() {
// Only dynamic configuration can set blocks to unknown, so this is
// not allowed from the provider. This means that either the config
// and plan should match, or we have an error where the plan
// changed the config value, both of which have been checked.
errs = append(errs, path.NewErrorf("attribute representing nested block must not be unknown itself; set nested attribute values to unknown instead"))
continue
}
@ -94,6 +107,7 @@ func assertPlanValid(schema *configschema.Block, priorState, config, plannedStat
errs = append(errs, path.NewErrorf("block count in plan (%d) disagrees with count in config (%d)", plannedL, configL))
continue
}
for it := plannedV.ElementIterator(); it.Next(); {
idx, plannedEV := it.Element()
path := append(path, cty.IndexStep{Key: idx})

View File

@ -388,6 +388,110 @@ func TestAssertPlanValid(t *testing.T) {
`.b: attribute representing a list of nested blocks must be empty to indicate no blocks, not null`,
},
},
// blocks can be unknown when using dynamic
"nested list, unknown nested dynamic": {
&configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"a": {
Nesting: configschema.NestingList,
Block: configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"b": {
Nesting: configschema.NestingList,
Block: configschema.Block{
Attributes: map[string]*configschema.Attribute{
"c": {
Type: cty.String,
Optional: true,
},
"computed": {
Type: cty.String,
Computed: true,
},
},
},
},
},
},
},
},
},
cty.ObjectVal(map[string]cty.Value{
"a": cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{
"computed": cty.NullVal(cty.String),
"b": cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{
"c": cty.StringVal("x"),
})}),
})}),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{
"b": cty.UnknownVal(cty.List(cty.Object(map[string]cty.Type{
"c": cty.String,
"computed": cty.String,
}))),
})}),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{
"b": cty.UnknownVal(cty.List(cty.Object(map[string]cty.Type{
"c": cty.String,
"computed": cty.String,
}))),
})}),
}),
[]string{},
},
"nested set, unknown dynamic cannot be planned": {
&configschema.Block{
Attributes: map[string]*configschema.Attribute{
"computed": {
Type: cty.String,
Computed: true,
},
},
BlockTypes: map[string]*configschema.NestedBlock{
"b": {
Nesting: configschema.NestingSet,
Block: configschema.Block{
Attributes: map[string]*configschema.Attribute{
"c": {
Type: cty.String,
Optional: true,
},
},
},
},
},
},
cty.ObjectVal(map[string]cty.Value{
"computed": cty.NullVal(cty.String),
"b": cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{
"c": cty.StringVal("x"),
})}),
}),
cty.ObjectVal(map[string]cty.Value{
"computed": cty.NullVal(cty.String),
"b": cty.UnknownVal(cty.Set(cty.Object(map[string]cty.Type{
"c": cty.String,
}))),
}),
cty.ObjectVal(map[string]cty.Value{
"computed": cty.StringVal("default"),
"b": cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{
"c": cty.StringVal("oops"),
})}),
}),
[]string{
`.b: planned value cty.SetVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"c":cty.StringVal("oops")})}) for unknown dynamic block`,
},
},
"nested set, null in plan": {
&configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{