From 578a3d89d148da0fe7b17aacf67d2f128da5f645 Mon Sep 17 00:00:00 2001 From: Pam Selle <204372+pselle@users.noreply.github.com> Date: Thu, 19 Nov 2020 17:24:55 -0500 Subject: [PATCH] Unmark values before provider validate call Unmark values before calling provider's validate function, this was not tested as the mock provider does not use Marshall. Update mock provider funcs to marshall and error if there was an error in marshalling --- terraform/context_components_test.go | 2 +- terraform/eval_validate.go | 8 ++++-- terraform/eval_validate_test.go | 8 ++++++ terraform/provider_mock.go | 40 ++++++++++++++++++++++++++-- 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/terraform/context_components_test.go b/terraform/context_components_test.go index 28feebdc3..fd2ac074b 100644 --- a/terraform/context_components_test.go +++ b/terraform/context_components_test.go @@ -62,7 +62,7 @@ func simpleTestSchema() *configschema.Block { Optional: true, }, "test_number": { - Type: cty.String, + Type: cty.Number, Optional: true, }, "test_bool": { diff --git a/terraform/eval_validate.go b/terraform/eval_validate.go index 8f1fd7e08..38ea7086f 100644 --- a/terraform/eval_validate.go +++ b/terraform/eval_validate.go @@ -374,9 +374,11 @@ func (n *EvalValidateResource) Validate(ctx EvalContext) tfdiags.Diagnostics { } } + // Use unmarked value for validate request + unmarkedConfigVal, _ := configVal.UnmarkDeep() req := providers.ValidateResourceTypeConfigRequest{ TypeName: cfg.Type, - Config: configVal, + Config: unmarkedConfigVal, } resp := provider.ValidateResourceTypeConfig(req) @@ -404,9 +406,11 @@ func (n *EvalValidateResource) Validate(ctx EvalContext) tfdiags.Diagnostics { return diags } + // Use unmarked value for validate request + unmarkedConfigVal, _ := configVal.UnmarkDeep() req := providers.ValidateDataSourceConfigRequest{ TypeName: cfg.Type, - Config: configVal, + Config: unmarkedConfigVal, } resp := provider.ValidateDataSourceConfig(req) diff --git a/terraform/eval_validate_test.go b/terraform/eval_validate_test.go index 5ff84fee1..4d23704e6 100644 --- a/terraform/eval_validate_test.go +++ b/terraform/eval_validate_test.go @@ -26,6 +26,9 @@ func TestEvalValidateResource_managedResource(t *testing.T) { if got, want := req.Config.GetAttr("test_string"), cty.StringVal("bar"); !got.RawEquals(want) { t.Fatalf("wrong value for test_string\ngot: %#v\nwant: %#v", got, want) } + if got, want := req.Config.GetAttr("test_number"), cty.NumberIntVal(2); !got.RawEquals(want) { + t.Fatalf("wrong value for test_number\ngot: %#v\nwant: %#v", got, want) + } return providers.ValidateResourceTypeConfigResponse{} } @@ -36,6 +39,7 @@ func TestEvalValidateResource_managedResource(t *testing.T) { Name: "foo", Config: configs.SynthBody("", map[string]cty.Value{ "test_string": cty.StringVal("bar"), + "test_number": cty.NumberIntVal(2).Mark("sensitive"), }), } node := &EvalValidateResource{ @@ -117,6 +121,9 @@ func TestEvalValidateResource_dataSource(t *testing.T) { if got, want := req.Config.GetAttr("test_string"), cty.StringVal("bar"); !got.RawEquals(want) { t.Fatalf("wrong value for test_string\ngot: %#v\nwant: %#v", got, want) } + if got, want := req.Config.GetAttr("test_number"), cty.NumberIntVal(2); !got.RawEquals(want) { + t.Fatalf("wrong value for test_number\ngot: %#v\nwant: %#v", got, want) + } return providers.ValidateDataSourceConfigResponse{} } @@ -127,6 +134,7 @@ func TestEvalValidateResource_dataSource(t *testing.T) { Name: "foo", Config: configs.SynthBody("", map[string]cty.Value{ "test_string": cty.StringVal("bar"), + "test_number": cty.NumberIntVal(2).Mark("sensitive"), }), } diff --git a/terraform/provider_mock.go b/terraform/provider_mock.go index 2a6f6dbf0..53c46d994 100644 --- a/terraform/provider_mock.go +++ b/terraform/provider_mock.go @@ -6,6 +6,7 @@ import ( "github.com/zclconf/go-cty/cty" ctyjson "github.com/zclconf/go-cty/cty/json" + "github.com/zclconf/go-cty/cty/msgpack" "github.com/hashicorp/terraform/configs/hcl2shim" "github.com/hashicorp/terraform/providers" @@ -124,6 +125,24 @@ func (p *MockProvider) getSchema() providers.GetSchemaResponse { return ret } +func (p *MockProvider) getResourceSchema(name string) providers.Schema { + schema := p.getSchema() + resSchema, ok := schema.ResourceTypes[name] + if !ok { + panic("unknown resource type " + name) + } + return resSchema +} + +func (p *MockProvider) getDatasourceSchema(name string) providers.Schema { + schema := p.getSchema() + dataSchema, ok := schema.DataSources[name] + if !ok { + panic("unknown data source " + name) + } + return dataSchema +} + func (p *MockProvider) PrepareProviderConfig(r providers.PrepareProviderConfigRequest) providers.PrepareProviderConfigResponse { p.Lock() defer p.Unlock() @@ -137,13 +156,22 @@ func (p *MockProvider) PrepareProviderConfig(r providers.PrepareProviderConfigRe return p.PrepareProviderConfigResponse } -func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { +func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTypeConfigRequest) (resp providers.ValidateResourceTypeConfigResponse) { p.Lock() defer p.Unlock() p.ValidateResourceTypeConfigCalled = true p.ValidateResourceTypeConfigRequest = r + // Marshall the value to replicate behavior by the GRPC protocol, + // and return any relevant errors + resourceSchema := p.getResourceSchema(r.TypeName) + _, err := msgpack.Marshal(r.Config, resourceSchema.Block.ImpliedType()) + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(err) + return resp + } + if p.ValidateResourceTypeConfigFn != nil { return p.ValidateResourceTypeConfigFn(r) } @@ -151,13 +179,21 @@ func (p *MockProvider) ValidateResourceTypeConfig(r providers.ValidateResourceTy return p.ValidateResourceTypeConfigResponse } -func (p *MockProvider) ValidateDataSourceConfig(r providers.ValidateDataSourceConfigRequest) providers.ValidateDataSourceConfigResponse { +func (p *MockProvider) ValidateDataSourceConfig(r providers.ValidateDataSourceConfigRequest) (resp providers.ValidateDataSourceConfigResponse) { p.Lock() defer p.Unlock() p.ValidateDataSourceConfigCalled = true p.ValidateDataSourceConfigRequest = r + // Marshall the value to replicate behavior by the GRPC protocol + dataSchema := p.getDatasourceSchema(r.TypeName) + _, err := msgpack.Marshal(r.Config, dataSchema.Block.ImpliedType()) + if err != nil { + resp.Diagnostics = resp.Diagnostics.Append(err) + return resp + } + if p.ValidateDataSourceConfigFn != nil { return p.ValidateDataSourceConfigFn(r) }