From 9a4b90c3300094b3ccee14a17e03aacd3df8f47b Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Thu, 11 Dec 2025 13:27:44 +0100 Subject: [PATCH 1/2] add deprecation marks --- internal/command/jsonstate/state.go | 1 + internal/lang/marks/marks.go | 69 ++++++++- internal/lang/marks/marks_test.go | 52 +++++++ internal/lang/marks/paths.go | 51 ++++++- internal/lang/marks/paths_test.go | 154 +++++++++++++++++++- internal/plans/changes.go | 5 + internal/stacks/stackplan/planned_change.go | 1 + internal/states/instance_object.go | 1 + 8 files changed, 321 insertions(+), 13 deletions(-) create mode 100644 internal/lang/marks/marks_test.go diff --git a/internal/command/jsonstate/state.go b/internal/command/jsonstate/state.go index a29e0ebba57f..ca98e98bae48 100644 --- a/internal/command/jsonstate/state.go +++ b/internal/command/jsonstate/state.go @@ -620,6 +620,7 @@ func SensitiveAsBool(val cty.Value) cty.Value { func unmarkValueForMarshaling(v cty.Value) (unmarkedV cty.Value, sensitivePaths []cty.Path, err error) { val, pvms := v.UnmarkDeepWithPaths() sensitivePaths, otherMarks := marks.PathsWithMark(pvms, marks.Sensitive) + _, otherMarks = marks.PathsWithMark(otherMarks, marks.Deprecation) if len(otherMarks) != 0 { 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)", diff --git a/internal/lang/marks/marks.go b/internal/lang/marks/marks.go index 7ba2752d2286..1d763e0b8011 100644 --- a/internal/lang/marks/marks.go +++ b/internal/lang/marks/marks.go @@ -4,6 +4,7 @@ package marks import ( + "github.com/hashicorp/hcl/v2" "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. -func Has(val cty.Value, mark valueMark) bool { - return val.HasMark(mark) +func Has(val cty.Value, mark interface{}) bool { + 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 // the given mark. -func Contains(val cty.Value, mark valueMark) bool { +func Contains(val cty.Value, mark interface{}) bool { ret := false cty.Walk(val, func(_ cty.Path, v cty.Value) (bool, error) { - if v.HasMark(mark) { + if Has(v, mark) { ret = true return false, nil } @@ -35,6 +50,33 @@ func Contains(val cty.Value, mark valueMark) bool { 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 // Terraform. 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 // `type` function. 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, + } +} diff --git a/internal/lang/marks/marks_test.go b/internal/lang/marks/marks_test.go new file mode 100644 index 000000000000..1e5f2a71f7a6 --- /dev/null +++ b/internal/lang/marks/marks_test.go @@ -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") + } +} diff --git a/internal/lang/marks/paths.go b/internal/lang/marks/paths.go index 0bb81ae43b16..4cdcde85ed92 100644 --- a/internal/lang/marks/paths.go +++ b/internal/lang/marks/paths.go @@ -4,6 +4,7 @@ package marks import ( + "fmt" "sort" "strings" @@ -28,16 +29,36 @@ func PathsWithMark(pvms []cty.PathValueMarks, wantMark any) (withWanted []cty.Pa } 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) } - for mark := range pvm.Marks { - if mark != wantMark { - withOthers = append(withOthers, pvm) - // only add a path with unwanted marks a single time - break - } + if pathHasOtherMarks { + withOthers = append(withOthers, pvm) } } @@ -57,7 +78,21 @@ func RemoveAll(pvms []cty.PathValueMarks, remove any) []cty.PathValueMarks { var res []cty.PathValueMarks 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 { res = append(res, pvm) } diff --git a/internal/lang/marks/paths_test.go b/internal/lang/marks/paths_test.go index f6adf437e388..e441c398e09d 100644 --- a/internal/lang/marks/paths_test.go +++ b/internal/lang/marks/paths_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/hashicorp/hcl/v2" "github.com/zclconf/go-cty-debug/ctydebug" "github.com/zclconf/go-cty/cty" ) @@ -30,12 +31,25 @@ func TestPathsWithMark(t *testing.T) { Path: cty.GetAttrPath("neither"), 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") wantPaths := []cty.Path{ cty.GetAttrPath("sensitive"), cty.GetAttrPath("both"), + cty.GetAttrPath("multipleDeprecationsAndSensitive"), } wantOthers := []cty.PathValueMarks{ { @@ -56,6 +70,18 @@ func TestPathsWithMark(t *testing.T) { Path: cty.GetAttrPath("neither"), 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 != "" { @@ -64,9 +90,46 @@ func TestPathsWithMark(t *testing.T) { if diff := cmp.Diff(wantOthers, gotOthers, ctydebug.CmpOptions); 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{ { 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) { value := cty.ObjectVal(map[string]cty.Value{ "s": cty.StringVal(".s"), @@ -150,6 +243,38 @@ func TestMarkPaths(t *testing.T) { if diff := cmp.Diff(want, got, ctydebug.CmpOptions); 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) { @@ -239,6 +364,33 @@ func TestMarksEqual(t *testing.T) { }, 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) { if MarksEqual(tc.a, tc.b) != tc.equal { diff --git a/internal/plans/changes.go b/internal/plans/changes.go index ca362054b79d..29b5b80d3921 100644 --- a/internal/plans/changes.go +++ b/internal/plans/changes.go @@ -743,6 +743,7 @@ type Change struct { func (c *Change) Encode(schema *providers.Schema) (*ChangeSrc, error) { // We can't serialize value marks directly so we'll need to extract the // 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 // 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() sensitiveAttrsBefore, unsupportedMarksesBefore := marks.PathsWithMark(marksesBefore, 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 { return nil, fmt.Errorf( "prior value %s: can't serialize value marked with %#v (this is a bug in Terraform)", diff --git a/internal/stacks/stackplan/planned_change.go b/internal/stacks/stackplan/planned_change.go index 7cb8888ca95e..fb458d685d9c 100644 --- a/internal/stacks/stackplan/planned_change.go +++ b/internal/stacks/stackplan/planned_change.go @@ -499,6 +499,7 @@ func (pc *PlannedChangeResourceInstancePlanned) ChangeDescription() (*stacks.Pla func DynamicValueToTerraform1(val cty.Value, ty cty.Type) (*stacks.DynamicValue, error) { unmarkedVal, markPaths := val.UnmarkDeepWithPaths() sensitivePaths, withOtherMarks := marks.PathsWithMark(markPaths, marks.Sensitive) + _, withOtherMarks = marks.PathsWithMark(withOtherMarks, marks.Sensitive) if len(withOtherMarks) != 0 { return nil, withOtherMarks[0].Path.NewErrorf( "can't serialize value marked with %#v (this is a bug in Terraform)", diff --git a/internal/states/instance_object.go b/internal/states/instance_object.go index 82a4ab1e2540..f9ce435b6872 100644 --- a/internal/states/instance_object.go +++ b/internal/states/instance_object.go @@ -205,6 +205,7 @@ func (o *ResourceInstanceObject) AsTainted() *ResourceInstanceObject { func unmarkValueForStorage(v cty.Value) (unmarkedV cty.Value, sensitivePaths []cty.Path, err error) { val, pvms := v.UnmarkDeepWithPaths() sensitivePaths, withOtherMarks := marks.PathsWithMark(pvms, marks.Sensitive) + _, withOtherMarks = marks.PathsWithMark(withOtherMarks, marks.Deprecation) if len(withOtherMarks) != 0 { 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)", From 5c898c6d9ad7f0b81d006c04f6b035ce9afb48b0 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Fri, 12 Dec 2025 14:26:30 +0100 Subject: [PATCH 2/2] remove deprecation origin for now we will add sth like this again when we will be able display a nicer diagnostic with the origin --- internal/lang/marks/marks.go | 9 ++++---- internal/lang/marks/marks_test.go | 29 ++++++++---------------- internal/lang/marks/paths_test.go | 37 +++++++++++++++---------------- 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/internal/lang/marks/marks.go b/internal/lang/marks/marks.go index 1d763e0b8011..54850ca00dad 100644 --- a/internal/lang/marks/marks.go +++ b/internal/lang/marks/marks.go @@ -4,7 +4,6 @@ package marks import ( - "github.com/hashicorp/hcl/v2" "github.com/zclconf/go-cty/cty" ) @@ -94,9 +93,10 @@ const Ephemeral = valueMark("Ephemeral") // `type` function. const TypeType = valueMark("TypeType") +// DeprecationMark is a mark indicating that a value is deprecated. It is a struct +// rather than a primitive type so that it can carry a deprecation message. type DeprecationMark struct { Message string - Origin *hcl.Range } func (d DeprecationMark) GoString() string { @@ -104,11 +104,10 @@ func (d DeprecationMark) GoString() string { } // Empty deprecation mark for usage in marks.Has / Contains / etc -var Deprecation = NewDeprecation("", nil) +var Deprecation = NewDeprecation("") -func NewDeprecation(message string, origin *hcl.Range) DeprecationMark { +func NewDeprecation(message string) DeprecationMark { return DeprecationMark{ Message: message, - Origin: origin, } } diff --git a/internal/lang/marks/marks_test.go b/internal/lang/marks/marks_test.go index 1e5f2a71f7a6..8190385d27c1 100644 --- a/internal/lang/marks/marks_test.go +++ b/internal/lang/marks/marks_test.go @@ -6,45 +6,34 @@ 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}})) + deprecation := cty.StringVal("OldValue").Mark(NewDeprecation("This is outdated")) composite := cty.ObjectVal(map[string]cty.Value{ - "foo": deprecationWithRange, - "bar": deprecationWithoutRange, + "foo": deprecation, + "bar": deprecation, "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 !deprecation.IsMarked() { + t.Errorf("Expected deprecation 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(deprecation, Deprecation) { + t.Errorf("Expected deprecation 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(deprecation, Deprecation) { + t.Errorf("Expected deprecation to be contain Deprecation Mark") } if !Contains(composite, Deprecation) { t.Errorf("Expected composite to be contain Deprecation Mark") diff --git a/internal/lang/marks/paths_test.go b/internal/lang/marks/paths_test.go index e441c398e09d..3d21689dbb1a 100644 --- a/internal/lang/marks/paths_test.go +++ b/internal/lang/marks/paths_test.go @@ -8,7 +8,6 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/hashicorp/hcl/v2" "github.com/zclconf/go-cty-debug/ctydebug" "github.com/zclconf/go-cty/cty" ) @@ -33,15 +32,15 @@ func TestPathsWithMark(t *testing.T) { }, { Path: cty.GetAttrPath("deprecated"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated")), }, { Path: cty.GetAttrPath("multipleDeprecations"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated"), NewDeprecation("this is also deprecated")), }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated"), NewDeprecation("this is also deprecated"), "sensitive"), }, } @@ -72,15 +71,15 @@ func TestPathsWithMark(t *testing.T) { }, { Path: cty.GetAttrPath("deprecated"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated")), }, { Path: cty.GetAttrPath("multipleDeprecations"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated"), NewDeprecation("this is also deprecated")), }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated"), NewDeprecation("this is also deprecated"), "sensitive"), }, } @@ -117,7 +116,7 @@ func TestPathsWithMark(t *testing.T) { }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated"), NewDeprecation("this is also deprecated"), "sensitive"), }, } @@ -167,15 +166,15 @@ func TestRemoveAll_dataMarks(t *testing.T) { input := []cty.PathValueMarks{ { Path: cty.GetAttrPath("deprecated"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated")), }, { Path: cty.GetAttrPath("multipleDeprecations"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil)), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated"), NewDeprecation("this is also deprecated")), }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", nil), NewDeprecation("this is also deprecated", nil), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated"), NewDeprecation("this is also deprecated"), "sensitive"), }, } @@ -251,7 +250,7 @@ func TestMarkPaths(t *testing.T) { cty.GetAttrPath("o").GetAttr("b"), cty.GetAttrPath("t").IndexInt(0), } - deprecationMark := NewDeprecation("this is deprecated", nil) + deprecationMark := NewDeprecation("this is deprecated") got = MarkPaths(value, deprecationMark, deprecatedPaths) want = cty.ObjectVal(map[string]cty.Value{ "s": cty.StringVal(".s").Mark(deprecationMark), @@ -366,30 +365,30 @@ func TestMarksEqual(t *testing.T) { }, { []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message"))}, }, []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message"))}, }, true, }, { []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("different", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("different"))}, }, []cty.PathValueMarks{ - {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("message", nil))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("message"))}, }, 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}}))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message"))}, }, []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}}))}, + {Path: cty.Path{cty.GetAttrStep{Name: "a"}}, Marks: cty.NewValueMarks(NewDeprecation("same message"))}, }, - false, // TODO: Should this really be different? + true, }, } { t.Run(fmt.Sprint(i), func(t *testing.T) {