From 4c79143aefc3d44976b774adec0358f87cac2532 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Fri, 6 Oct 2023 10:39:26 -0700 Subject: [PATCH 1/2] hclsyntax: New tests for marks+refinments together The interactions between value marks and unknown value refinements can be a little tricky, so this pair of new tests cover two examples of that interaction that are currently working and ought to stay that way. --- hclsyntax/expression_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/hclsyntax/expression_test.go b/hclsyntax/expression_test.go index 6f761023..1af93dad 100644 --- a/hclsyntax/expression_test.go +++ b/hclsyntax/expression_test.go @@ -1397,6 +1397,26 @@ upper( }).Mark("sensitive"), 0, }, + { // splat with sensitive collection that's unknown + `maps.*.enabled`, + &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "maps": cty.UnknownVal(cty.List(cty.Map(cty.Bool))).Mark("sensitive"), + }, + }, + cty.UnknownVal(cty.List(cty.Bool)).RefineNotNull().Mark("sensitive"), + 0, + }, + { // splat with sensitive collection that's unknown and not null + `maps.*.enabled`, + &hcl.EvalContext{ + Variables: map[string]cty.Value{ + "maps": cty.UnknownVal(cty.List(cty.Map(cty.Bool))).RefineNotNull().Mark("sensitive"), + }, + }, + cty.UnknownVal(cty.List(cty.Bool)).RefineNotNull().Mark("sensitive"), + 0, + }, { // splat with collection with sensitive elements `maps.*.x`, &hcl.EvalContext{ From bb95f0fe1c7fea4f7f0f23bde21d6a618aaed718 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Fri, 6 Oct 2023 10:40:55 -0700 Subject: [PATCH 2/2] hcldec: New test for marks+refinements together The interactions between value marks and unknown value refinements can be a little tricky, so this new addition to the "RefineWith" tests confirms that it does indeed handle marked values correctly when passing through the refinement spec. --- hcldec/spec_test.go | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/hcldec/spec_test.go b/hcldec/spec_test.go index 25c5d6cb..1b0594d1 100644 --- a/hcldec/spec_test.go +++ b/hcldec/spec_test.go @@ -12,6 +12,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/zclconf/go-cty-debug/ctydebug" "github.com/zclconf/go-cty/cty" + "github.com/zclconf/go-cty/cty/function" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" @@ -218,6 +219,7 @@ func TestRefineValueSpec(t *testing.T) { foo = "hello" bar = unk dyn = dyn +marked = mark(unk) ` f, diags := hclsyntax.ParseConfig([]byte(config), "", hcl.InitialPos) @@ -256,9 +258,10 @@ dyn = dyn } } spec := &ObjectSpec{ - "foo": attrSpec("foo"), - "bar": attrSpec("bar"), - "dyn": attrSpec("dyn"), + "foo": attrSpec("foo"), + "bar": attrSpec("bar"), + "dyn": attrSpec("dyn"), + "marked": attrSpec("marked"), } got, diags := Decode(f.Body, spec, &hcl.EvalContext{ @@ -266,6 +269,26 @@ dyn = dyn "unk": cty.UnknownVal(cty.String), "dyn": cty.DynamicVal, }, + Functions: map[string]function.Function{ + "mark": function.New(&function.Spec{ + Params: []function.Parameter{ + { + Name: "v", + Type: cty.DynamicPseudoType, + AllowMarked: true, + AllowNull: true, + AllowUnknown: true, + AllowDynamicType: true, + }, + }, + Type: func(args []cty.Value) (cty.Type, error) { + return args[0].Type(), nil + }, + Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { + return args[0].Mark("boop"), nil + }, + }), + }, }) if diags.HasErrors() { t.Fatal(diags.Error()) @@ -284,6 +307,10 @@ dyn = dyn // Correct behavior here requires that we convert the DynamicVal // to an unknown string first and then refine it. "dyn": cty.UnknownVal(cty.String).RefineNotNull(), + + // This argument had a mark applied, which should be preserved + // despite the refinement. + "marked": cty.UnknownVal(cty.String).RefineNotNull().Mark("boop"), }) if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" { t.Errorf("wrong result\n%s", diff)