mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
set length is unknown with partially known elems
If a set contains partially known values the length is unknown which causes assertPlannedObjectValid to fail valid plans. Revert to the old method if using LengthInt for the set lengths, which returns the maximum number of possible elements, with a guard for entirely unknown set values.
This commit is contained in:
parent
8f6fd86ed8
commit
3c8a163583
@ -342,6 +342,11 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
|
||||
errs = append(errs, path.NewErrorf("planned for existence but config wants absence"))
|
||||
return errs
|
||||
}
|
||||
if !config.IsNull() && !planned.IsKnown() {
|
||||
errs = append(errs, path.NewErrorf("planned unknown for configured value"))
|
||||
return errs
|
||||
}
|
||||
|
||||
if planned.IsNull() {
|
||||
// No further checks possible if the planned value is null
|
||||
return errs
|
||||
@ -442,16 +447,14 @@ func assertPlannedObjectValid(schema *configschema.Object, prior, config, planne
|
||||
}
|
||||
|
||||
case configschema.NestingSet:
|
||||
plannedL := planned.Length()
|
||||
configL := config.Length()
|
||||
|
||||
// config wasn't known, then planned should be unknown too
|
||||
if !plannedL.IsKnown() && !configL.IsKnown() {
|
||||
if !planned.IsKnown() || !config.IsKnown() {
|
||||
// if either is unknown we cannot check the lengths
|
||||
return errs
|
||||
}
|
||||
|
||||
lenEqual := plannedL.Equals(configL)
|
||||
if !lenEqual.IsKnown() || lenEqual.False() {
|
||||
plannedL := planned.LengthInt()
|
||||
configL := config.LengthInt()
|
||||
if plannedL != configL {
|
||||
errs = append(errs, path.NewErrorf("count in plan (%#v) disagrees with count in config (%#v)", plannedL, configL))
|
||||
return errs
|
||||
}
|
||||
|
@ -1700,7 +1700,7 @@ func TestAssertPlanValid(t *testing.T) {
|
||||
&configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"set": {
|
||||
Computed: true,
|
||||
//Computed: true,
|
||||
Optional: true,
|
||||
NestedType: &configschema.Object{
|
||||
Nesting: configschema.NestingSet,
|
||||
@ -1796,9 +1796,9 @@ func TestAssertPlanValid(t *testing.T) {
|
||||
)),
|
||||
}),
|
||||
[]string{
|
||||
`.set: count in plan (cty.UnknownVal(cty.Number).Refine().NotNull().NumberLowerBound(cty.NumberIntVal(0), true).NumberUpperBound(cty.NumberIntVal(9.223372036854775807e+18), true).NewValue()) disagrees with count in config (cty.NumberIntVal(1))`,
|
||||
`.list: count in plan (cty.UnknownVal(cty.Number).Refine().NotNull().NumberLowerBound(cty.NumberIntVal(0), true).NumberUpperBound(cty.NumberIntVal(9.223372036854775807e+18), true).NewValue()) disagrees with count in config (cty.NumberIntVal(1))`,
|
||||
`.map: count in plan (cty.UnknownVal(cty.Number).Refine().NotNull().NumberLowerBound(cty.NumberIntVal(0), true).NumberUpperBound(cty.NumberIntVal(9.223372036854775807e+18), true).NewValue()) disagrees with count in config (cty.NumberIntVal(1))`,
|
||||
`.set: planned unknown for configured value`,
|
||||
`.list: planned unknown for configured value`,
|
||||
`.map: planned unknown for configured value`,
|
||||
},
|
||||
},
|
||||
|
||||
@ -1829,6 +1829,68 @@ func TestAssertPlanValid(t *testing.T) {
|
||||
}),
|
||||
nil,
|
||||
},
|
||||
|
||||
"nested set values can contain computed unknown": {
|
||||
&configschema.Block{
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"set": {
|
||||
Optional: true,
|
||||
NestedType: &configschema.Object{
|
||||
Nesting: configschema.NestingSet,
|
||||
Attributes: map[string]*configschema.Attribute{
|
||||
"input": {
|
||||
Type: cty.String,
|
||||
Optional: true,
|
||||
},
|
||||
"computed": {
|
||||
Type: cty.String,
|
||||
Computed: true,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"set": cty.SetVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"input": cty.StringVal("a"),
|
||||
"computed": cty.NullVal(cty.String),
|
||||
}),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"input": cty.StringVal("b"),
|
||||
"computed": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"set": cty.SetVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"input": cty.StringVal("a"),
|
||||
"computed": cty.NullVal(cty.String),
|
||||
}),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"input": cty.StringVal("b"),
|
||||
"computed": cty.NullVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
// Plan can mark the null computed values as unknown
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"set": cty.SetVal([]cty.Value{
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"input": cty.StringVal("a"),
|
||||
"computed": cty.UnknownVal(cty.String),
|
||||
}),
|
||||
cty.ObjectVal(map[string]cty.Value{
|
||||
"input": cty.StringVal("b"),
|
||||
"computed": cty.UnknownVal(cty.String),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
[]string{},
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
|
Loading…
Reference in New Issue
Block a user