From f593127da653bcee761ade0b4f7b64f01d395742 Mon Sep 17 00:00:00 2001 From: Alexander Klein Date: Sun, 11 Oct 2020 11:04:07 +0200 Subject: [PATCH 1/5] Add wrapper func for legacy SchemaValidateFunc --- helper/validation/meta.go | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/helper/validation/meta.go b/helper/validation/meta.go index 344f8ba1fee..83f547a4577 100644 --- a/helper/validation/meta.go +++ b/helper/validation/meta.go @@ -2,9 +2,10 @@ package validation import ( "fmt" - "reflect" - + "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "reflect" ) // NoZeroValues is a SchemaValidateFunc which tests if the provided value is @@ -57,3 +58,27 @@ func Any(validators ...schema.SchemaValidateFunc) schema.SchemaValidateFunc { return allWarnings, allErrors } } + +// ToDiagFunc is a wrapper for legacy schema.SchemaValidateFunc +// converting it to schema.SchemaValidateDiagFunc +func ToDiagFunc(validator schema.SchemaValidateFunc) schema.SchemaValidateDiagFunc { + return func(i interface{}, p cty.Path) diag.Diagnostics { + var diags diag.Diagnostics + ws, es := validator(i, "") + for _, w := range ws { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Warning, + Summary: w, + AttributePath: p, + }) + } + for _, e := range es { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: e.Error(), + AttributePath: p, + }) + } + return diags + } +} From 56b6d3479b0a63830bbfc71ccaaa9f9b0650ec2c Mon Sep 17 00:00:00 2001 From: Alexander Klein Date: Sun, 11 Oct 2020 15:05:05 +0200 Subject: [PATCH 2/5] Parse attribute name to validator --- helper/validation/meta.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/helper/validation/meta.go b/helper/validation/meta.go index 83f547a4577..9574a8b8c77 100644 --- a/helper/validation/meta.go +++ b/helper/validation/meta.go @@ -64,7 +64,10 @@ func Any(validators ...schema.SchemaValidateFunc) schema.SchemaValidateFunc { func ToDiagFunc(validator schema.SchemaValidateFunc) schema.SchemaValidateDiagFunc { return func(i interface{}, p cty.Path) diag.Diagnostics { var diags diag.Diagnostics - ws, es := validator(i, "") + + attr := p[len(p)-1].(cty.GetAttrStep) + ws, es := validator(i, attr.Name) + for _, w := range ws { diags = append(diags, diag.Diagnostic{ Severity: diag.Warning, From 6868f2c11b40469f602ced497f83d54163e2e5d6 Mon Sep 17 00:00:00 2001 From: Alexander Klein Date: Sun, 11 Oct 2020 15:10:53 +0200 Subject: [PATCH 3/5] Fix sorting of imports --- helper/validation/meta.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helper/validation/meta.go b/helper/validation/meta.go index 9574a8b8c77..f1376c2d394 100644 --- a/helper/validation/meta.go +++ b/helper/validation/meta.go @@ -2,10 +2,11 @@ package validation import ( "fmt" + "reflect" + "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "reflect" ) // NoZeroValues is a SchemaValidateFunc which tests if the provided value is From 5468f1c48c275eaaca1aa00c579805a9016211d1 Mon Sep 17 00:00:00 2001 From: Alexander Klein Date: Sun, 11 Oct 2020 15:34:22 +0200 Subject: [PATCH 4/5] Add diagnostics testing helpers --- helper/validation/testing.go | 63 +++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/helper/validation/testing.go b/helper/validation/testing.go index c76a4ed999f..596c5754a48 100644 --- a/helper/validation/testing.go +++ b/helper/validation/testing.go @@ -5,6 +5,8 @@ import ( testing "github.com/mitchellh/go-testing-interface" + "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -14,20 +16,15 @@ type testCase struct { expectedErr *regexp.Regexp } +type diagTestCase struct { + val interface{} + f schema.SchemaValidateDiagFunc + expectedErr *regexp.Regexp +} + func runTestCases(t testing.T, cases []testCase) { t.Helper() - matchErr := func(errs []error, r *regexp.Regexp) bool { - // err must match one provided - for _, err := range errs { - if r.MatchString(err.Error()) { - return true - } - } - - return false - } - for i, tc := range cases { _, errs := tc.f(tc.val, "test_property") @@ -39,8 +36,50 @@ func runTestCases(t testing.T, cases []testCase) { t.Fatalf("expected test case %d to produce no errors, got %v", i, errs) } - if !matchErr(errs, tc.expectedErr) { + if !matchAnyError(errs, tc.expectedErr) { t.Fatalf("expected test case %d to produce error matching \"%s\", got %v", i, tc.expectedErr, errs) } } } + +func matchAnyError(errs []error, r *regexp.Regexp) bool { + // err must match one provided + for _, err := range errs { + if r.MatchString(err.Error()) { + return true + } + } + return false +} + +func runDiagTestCases(t testing.T, cases []diagTestCase) { + t.Helper() + + for i, tc := range cases { + p := cty.Path{ + cty.GetAttrStep{Name: "test_property"}, + } + diags := tc.f(tc.val, p) + + if !diags.HasError() && tc.expectedErr == nil { + continue + } + + if diags.HasError() && tc.expectedErr == nil { + t.Fatalf("expected test case %d to produce no errors, got %v", i, diags) + } + + if !matchAnyDiagSummary(diags, tc.expectedErr) { + t.Fatalf("expected test case %d to produce error matching \"%s\", got %v", i, tc.expectedErr, diags) + } + } +} + +func matchAnyDiagSummary(ds diag.Diagnostics, r *regexp.Regexp) bool { + for _, d := range ds { + if r.MatchString(d.Summary) { + return true + } + } + return false +} From b63f9bf0e01af73bdec81c54718f55612a65cd98 Mon Sep 17 00:00:00 2001 From: Alexander Klein Date: Sun, 11 Oct 2020 15:48:24 +0200 Subject: [PATCH 5/5] Add tests for diag func wrapper --- helper/validation/meta_test.go | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/helper/validation/meta_test.go b/helper/validation/meta_test.go index 1ec0b9c66a8..398dcb0612d 100644 --- a/helper/validation/meta_test.go +++ b/helper/validation/meta_test.go @@ -99,3 +99,38 @@ func TestValidationAny(t *testing.T) { }, }) } + +func TestToDiagFunc(t *testing.T) { + runDiagTestCases(t, []diagTestCase{ + { + val: 43, + f: ToDiagFunc(Any( + IntAtLeast(42), + IntAtMost(5), + )), + }, + { + val: "foo", + f: ToDiagFunc(All( + StringLenBetween(1, 10), + StringIsNotWhiteSpace, + )), + }, + { + val: 7, + f: ToDiagFunc(Any( + IntAtLeast(42), + IntAtMost(5), + )), + expectedErr: regexp.MustCompile("expected [\\w]+ to be at least \\(42\\), got 7"), + }, + { + val: 7, + f: ToDiagFunc(Any( + IntAtLeast(42), + IntAtMost(5), + )), + expectedErr: regexp.MustCompile("expected [\\w]+ to be at most \\(5\\), got 7"), + }, + }) +}