mirror of
https://github.com/hashicorp/terraform.git
synced 2026-02-03 20:50:59 -05:00
add deprecation marks
This commit is contained in:
parent
8a615f93e9
commit
d813ad14f7
8 changed files with 321 additions and 13 deletions
|
|
@ -620,6 +620,7 @@ func SensitiveAsBool(val cty.Value) cty.Value {
|
||||||
func unmarkValueForMarshaling(v cty.Value) (unmarkedV cty.Value, sensitivePaths []cty.Path, err error) {
|
func unmarkValueForMarshaling(v cty.Value) (unmarkedV cty.Value, sensitivePaths []cty.Path, err error) {
|
||||||
val, pvms := v.UnmarkDeepWithPaths()
|
val, pvms := v.UnmarkDeepWithPaths()
|
||||||
sensitivePaths, otherMarks := marks.PathsWithMark(pvms, marks.Sensitive)
|
sensitivePaths, otherMarks := marks.PathsWithMark(pvms, marks.Sensitive)
|
||||||
|
_, otherMarks = marks.PathsWithMark(otherMarks, marks.Deprecation)
|
||||||
if len(otherMarks) != 0 {
|
if len(otherMarks) != 0 {
|
||||||
return cty.NilVal, nil, fmt.Errorf(
|
return cty.NilVal, nil, fmt.Errorf(
|
||||||
"%s: cannot serialize value marked as %#v for inclusion in a state snapshot (this is a bug in Terraform)",
|
"%s: cannot serialize value marked as %#v for inclusion in a state snapshot (this is a bug in Terraform)",
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
package marks
|
package marks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hashicorp/hcl/v2"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -17,16 +18,30 @@ func (m valueMark) GoString() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has returns true if and only if the cty.Value has the given mark.
|
// Has returns true if and only if the cty.Value has the given mark.
|
||||||
func Has(val cty.Value, mark valueMark) bool {
|
func Has(val cty.Value, mark interface{}) bool {
|
||||||
return val.HasMark(mark)
|
switch m := mark.(type) {
|
||||||
|
case valueMark:
|
||||||
|
return val.HasMark(m)
|
||||||
|
|
||||||
|
// For value marks Has returns true if a mark of the type is present
|
||||||
|
case DeprecationMark:
|
||||||
|
for depMark := range val.Marks() {
|
||||||
|
if _, ok := depMark.(DeprecationMark); ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
panic("Unknown mark type")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contains returns true if the cty.Value or any any value within it contains
|
// Contains returns true if the cty.Value or any any value within it contains
|
||||||
// the given mark.
|
// the given mark.
|
||||||
func Contains(val cty.Value, mark valueMark) bool {
|
func Contains(val cty.Value, mark interface{}) bool {
|
||||||
ret := false
|
ret := false
|
||||||
cty.Walk(val, func(_ cty.Path, v cty.Value) (bool, error) {
|
cty.Walk(val, func(_ cty.Path, v cty.Value) (bool, error) {
|
||||||
if v.HasMark(mark) {
|
if Has(v, mark) {
|
||||||
ret = true
|
ret = true
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
@ -35,6 +50,33 @@ func Contains(val cty.Value, mark valueMark) bool {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterDeprecationMarks returns all deprecation marks present in the given
|
||||||
|
// cty.ValueMarks.
|
||||||
|
func FilterDeprecationMarks(marks cty.ValueMarks) []DeprecationMark {
|
||||||
|
depMarks := []DeprecationMark{}
|
||||||
|
for mark := range marks {
|
||||||
|
if d, ok := mark.(DeprecationMark); ok {
|
||||||
|
depMarks = append(depMarks, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return depMarks
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDeprecationMarks returns all deprecation marks present on the given
|
||||||
|
// cty.Value.
|
||||||
|
func GetDeprecationMarks(val cty.Value) []DeprecationMark {
|
||||||
|
_, marks := val.UnmarkDeep()
|
||||||
|
return FilterDeprecationMarks(marks)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveDeprecationMarks returns a copy of the given cty.Value with all
|
||||||
|
// deprecation marks removed.
|
||||||
|
func RemoveDeprecationMarks(val cty.Value) cty.Value {
|
||||||
|
newVal, pvms := val.UnmarkDeepWithPaths()
|
||||||
|
otherPvms := RemoveAll(pvms, Deprecation)
|
||||||
|
return newVal.MarkWithPaths(otherPvms)
|
||||||
|
}
|
||||||
|
|
||||||
// Sensitive indicates that this value is marked as sensitive in the context of
|
// Sensitive indicates that this value is marked as sensitive in the context of
|
||||||
// Terraform.
|
// Terraform.
|
||||||
const Sensitive = valueMark("Sensitive")
|
const Sensitive = valueMark("Sensitive")
|
||||||
|
|
@ -51,3 +93,22 @@ const Ephemeral = valueMark("Ephemeral")
|
||||||
// another value's type. This is part of the implementation of the console-only
|
// another value's type. This is part of the implementation of the console-only
|
||||||
// `type` function.
|
// `type` function.
|
||||||
const TypeType = valueMark("TypeType")
|
const TypeType = valueMark("TypeType")
|
||||||
|
|
||||||
|
type DeprecationMark struct {
|
||||||
|
Message string
|
||||||
|
Origin *hcl.Range
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d DeprecationMark) GoString() string {
|
||||||
|
return "marks.deprecation<" + d.Message + ">"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty deprecation mark for usage in marks.Has / Contains / etc
|
||||||
|
var Deprecation = NewDeprecation("", nil)
|
||||||
|
|
||||||
|
func NewDeprecation(message string, origin *hcl.Range) DeprecationMark {
|
||||||
|
return DeprecationMark{
|
||||||
|
Message: message,
|
||||||
|
Origin: origin,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
52
internal/lang/marks/marks_test.go
Normal file
52
internal/lang/marks/marks_test.go
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
// Copyright (c) HashiCorp, Inc.
|
||||||
|
// SPDX-License-Identifier: BUSL-1.1
|
||||||
|
|
||||||
|
package marks
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/hcl/v2"
|
||||||
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDeprecationMark(t *testing.T) {
|
||||||
|
deprecationWithoutRange := cty.StringVal("OldValue").Mark(NewDeprecation("This is outdated", nil))
|
||||||
|
deprecationWithRange := cty.StringVal("OldValue").Mark(NewDeprecation("This is outdated", &hcl.Range{Filename: "example.tf", Start: hcl.Pos{Line: 1, Column: 1}, End: hcl.Pos{Line: 1, Column: 10}}))
|
||||||
|
|
||||||
|
composite := cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": deprecationWithRange,
|
||||||
|
"bar": deprecationWithoutRange,
|
||||||
|
"baz": cty.StringVal("Not deprecated"),
|
||||||
|
})
|
||||||
|
|
||||||
|
if !deprecationWithRange.IsMarked() {
|
||||||
|
t.Errorf("Expected deprecationWithRange to be marked")
|
||||||
|
}
|
||||||
|
if !deprecationWithoutRange.IsMarked() {
|
||||||
|
t.Errorf("Expected deprecationWithoutRange to be marked")
|
||||||
|
}
|
||||||
|
if composite.IsMarked() {
|
||||||
|
t.Errorf("Expected composite to be marked")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !Has(deprecationWithRange, Deprecation) {
|
||||||
|
t.Errorf("Expected deprecationWithRange to be marked with Deprecation")
|
||||||
|
}
|
||||||
|
if !Has(deprecationWithoutRange, Deprecation) {
|
||||||
|
t.Errorf("Expected deprecationWithoutRange to be marked with Deprecation")
|
||||||
|
}
|
||||||
|
if Has(composite, Deprecation) {
|
||||||
|
t.Errorf("Expected composite to be marked with Deprecation")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !Contains(deprecationWithRange, Deprecation) {
|
||||||
|
t.Errorf("Expected deprecationWithRange to be contain Deprecation Mark")
|
||||||
|
}
|
||||||
|
if !Contains(deprecationWithoutRange, Deprecation) {
|
||||||
|
t.Errorf("Expected deprecationWithoutRange to be contain Deprecation Mark")
|
||||||
|
}
|
||||||
|
if !Contains(composite, Deprecation) {
|
||||||
|
t.Errorf("Expected composite to be contain Deprecation Mark")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
package marks
|
package marks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
|
@ -28,16 +29,36 @@ func PathsWithMark(pvms []cty.PathValueMarks, wantMark any) (withWanted []cty.Pa
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pvm := range pvms {
|
for _, pvm := range pvms {
|
||||||
if _, ok := pvm.Marks[wantMark]; ok {
|
pathHasMark := false
|
||||||
|
pathHasOtherMarks := false
|
||||||
|
for mark := range pvm.Marks {
|
||||||
|
switch wantMark.(type) {
|
||||||
|
case valueMark, string:
|
||||||
|
if mark == wantMark {
|
||||||
|
pathHasMark = true
|
||||||
|
} else {
|
||||||
|
pathHasOtherMarks = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// For data marks we check if a mark of the type exists
|
||||||
|
case DeprecationMark:
|
||||||
|
if _, ok := mark.(DeprecationMark); ok {
|
||||||
|
pathHasMark = true
|
||||||
|
} else {
|
||||||
|
pathHasOtherMarks = true
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unexpected mark type %T", wantMark))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pathHasMark {
|
||||||
withWanted = append(withWanted, pvm.Path)
|
withWanted = append(withWanted, pvm.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
for mark := range pvm.Marks {
|
if pathHasOtherMarks {
|
||||||
if mark != wantMark {
|
withOthers = append(withOthers, pvm)
|
||||||
withOthers = append(withOthers, pvm)
|
|
||||||
// only add a path with unwanted marks a single time
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,7 +78,21 @@ func RemoveAll(pvms []cty.PathValueMarks, remove any) []cty.PathValueMarks {
|
||||||
var res []cty.PathValueMarks
|
var res []cty.PathValueMarks
|
||||||
|
|
||||||
for _, pvm := range pvms {
|
for _, pvm := range pvms {
|
||||||
delete(pvm.Marks, remove)
|
switch remove.(type) {
|
||||||
|
case valueMark, string:
|
||||||
|
delete(pvm.Marks, remove)
|
||||||
|
|
||||||
|
case DeprecationMark:
|
||||||
|
// We want to delete all marks of this type
|
||||||
|
for mark := range pvm.Marks {
|
||||||
|
if _, ok := mark.(DeprecationMark); ok {
|
||||||
|
delete(pvm.Marks, mark)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unexpected mark type %T", remove))
|
||||||
|
}
|
||||||
if len(pvm.Marks) > 0 {
|
if len(pvm.Marks) > 0 {
|
||||||
res = append(res, pvm)
|
res = append(res, pvm)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/hashicorp/hcl/v2"
|
||||||
"github.com/zclconf/go-cty-debug/ctydebug"
|
"github.com/zclconf/go-cty-debug/ctydebug"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
@ -30,12 +31,25 @@ func TestPathsWithMark(t *testing.T) {
|
||||||
Path: cty.GetAttrPath("neither"),
|
Path: cty.GetAttrPath("neither"),
|
||||||
Marks: cty.NewValueMarks("x", "y"),
|
Marks: cty.NewValueMarks("x", "y"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("deprecated"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("multipleDeprecations"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
gotPaths, gotOthers := PathsWithMark(input, "sensitive")
|
gotPaths, gotOthers := PathsWithMark(input, "sensitive")
|
||||||
wantPaths := []cty.Path{
|
wantPaths := []cty.Path{
|
||||||
cty.GetAttrPath("sensitive"),
|
cty.GetAttrPath("sensitive"),
|
||||||
cty.GetAttrPath("both"),
|
cty.GetAttrPath("both"),
|
||||||
|
cty.GetAttrPath("multipleDeprecationsAndSensitive"),
|
||||||
}
|
}
|
||||||
wantOthers := []cty.PathValueMarks{
|
wantOthers := []cty.PathValueMarks{
|
||||||
{
|
{
|
||||||
|
|
@ -56,6 +70,18 @@ func TestPathsWithMark(t *testing.T) {
|
||||||
Path: cty.GetAttrPath("neither"),
|
Path: cty.GetAttrPath("neither"),
|
||||||
Marks: cty.NewValueMarks("x", "y"),
|
Marks: cty.NewValueMarks("x", "y"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("deprecated"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("multipleDeprecations"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if diff := cmp.Diff(wantPaths, gotPaths, ctydebug.CmpOptions); diff != "" {
|
if diff := cmp.Diff(wantPaths, gotPaths, ctydebug.CmpOptions); diff != "" {
|
||||||
|
|
@ -64,9 +90,46 @@ func TestPathsWithMark(t *testing.T) {
|
||||||
if diff := cmp.Diff(wantOthers, gotOthers, ctydebug.CmpOptions); diff != "" {
|
if diff := cmp.Diff(wantOthers, gotOthers, ctydebug.CmpOptions); diff != "" {
|
||||||
t.Errorf("wrong set of entries with other marks\n%s", diff)
|
t.Errorf("wrong set of entries with other marks\n%s", diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gotPaths, gotOthers = PathsWithMark(input, Deprecation)
|
||||||
|
|
||||||
|
wantPaths = []cty.Path{
|
||||||
|
cty.GetAttrPath("deprecated"),
|
||||||
|
cty.GetAttrPath("multipleDeprecations"),
|
||||||
|
cty.GetAttrPath("multipleDeprecationsAndSensitive"),
|
||||||
|
}
|
||||||
|
wantOthers = []cty.PathValueMarks{
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("sensitive"),
|
||||||
|
Marks: cty.NewValueMarks("sensitive"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("other"),
|
||||||
|
Marks: cty.NewValueMarks("other"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("both"),
|
||||||
|
Marks: cty.NewValueMarks("sensitive", "other"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("neither"),
|
||||||
|
Marks: cty.NewValueMarks("x", "y"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if diff := cmp.Diff(wantPaths, gotPaths, ctydebug.CmpOptions); diff != "" {
|
||||||
|
t.Errorf("wrong matched deprecation paths\n%s", diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(wantOthers, gotOthers, ctydebug.CmpOptions); diff != "" {
|
||||||
|
t.Errorf("wrong set of entries with other than deprecation marks\n%s", diff)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveAll(t *testing.T) {
|
func TestRemoveAll_valueMarks(t *testing.T) {
|
||||||
input := []cty.PathValueMarks{
|
input := []cty.PathValueMarks{
|
||||||
{
|
{
|
||||||
Path: cty.GetAttrPath("sensitive"),
|
Path: cty.GetAttrPath("sensitive"),
|
||||||
|
|
@ -100,6 +163,36 @@ func TestRemoveAll(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveAll_dataMarks(t *testing.T) {
|
||||||
|
input := []cty.PathValueMarks{
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("deprecated"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("multipleDeprecations"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"),
|
||||||
|
Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
want := []cty.PathValueMarks{
|
||||||
|
{
|
||||||
|
Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"),
|
||||||
|
Marks: cty.NewValueMarks("sensitive"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
got := RemoveAll(input, Deprecation)
|
||||||
|
|
||||||
|
if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" {
|
||||||
|
t.Errorf("wrong matched paths\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMarkPaths(t *testing.T) {
|
func TestMarkPaths(t *testing.T) {
|
||||||
value := cty.ObjectVal(map[string]cty.Value{
|
value := cty.ObjectVal(map[string]cty.Value{
|
||||||
"s": cty.StringVal(".s"),
|
"s": cty.StringVal(".s"),
|
||||||
|
|
@ -150,6 +243,38 @@ func TestMarkPaths(t *testing.T) {
|
||||||
if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" {
|
if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" {
|
||||||
t.Errorf("wrong result\n%s", diff)
|
t.Errorf("wrong result\n%s", diff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deprecatedPaths := []cty.Path{
|
||||||
|
cty.GetAttrPath("s"),
|
||||||
|
cty.GetAttrPath("l").IndexInt(1),
|
||||||
|
cty.GetAttrPath("m").IndexString("a"),
|
||||||
|
cty.GetAttrPath("o").GetAttr("b"),
|
||||||
|
cty.GetAttrPath("t").IndexInt(0),
|
||||||
|
}
|
||||||
|
deprecationMark := NewDeprecation("this is deprecated", nil)
|
||||||
|
got = MarkPaths(value, deprecationMark, deprecatedPaths)
|
||||||
|
want = cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"s": cty.StringVal(".s").Mark(deprecationMark),
|
||||||
|
"l": cty.ListVal([]cty.Value{
|
||||||
|
cty.StringVal(".l[0]"),
|
||||||
|
cty.StringVal(".l[1]").Mark(deprecationMark),
|
||||||
|
}),
|
||||||
|
"m": cty.MapVal(map[string]cty.Value{
|
||||||
|
"a": cty.StringVal(`.m["a"]`).Mark(deprecationMark),
|
||||||
|
"b": cty.StringVal(`.m["b"]`),
|
||||||
|
}),
|
||||||
|
"o": cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.StringVal(".o.a"),
|
||||||
|
"b": cty.StringVal(".o.b").Mark(deprecationMark),
|
||||||
|
}),
|
||||||
|
"t": cty.TupleVal([]cty.Value{
|
||||||
|
cty.StringVal(`.t[0]`).Mark(deprecationMark),
|
||||||
|
cty.StringVal(`.t[1]`),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" {
|
||||||
|
t.Errorf("wrong result\n%s", diff)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarksEqual(t *testing.T) {
|
func TestMarksEqual(t *testing.T) {
|
||||||
|
|
@ -239,6 +364,33 @@ func TestMarksEqual(t *testing.T) {
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
[]cty.PathValueMarks{
|
||||||
|
{Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", nil))},
|
||||||
|
},
|
||||||
|
[]cty.PathValueMarks{
|
||||||
|
{Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", nil))},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]cty.PathValueMarks{
|
||||||
|
{Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("different", nil))},
|
||||||
|
},
|
||||||
|
[]cty.PathValueMarks{
|
||||||
|
{Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("message", nil))},
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[]cty.PathValueMarks{
|
||||||
|
{Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", &hcl.Range{Filename: "test.tf", Start: hcl.Pos{Line: 1, Column: 1}, End: hcl.Pos{Line: 1, Column: 1}}))},
|
||||||
|
},
|
||||||
|
[]cty.PathValueMarks{
|
||||||
|
{Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", &hcl.Range{Filename: "otherFile.tf", Start: hcl.Pos{Line: 1, Column: 1}, End: hcl.Pos{Line: 1, Column: 1}}))},
|
||||||
|
},
|
||||||
|
false, // TODO: Should this really be different?
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||||
if MarksEqual(tc.a, tc.b) != tc.equal {
|
if MarksEqual(tc.a, tc.b) != tc.equal {
|
||||||
|
|
|
||||||
|
|
@ -743,6 +743,7 @@ type Change struct {
|
||||||
func (c *Change) Encode(schema *providers.Schema) (*ChangeSrc, error) {
|
func (c *Change) Encode(schema *providers.Schema) (*ChangeSrc, error) {
|
||||||
// We can't serialize value marks directly so we'll need to extract the
|
// We can't serialize value marks directly so we'll need to extract the
|
||||||
// sensitive marks and store them in a separate field.
|
// sensitive marks and store them in a separate field.
|
||||||
|
// We ignore Deprecation marks.
|
||||||
//
|
//
|
||||||
// We don't accept any other marks here. The caller should have dealt
|
// We don't accept any other marks here. The caller should have dealt
|
||||||
// with those somehow and replaced them with unmarked placeholders before
|
// with those somehow and replaced them with unmarked placeholders before
|
||||||
|
|
@ -751,6 +752,10 @@ func (c *Change) Encode(schema *providers.Schema) (*ChangeSrc, error) {
|
||||||
unmarkedAfter, marksesAfter := c.After.UnmarkDeepWithPaths()
|
unmarkedAfter, marksesAfter := c.After.UnmarkDeepWithPaths()
|
||||||
sensitiveAttrsBefore, unsupportedMarksesBefore := marks.PathsWithMark(marksesBefore, marks.Sensitive)
|
sensitiveAttrsBefore, unsupportedMarksesBefore := marks.PathsWithMark(marksesBefore, marks.Sensitive)
|
||||||
sensitiveAttrsAfter, unsupportedMarksesAfter := marks.PathsWithMark(marksesAfter, marks.Sensitive)
|
sensitiveAttrsAfter, unsupportedMarksesAfter := marks.PathsWithMark(marksesAfter, marks.Sensitive)
|
||||||
|
|
||||||
|
_, unsupportedMarksesBefore = marks.PathsWithMark(unsupportedMarksesBefore, marks.Deprecation)
|
||||||
|
_, unsupportedMarksesAfter = marks.PathsWithMark(unsupportedMarksesAfter, marks.Deprecation)
|
||||||
|
|
||||||
if len(unsupportedMarksesBefore) != 0 {
|
if len(unsupportedMarksesBefore) != 0 {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"prior value %s: can't serialize value marked with %#v (this is a bug in Terraform)",
|
"prior value %s: can't serialize value marked with %#v (this is a bug in Terraform)",
|
||||||
|
|
|
||||||
|
|
@ -499,6 +499,7 @@ func (pc *PlannedChangeResourceInstancePlanned) ChangeDescription() (*stacks.Pla
|
||||||
func DynamicValueToTerraform1(val cty.Value, ty cty.Type) (*stacks.DynamicValue, error) {
|
func DynamicValueToTerraform1(val cty.Value, ty cty.Type) (*stacks.DynamicValue, error) {
|
||||||
unmarkedVal, markPaths := val.UnmarkDeepWithPaths()
|
unmarkedVal, markPaths := val.UnmarkDeepWithPaths()
|
||||||
sensitivePaths, withOtherMarks := marks.PathsWithMark(markPaths, marks.Sensitive)
|
sensitivePaths, withOtherMarks := marks.PathsWithMark(markPaths, marks.Sensitive)
|
||||||
|
_, withOtherMarks = marks.PathsWithMark(withOtherMarks, marks.Sensitive)
|
||||||
if len(withOtherMarks) != 0 {
|
if len(withOtherMarks) != 0 {
|
||||||
return nil, withOtherMarks[0].Path.NewErrorf(
|
return nil, withOtherMarks[0].Path.NewErrorf(
|
||||||
"can't serialize value marked with %#v (this is a bug in Terraform)",
|
"can't serialize value marked with %#v (this is a bug in Terraform)",
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,7 @@ func (o *ResourceInstanceObject) AsTainted() *ResourceInstanceObject {
|
||||||
func unmarkValueForStorage(v cty.Value) (unmarkedV cty.Value, sensitivePaths []cty.Path, err error) {
|
func unmarkValueForStorage(v cty.Value) (unmarkedV cty.Value, sensitivePaths []cty.Path, err error) {
|
||||||
val, pvms := v.UnmarkDeepWithPaths()
|
val, pvms := v.UnmarkDeepWithPaths()
|
||||||
sensitivePaths, withOtherMarks := marks.PathsWithMark(pvms, marks.Sensitive)
|
sensitivePaths, withOtherMarks := marks.PathsWithMark(pvms, marks.Sensitive)
|
||||||
|
_, withOtherMarks = marks.PathsWithMark(withOtherMarks, marks.Deprecation)
|
||||||
if len(withOtherMarks) != 0 {
|
if len(withOtherMarks) != 0 {
|
||||||
return cty.NilVal, nil, fmt.Errorf(
|
return cty.NilVal, nil, fmt.Errorf(
|
||||||
"%s: cannot serialize value marked as %#v for inclusion in a state snapshot (this is a bug in Terraform)",
|
"%s: cannot serialize value marked as %#v for inclusion in a state snapshot (this is a bug in Terraform)",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue