prevent panic when input or output variables are sensitive

pull/35774/head
UKEME BASSEY 2 years ago
parent 55d4cbb00a
commit d89ee04e9e

@ -4,6 +4,9 @@
package marks
import (
"fmt"
"sort"
"github.com/zclconf/go-cty/cty"
)
@ -60,3 +63,34 @@ func MarkPaths(val cty.Value, mark any, paths []cty.Path) cty.Value {
}
return val.MarkWithPaths(markses)
}
// MarksEqual compares 2 unordered sets of PathValue marks for equality, with
// the comparison using the cty.PathValueMarks.Equal method.
func MarksEqual(a, b []cty.PathValueMarks) bool {
if len(a) == 0 && len(b) == 0 {
return true
}
if len(a) != len(b) {
return false
}
less := func(s []cty.PathValueMarks) func(i, j int) bool {
return func(i, j int) bool {
// the sort only needs to be consistent, so use the GoString format
// to get a comparable value
return fmt.Sprintf("%#v", s[i]) < fmt.Sprintf("%#v", s[j])
}
}
sort.Slice(a, less(a))
sort.Slice(b, less(b))
for i := 0; i < len(a); i++ {
if !a[i].Equal(b[i]) {
return false
}
}
return true
}

@ -11,6 +11,7 @@ import (
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/convert"
"github.com/hashicorp/terraform/internal/lang/marks"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/plans/objchange"
"github.com/hashicorp/terraform/internal/promising"
@ -268,13 +269,17 @@ func (v *InputVariable) PlanChanges(ctx context.Context) ([]stackplan.PlannedCha
// we'll set the operation to an update even if the actual hasn't
// changed
action = plans.Update
} else if result := before.Equals(after); result.IsKnown() && result.True() {
// The values are definitely equal, so NoOp change.
action = plans.NoOp
} else {
// If we don't know for sure that the values are equal, then we'll
// call this an update.
action = plans.Update
unmarkedBefore, beforePaths := before.UnmarkDeepWithPaths()
unmarkedAfter, afterPaths := after.UnmarkDeepWithPaths()
result := unmarkedBefore.Equals(unmarkedAfter)
if result.IsKnown() && result.True() && marks.MarksEqual(beforePaths, afterPaths) {
action = plans.NoOp
} else {
// If we don't know for sure that the values are equal, then we'll
// call this an update.
action = plans.Update
}
}
} else {
action = plans.Create

@ -800,7 +800,10 @@ func (s *Stack) PlanChanges(ctx context.Context) ([]stackplan.PlannedChange, tfd
if actualBefore, exists := beforeVal[addr]; exists {
before = actualBefore
if result := before.Equals(after); result.IsKnown() && result.True() {
unmarkedBefore, beforePaths := before.UnmarkDeepWithPaths()
unmarkedAfter, afterPaths := after.UnmarkDeepWithPaths()
result := unmarkedBefore.Equals(unmarkedAfter)
if result.IsKnown() && result.True() && marks.MarksEqual(beforePaths, afterPaths) {
action = plans.NoOp
} else {
action = plans.Update

@ -4,9 +4,7 @@
package terraform
import (
"fmt"
"sort"
"github.com/hashicorp/terraform/internal/lang/marks"
"github.com/zclconf/go-cty/cty"
)
@ -14,36 +12,5 @@ import (
func valueMarksEqual(a, b cty.Value) bool {
_, aMarks := a.UnmarkDeepWithPaths()
_, bMarks := b.UnmarkDeepWithPaths()
return marksEqual(aMarks, bMarks)
}
// marksEqual compares 2 unordered sets of PathValue marks for equality, with
// the comparison using the cty.PathValueMarks.Equal method.
func marksEqual(a, b []cty.PathValueMarks) bool {
if len(a) == 0 && len(b) == 0 {
return true
}
if len(a) != len(b) {
return false
}
less := func(s []cty.PathValueMarks) func(i, j int) bool {
return func(i, j int) bool {
// the sort only needs to be consistent, so use the GoString format
// to get a comparable value
return fmt.Sprintf("%#v", s[i]) < fmt.Sprintf("%#v", s[j])
}
}
sort.Slice(a, less(a))
sort.Slice(b, less(b))
for i := 0; i < len(a); i++ {
if !a[i].Equal(b[i]) {
return false
}
}
return true
return marks.MarksEqual(aMarks, bMarks)
}

@ -2462,7 +2462,7 @@ func (n *NodeAbstractResourceInstance) apply(
// persisted.
eqV := unmarkedBefore.Equals(unmarkedAfter)
eq := eqV.IsKnown() && eqV.True()
if change.Action == plans.Update && eq && !marksEqual(beforePaths, afterPaths) {
if change.Action == plans.Update && eq && !marks.MarksEqual(beforePaths, afterPaths) {
// Copy the previous state, changing only the value
newState := &states.ResourceInstanceObject{
CreateBeforeDestroy: state.CreateBeforeDestroy,

Loading…
Cancel
Save