From 459a00e618ce799071bb2f38611dae0d1aaaa095 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Mon, 22 Jul 2024 11:48:30 +0200 Subject: [PATCH 1/2] config generation: stop editing the original schema when filtering --- internal/configs/configschema/copy.go | 68 ++++++++++++++++++++ internal/configs/configschema/filter.go | 10 +-- internal/configs/configschema/filter_test.go | 9 ++- 3 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 internal/configs/configschema/copy.go diff --git a/internal/configs/configschema/copy.go b/internal/configs/configschema/copy.go new file mode 100644 index 000000000000..862e4b69f06c --- /dev/null +++ b/internal/configs/configschema/copy.go @@ -0,0 +1,68 @@ +package configschema + +// DeepCopy returns a deep copy of the schema. +func (b *Block) DeepCopy() *Block { + block := &Block{ + Description: b.Description, + DescriptionKind: b.DescriptionKind, + Deprecated: b.Deprecated, + } + + if b.Attributes != nil { + block.Attributes = make(map[string]*Attribute, len(b.Attributes)) + } + for name, a := range b.Attributes { + block.Attributes[name] = a.DeepCopy() + } + + if b.BlockTypes != nil { + block.BlockTypes = make(map[string]*NestedBlock, len(b.BlockTypes)) + } + for name, bt := range b.BlockTypes { + inner := bt.Block.DeepCopy() + block.BlockTypes[name] = &NestedBlock{ + Block: *inner, + Nesting: bt.Nesting, + MinItems: bt.MinItems, + MaxItems: bt.MaxItems, + } + } + + return block +} + +// DeepCopy returns a deep copy of the schema. +func (a *Attribute) DeepCopy() *Attribute { + attr := &Attribute{ + Type: a.Type, + Description: a.Description, + DescriptionKind: a.DescriptionKind, + Deprecated: a.Deprecated, + Required: a.Required, + Computed: a.Computed, + Optional: a.Optional, + Sensitive: a.Sensitive, + + // NestedType is not copied here because it will be copied + // separately if it is set. + NestedType: nil, + } + if a.NestedType != nil { + attr.NestedType = a.NestedType.DeepCopy() + } + return attr +} + +// DeepCopy returns a deep copy of the schema. +func (o *Object) DeepCopy() *Object { + object := &Object{ + Nesting: o.Nesting, + } + if o.Attributes != nil { + object.Attributes = make(map[string]*Attribute, len(o.Attributes)) + for name, a := range o.Attributes { + object.Attributes[name] = a.DeepCopy() + } + } + return object +} diff --git a/internal/configs/configschema/filter.go b/internal/configs/configschema/filter.go index e8abd17c03cd..3d05558f4941 100644 --- a/internal/configs/configschema/filter.go +++ b/internal/configs/configschema/filter.go @@ -56,10 +56,11 @@ func (b *Block) filter(path cty.Path, filterAttribute FilterT[*Attribute], filte for name, attrS := range b.Attributes { path := path.GetAttr(name) if filterAttribute == nil || !filterAttribute(path, attrS) { - ret.Attributes[name] = attrS + attr := *attrS if attrS.NestedType != nil { - ret.Attributes[name].NestedType = filterNestedType(attrS.NestedType, path, filterAttribute) + attr.NestedType = filterNestedType(attrS.NestedType, path, filterAttribute) } + ret.Attributes[name] = &attr } } @@ -95,10 +96,11 @@ func filterNestedType(obj *Object, path cty.Path, filterAttribute FilterT[*Attri for name, attrS := range obj.Attributes { path := path.GetAttr(name) if filterAttribute == nil || !filterAttribute(path, attrS) { - ret.Attributes[name] = attrS + attr := *attrS if attrS.NestedType != nil { - ret.Attributes[name].NestedType = filterNestedType(attrS.NestedType, path, filterAttribute) + attr.NestedType = filterNestedType(attrS.NestedType, path, filterAttribute) } + ret.Attributes[name] = &attr } } diff --git a/internal/configs/configschema/filter_test.go b/internal/configs/configschema/filter_test.go index b2666f0a40a3..979204cbfad3 100644 --- a/internal/configs/configschema/filter_test.go +++ b/internal/configs/configschema/filter_test.go @@ -278,9 +278,16 @@ func TestFilter(t *testing.T) { for name, tc := range testCases { t.Run(name, func(t *testing.T) { + original := tc.schema.DeepCopy() + got := tc.schema.Filter(tc.filterAttribute, tc.filterBlock) if !cmp.Equal(got, tc.want, cmp.Comparer(cty.Type.Equals), cmpopts.EquateEmpty()) { - t.Fatal(cmp.Diff(got, tc.want, cmp.Comparer(cty.Type.Equals), cmpopts.EquateEmpty())) + t.Error(cmp.Diff(got, tc.want, cmp.Comparer(cty.Type.Equals), cmpopts.EquateEmpty())) + } + + // We shouldn't have edited the original schema. + if !cmp.Equal(tc.schema, original, cmp.Comparer(cty.Type.Equals), cmpopts.EquateEmpty()) { + t.Errorf("the original schema was edited when it shouldn't have been: %s", cmp.Diff(tc.schema, original, cmp.Comparer(cty.Type.Equals), cmpopts.EquateEmpty())) } }) } From 1fbb3409934ca302fec8083c0e4353736d7f2a6e Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Mon, 22 Jul 2024 11:57:33 +0200 Subject: [PATCH 2/2] copywrite headers --- internal/configs/configschema/copy.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/configs/configschema/copy.go b/internal/configs/configschema/copy.go index 862e4b69f06c..ce4845607bd7 100644 --- a/internal/configs/configschema/copy.go +++ b/internal/configs/configschema/copy.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + package configschema // DeepCopy returns a deep copy of the schema.