Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

always allow computed-only changes in the plan #31509

Merged
merged 1 commit into from Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 19 additions & 12 deletions internal/plans/objchange/plan_valid.go
Expand Up @@ -257,6 +257,7 @@ func assertPlannedAttrValid(name string, attrS *configschema.Attribute, priorSta
}

func assertPlannedValueValid(attrS *configschema.Attribute, priorV, configV, plannedV cty.Value, path cty.Path) []error {

var errs []error
if plannedV.RawEquals(configV) {
// This is the easy path: provider didn't change anything at all.
Expand All @@ -270,22 +271,28 @@ func assertPlannedValueValid(attrS *configschema.Attribute, priorV, configV, pla
return errs
}

// the provider is allowed to insert values when the config is
switch {
// The provider can plan any value for a computed-only attribute. There may
// be a config value here in the case where a user used `ignore_changes` on
// a computed attribute and ignored the warning, or we failed to validate
// computed attributes in the config, but regardless it's not a plan error
// caused by the provider.
case attrS.Computed && !attrS.Optional:
return errs

// The provider is allowed to insert optional values when the config is
// null, but only if the attribute is computed.
if configV.IsNull() {
if attrS.Computed {
return errs
}
case configV.IsNull() && attrS.Computed:
return errs

case configV.IsNull() && !plannedV.IsNull():
// if the attribute is not computed, then any planned value is incorrect
if !plannedV.IsNull() {
if attrS.Sensitive {
errs = append(errs, path.NewErrorf("sensitive planned value for a non-computed attribute"))
} else {
errs = append(errs, path.NewErrorf("planned value %#v for a non-computed attribute", plannedV))
}
return errs
if attrS.Sensitive {
errs = append(errs, path.NewErrorf("sensitive planned value for a non-computed attribute"))
} else {
errs = append(errs, path.NewErrorf("planned value %#v for a non-computed attribute", plannedV))
}
return errs
}

// If this attribute has a NestedType, validate the nested object
Expand Down
26 changes: 26 additions & 0 deletions internal/plans/objchange/plan_valid_test.go
Expand Up @@ -1628,6 +1628,32 @@ func TestAssertPlanValid(t *testing.T) {
}),
[]string{`.map.one.name: planned value cty.StringVal("from_provider") does not match config value cty.StringVal("from_config")`},
},

// If a config value ended up in a computed-only attribute it can still
// be a valid plan. We either got here because the user ignore warnings
// about ignore_changes on computed attributes, or we failed to
// validate a config with computed values. Either way, we don't want to
// indicate an error with the provider.
"computed only value with config": {
&configschema.Block{
Attributes: map[string]*configschema.Attribute{
"a": {
Type: cty.String,
Computed: true,
},
},
},
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("old"),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.StringVal("old"),
}),
cty.ObjectVal(map[string]cty.Value{
"a": cty.UnknownVal(cty.String),
}),
nil,
},
}

for name, test := range tests {
Expand Down