From ebd3aba0beaba0bca57c20439e77ec3fb67b63f0 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Wed, 5 Sep 2018 14:35:30 -0700 Subject: [PATCH] core: Fix various compile-time errors in tests Significant changes to the provider interface left a lot of the tests in a non-buildable state. This set of changes gets the tests building again but does not attempt to make them run to completion or pass. After this commit, it is possible to build a test program for the ./terraform package but it will panic during its run. That will be addressed in subsequent commits. --- terraform/context_apply_test.go | 98 +++++++++++++---------- terraform/context_import_test.go | 17 ++-- terraform/context_input_test.go | 29 ++++--- terraform/context_plan_test.go | 45 ++++++----- terraform/context_refresh_test.go | 115 +++++++++++++++++---------- terraform/context_validate_test.go | 71 +++++++++++------ terraform/eval_diff_test.go | 11 +-- terraform/eval_validate_test.go | 99 ++++++++++++----------- terraform/graph_builder_plan_test.go | 23 +++--- terraform/hook_test.go | 3 +- terraform/provider_mock.go | 28 +++++++ terraform/schemas_test.go | 2 +- 12 files changed, 318 insertions(+), 223 deletions(-) diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index 63918483d..689278690 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -24,6 +24,7 @@ import ( "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" ) @@ -1485,7 +1486,11 @@ func TestContext2Apply_dataBasic(t *testing.T) { p := testProvider("null") p.ApplyFn = testApplyFn p.DiffFn = testDiffFn - p.ReadDataApplyReturn = &InstanceState{ID: "yo"} + p.ReadDataSourceResponse = providers.ReadDataSourceResponse{ + State: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("yo"), + }), + } ctx := testContext2(t, &ContextOpts{ Config: m, @@ -4274,9 +4279,11 @@ func TestContext2Apply_provisionerModule(t *testing.T) { p.DiffFn = testDiffFn pr := testProvisioner() - pr.GetConfigSchemaReturnSchema = &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "foo": {Type: cty.String, Optional: true}, + pr.GetSchemaResponse = provisioners.GetSchemaResponse{ + Provisioner: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "foo": {Type: cty.String, Optional: true}, + }, }, } @@ -5907,9 +5914,11 @@ func TestContext2Apply_Provisioner_ConnInfo(t *testing.T) { } p.DiffFn = testDiffFn - pr.GetConfigSchemaReturnSchema = &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "foo": {Type: cty.String, Optional: true}, + pr.GetSchemaResponse = provisioners.GetSchemaResponse{ + Provisioner: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "foo": {Type: cty.String, Optional: true}, + }, }, } @@ -7635,15 +7644,17 @@ func TestContext2Apply_destroyProvisionerWithLocals(t *testing.T) { } return nil } - pr.GetConfigSchemaReturnSchema = &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "command": { - Type: cty.String, - Required: true, - }, - "when": { - Type: cty.String, - Optional: true, + pr.GetSchemaResponse = provisioners.GetSchemaResponse{ + Provisioner: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "command": { + Type: cty.String, + Required: true, + }, + "when": { + Type: cty.String, + Optional: true, + }, }, }, } @@ -7701,15 +7712,17 @@ func TestContext2Apply_destroyProvisionerWithMultipleLocals(t *testing.T) { p.DiffFn = testDiffFn pr := testProvisioner() - pr.GetConfigSchemaReturnSchema = &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ - "command": { - Type: cty.String, - Required: true, - }, - "when": { - Type: cty.String, - Optional: true, + pr.GetSchemaResponse = provisioners.GetSchemaResponse{ + Provisioner: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "command": { + Type: cty.String, + Required: true, + }, + "when": { + Type: cty.String, + Optional: true, + }, }, }, } @@ -8572,9 +8585,6 @@ func TestContext2Apply_singleDestroy(t *testing.T) { // GH-7824 func TestContext2Apply_issue7824(t *testing.T) { p := testProvider("template") - p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ - Name: "template_file", - }) p.ApplyFn = testApplyFn p.DiffFn = testDiffFn p.GetSchemaReturn = &ProviderSchema{ @@ -8632,12 +8642,18 @@ func TestContext2Apply_issue5254(t *testing.T) { // Create a provider. We use "template" here just to match the repro // we got from the issue itself. p := testProvider("template") - p.ResourcesReturn = append(p.ResourcesReturn, ResourceType{ - Name: "template_file", - }) - p.ApplyFn = testApplyFn p.DiffFn = testDiffFn + p.GetSchemaReturn = &ProviderSchema{ + ResourceTypes: map[string]*configschema.Block{ + "template_file": { + Attributes: map[string]*configschema.Attribute{ + "template": {Type: cty.String, Optional: true}, + "__template_requires_new": {Type: cty.Bool, Optional: true}, + }, + }, + }, + } m, snap := testModuleWithSnapshot(t, "issue-5254/step-0") @@ -9106,18 +9122,12 @@ func TestContext2Apply_dataDependsOn(t *testing.T) { } p.DiffFn = testDiffFn - p.ReadDataDiffFn = testDataDiffFn - - p.ReadDataApplyFn = func(*InstanceInfo, *InstanceDiff) (*InstanceState, error) { - // Read the artifact created by our dependency being applied. - // Without any "depends_on", this would be skipped as it's assumed the - // initial diff during refresh was all that's needed. - return &InstanceState{ - ID: "read", - Attributes: map[string]string{ - "foo": provisionerOutput, - }, - }, nil + p.ReadDataSourceFn = func (req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse{ + return providers.ReadDataSourceResponse{ + State: cty.ObjectVal(map[string]cty.Value{ + "foo": cty.StringVal(provisionerOutput), + }), + } } _, diags := ctx.Refresh() diff --git a/terraform/context_import_test.go b/terraform/context_import_test.go index e590c8b12..aa36bdf0a 100644 --- a/terraform/context_import_test.go +++ b/terraform/context_import_test.go @@ -431,11 +431,12 @@ func TestContextImport_refresh(t *testing.T) { }, } - p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { - return &InstanceState{ - ID: "foo", - Attributes: map[string]string{"foo": "bar"}, - }, nil + p.ReadResourceFn = nil + p.ReadResourceResponse = providers.ReadResourceResponse{ + NewState: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("foo"), + "foo": cty.StringVal("bar"), + }), } state, diags := ctx.Import(&ImportOpts{ @@ -479,8 +480,10 @@ func TestContextImport_refreshNil(t *testing.T) { }, } - p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { - return nil, nil + p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { + return providers.ReadResourceResponse{ + NewState: cty.NullVal(cty.DynamicPseudoType), + } } state, diags := ctx.Import(&ImportOpts{ diff --git a/terraform/context_input_test.go b/terraform/context_input_test.go index 75de24036..8aea6cef7 100644 --- a/terraform/context_input_test.go +++ b/terraform/context_input_test.go @@ -1,7 +1,6 @@ package terraform import ( - "errors" "reflect" "strings" "sync" @@ -254,8 +253,8 @@ func TestContext2Input_providerOnce(t *testing.T) { ), }) - count := 0 - p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { + //count := 0 + /*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { count++ _, set := c.Config["from_input"] @@ -271,7 +270,7 @@ func TestContext2Input_providerOnce(t *testing.T) { } return c, nil - } + }*/ if diags := ctx.Input(InputModeStd); diags.HasErrors() { t.Fatalf("input errors: %s", diags.Err()) @@ -444,10 +443,10 @@ func TestContext2Input_providerVars(t *testing.T) { } var actual interface{} - p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { + /*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { c.Config["bar"] = "baz" return c, nil - } + }*/ p.ConfigureFn = func(c *ResourceConfig) error { actual, _ = c.Get("foo") return nil @@ -486,12 +485,12 @@ func TestContext2Input_providerVarsModuleInherit(t *testing.T) { UIInput: input, }) - p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { + /*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { if errs := c.CheckSet([]string{"access_key"}); len(errs) > 0 { return c, errs[0] } return c, nil - } + }*/ p.ConfigureFn = func(c *ResourceConfig) error { return nil } @@ -528,10 +527,10 @@ func TestContext2Input_varOnly(t *testing.T) { } var actual interface{} - p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { + /*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { c.Raw["foo"] = "bar" return c, nil - } + }*/ p.ConfigureFn = func(c *ResourceConfig) error { actual = c.Raw["foo"] return nil @@ -814,9 +813,9 @@ func TestContext2Input_submoduleTriggersInvalidCount(t *testing.T) { UIInput: input, }) - p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { + /*p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { return c, nil - } + }*/ p.ConfigureFn = func(c *ResourceConfig) error { return nil } @@ -842,7 +841,11 @@ func TestContext2Input_dataSourceRequiresRefresh(t *testing.T) { }, }, } - p.ReadDataDiffFn = testDataDiffFn + p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse { + return providers.ReadDataSourceResponse{ + State: req.Config, + } + } state := states.BuildState(func(s *states.SyncState) { s.SetResourceInstanceCurrent( diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index 1e71d3c70..924fecc32 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/tfdiags" ) func TestContext2Plan_basic(t *testing.T) { @@ -1457,18 +1458,17 @@ func TestContext2Plan_dataSourceTypeMismatch(t *testing.T) { }, }, } - p.ValidateResourceFn = func(t string, c *ResourceConfig) (ws []string, es []error) { - // Emulate the type checking behavior of helper/schema based validation - if t == "aws_instance" { - ami, _ := c.Get("ami") - switch a := ami.(type) { - case string: - // ok - default: - es = append(es, fmt.Errorf("Expected ami to be string, got %T", a)) + p.ValidateResourceTypeConfigFn = func (req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + var diags tfdiags.Diagnostics + if req.TypeName == "aws_instance" { + amiVal := req.Config.GetAttr("ami") + if amiVal.Type() != cty.String { + diags = diags.Append(fmt.Errorf("Expected ami to be cty.String, got %#v", amiVal)) } } - return + return providers.ValidateResourceTypeConfigResponse{ + Diagnostics: diags, + } } p.DiffFn = func( info *InstanceInfo, @@ -3891,8 +3891,10 @@ func TestContext2Plan_resourceNestedCount(t *testing.T) { m := testModule(t, "nested-resource-count-plan") p := testProvider("aws") p.DiffFn = testDiffFn - p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { - return is, nil + p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { + return providers.ReadResourceResponse{ + NewState: req.PriorState, + } } s := mustShimLegacyState(&State{ Modules: []*ModuleState{ @@ -4041,18 +4043,17 @@ func TestContext2Plan_computedAttrRefTypeMismatch(t *testing.T) { m := testModule(t, "plan-computed-attr-ref-type-mismatch") p := testProvider("aws") p.DiffFn = testDiffFn - p.ValidateResourceFn = func(t string, c *ResourceConfig) (ws []string, es []error) { - // Emulate the type checking behavior of helper/schema based validation - if t == "aws_instance" { - ami, _ := c.Get("ami") - switch a := ami.(type) { - case string: - // ok - default: - es = append(es, fmt.Errorf("Expected ami to be string, got %T", a)) + p.ValidateResourceTypeConfigFn = func (req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + var diags tfdiags.Diagnostics + if req.TypeName == "aws_instance" { + amiVal := req.Config.GetAttr("ami") + if amiVal.Type() != cty.String { + diags = diags.Append(fmt.Errorf("Expected ami to be cty.String, got %#v", amiVal)) } } - return + return providers.ValidateResourceTypeConfigResponse{ + Diagnostics: diags, + } } p.DiffFn = func( info *InstanceInfo, diff --git a/terraform/context_refresh_test.go b/terraform/context_refresh_test.go index 33222084e..6c20c9586 100644 --- a/terraform/context_refresh_test.go +++ b/terraform/context_refresh_test.go @@ -84,9 +84,11 @@ func TestContext2Refresh_dataComputedModuleVar(t *testing.T) { ), }) - p.RefreshFn = nil - p.RefreshReturn = &InstanceState{ - ID: "foo", + p.ReadResourceFn = nil + p.ReadResourceResponse = providers.ReadResourceResponse{ + NewState: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("foo"), + }), } p.GetSchemaReturn = &ProviderSchema{ @@ -193,9 +195,11 @@ func TestContext2Refresh_targeted(t *testing.T) { }) refreshedResources := make([]string, 0, 2) - p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { - refreshedResources = append(refreshedResources, i.Id) - return is, nil + p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { + refreshedResources = append(refreshedResources, req.PriorState.GetAttr("id").AsString()) + return providers.ReadResourceResponse{ + NewState: req.PriorState, + } } _, diags := ctx.Refresh() @@ -276,9 +280,11 @@ func TestContext2Refresh_targetedCount(t *testing.T) { }) refreshedResources := make([]string, 0, 2) - p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { - refreshedResources = append(refreshedResources, i.Id) - return is, nil + p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { + refreshedResources = append(refreshedResources, req.PriorState.GetAttr("id").AsString()) + return providers.ReadResourceResponse{ + NewState: req.PriorState, + } } _, diags := ctx.Refresh() @@ -367,9 +373,11 @@ func TestContext2Refresh_targetedCountIndex(t *testing.T) { }) refreshedResources := make([]string, 0, 2) - p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { - refreshedResources = append(refreshedResources, i.Id) - return is, nil + p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { + refreshedResources = append(refreshedResources, req.PriorState.GetAttr("id").AsString()) + return providers.ReadResourceResponse{ + NewState: req.PriorState, + } } _, diags := ctx.Refresh() @@ -447,8 +455,8 @@ func TestContext2Refresh_delete(t *testing.T) { }), }) - p.RefreshFn = nil - p.RefreshReturn = nil + p.ReadResourceFn = nil + p.ReadResourceResponse = providers.ReadResourceResponse{} s, diags := ctx.Refresh() if diags.HasErrors() { @@ -474,16 +482,18 @@ func TestContext2Refresh_ignoreUncreated(t *testing.T) { State: nil, }) - p.RefreshFn = nil - p.RefreshReturn = &InstanceState{ - ID: "foo", + p.ReadResourceFn = nil + p.ReadResourceResponse = providers.ReadResourceResponse{ + NewState: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("foo"), + }), } _, diags := ctx.Refresh() if diags.HasErrors() { t.Fatalf("refresh errors: %s", diags.Err()) } - if p.RefreshCalled { + if p.ReadResourceCalled { t.Fatal("refresh should not be called") } } @@ -569,13 +579,22 @@ func TestContext2Refresh_modules(t *testing.T) { State: state, }) - p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { - if s.ID != "baz" { - return s, nil + p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { + if !req.PriorState.GetAttr("id").RawEquals(cty.StringVal("baz")) { + return providers.ReadResourceResponse{ + NewState: req.PriorState, + } } - s.ID = "new" - return s, nil + new, _ := cty.Transform(req.PriorState, func(path cty.Path, v cty.Value) (cty.Value, error) { + if len(path) == 1 && path[0].(cty.GetAttrStep).Name == "id" { + return cty.StringVal("new"), nil + } + return v, nil + }) + return providers.ReadResourceResponse{ + NewState: new, + } } s, diags := ctx.Refresh() @@ -657,9 +676,11 @@ func TestContext2Refresh_noState(t *testing.T) { ), }) - p.RefreshFn = nil - p.RefreshReturn = &InstanceState{ - ID: "foo", + p.ReadResourceFn = nil + p.ReadResourceResponse = providers.ReadResourceResponse{ + NewState: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("foo"), + }), } if _, diags := ctx.Refresh(); diags.HasErrors() { @@ -719,8 +740,10 @@ func TestContext2Refresh_output(t *testing.T) { }), }) - p.RefreshFn = func(info *InstanceInfo, s *InstanceState) (*InstanceState, error) { - return s, nil + p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { + return providers.ReadResourceResponse{ + NewState: req.PriorState, + } } s, diags := ctx.Refresh() @@ -763,8 +786,8 @@ func TestContext2Refresh_outputPartial(t *testing.T) { }), }) - p.RefreshFn = nil - p.RefreshReturn = nil + p.ReadResourceFn = nil + p.ReadResourceResponse = providers.ReadResourceResponse{} p.GetSchemaReturn = &ProviderSchema{ Provider: &configschema.Block{}, @@ -1016,8 +1039,11 @@ func TestContext2Refresh_dataStateRefData(t *testing.T) { State: state, }) - p.ReadDataDiffFn = testDataDiffFn - p.ReadDataApplyFn = testDataApplyFn + p.ReadDataSourceFn = func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse { + return providers.ReadDataSourceResponse{ + State: req.Config, + } + } s, diags := ctx.Refresh() if diags.HasErrors() { @@ -1060,18 +1086,19 @@ func TestContext2Refresh_tainted(t *testing.T) { State: state, }) - p.RefreshFn = nil - p.RefreshReturn = &InstanceState{ - ID: "foo", - Tainted: true, + p.ReadResourceFn = nil + p.ReadResourceResponse = providers.ReadResourceResponse{ + NewState: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("foo"), + }), } s, diags := ctx.Refresh() if diags.HasErrors() { t.Fatalf("refresh errors: %s", diags.Err()) } - if !p.RefreshCalled { - t.Fatal("refresh should be called") + if !p.ReadResourceCalled { + t.Fatal("ReadResource was not called; should have been") } actual := strings.TrimSpace(s.String()) @@ -1205,14 +1232,14 @@ func TestContext2Refresh_orphanModule(t *testing.T) { // Create a custom refresh function to track the order they were visited var order []string var orderLock sync.Mutex - p.RefreshFn = func( - info *InstanceInfo, - is *InstanceState) (*InstanceState, error) { + p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { orderLock.Lock() defer orderLock.Unlock() - order = append(order, is.ID) - return is, nil + order = append(order, req.PriorState.GetAttr("id").AsString()) + return providers.ReadResourceResponse{ + NewState: req.PriorState, + } } p.GetSchemaReturn = &ProviderSchema{ Provider: &configschema.Block{}, @@ -1360,7 +1387,7 @@ func TestContext2Refresh_noDiffHookOnScaleOut(t *testing.T) { h := new(MockHook) p := testProvider("aws") m := testModule(t, "refresh-resource-scale-inout") - p.RefreshFn = nil + p.ReadResourceFn = nil p.GetSchemaReturn = &ProviderSchema{ Provider: &configschema.Block{}, ResourceTypes: map[string]*configschema.Block{ diff --git a/terraform/context_validate_test.go b/terraform/context_validate_test.go index 2423c0d46..de470e4f5 100644 --- a/terraform/context_validate_test.go +++ b/terraform/context_validate_test.go @@ -1,17 +1,19 @@ package terraform import ( + "errors" "fmt" "strings" "testing" - "github.com/hashicorp/terraform/providers" - "github.com/hashicorp/terraform/states" - "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs/configschema" + "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" + "github.com/hashicorp/terraform/states" + "github.com/hashicorp/terraform/tfdiags" ) func TestContext2Validate_badCount(t *testing.T) { @@ -367,7 +369,9 @@ func TestContext2Validate_moduleBadResource(t *testing.T) { ), }) - p.ValidateResourceReturnErrors = []error{fmt.Errorf("bad")} + p.ValidateResourceTypeConfigResponse = providers.ValidateResourceTypeConfigResponse{ + Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")), + } diags := c.Validate() if !diags.HasErrors() { @@ -580,9 +584,14 @@ func TestContext2Validate_orphans(t *testing.T) { State: state, }) - p.ValidateResourceFn = func( - t string, c *ResourceConfig) ([]string, []error) { - return nil, c.CheckSet([]string{"foo"}) + p.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + var diags tfdiags.Diagnostics + if req.Config.GetAttr("foo").IsNull() { + diags.Append(errors.New("foo is not set")) + } + return providers.ValidateResourceTypeConfigResponse{ + Diagnostics: diags, + } } diags := c.Validate() @@ -616,7 +625,9 @@ func TestContext2Validate_providerConfig_bad(t *testing.T) { ), }) - p.ValidateReturnErrors = []error{fmt.Errorf("bad")} + p.ValidateProviderConfigResponse = providers.ValidateProviderConfigResponse{ + Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")), + } diags := c.Validate() if len(diags) != 1 { @@ -652,7 +663,9 @@ func TestContext2Validate_providerConfig_badEmpty(t *testing.T) { ), }) - p.ValidateReturnErrors = []error{fmt.Errorf("bad")} + p.ValidateProviderConfigResponse = providers.ValidateProviderConfigResponse{ + Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")), + } diags := c.Validate() if !diags.HasErrors() { @@ -718,7 +731,9 @@ func TestContext2Validate_provisionerConfig_bad(t *testing.T) { }, }) - pr.ValidateReturnErrors = []error{fmt.Errorf("bad")} + p.ValidateProviderConfigResponse = providers.ValidateProviderConfigResponse{ + Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")), + } diags := c.Validate() if !diags.HasErrors() { @@ -745,11 +760,14 @@ func TestContext2Validate_provisionerConfig_good(t *testing.T) { } pr := simpleMockProvisioner() - pr.ValidateFn = func(c *ResourceConfig) ([]string, []error) { - if c == nil { - t.Fatalf("missing resource config for provisioner") + pr.ValidateProvisionerConfigFn = func(req provisioners.ValidateProvisionerConfigRequest) provisioners.ValidateProvisionerConfigResponse { + var diags tfdiags.Diagnostics + if req.Config.GetAttr("test_string").IsNull() { + diags.Append(errors.New("test_string is not set")) + } + return provisioners.ValidateProvisionerConfigResponse{ + Diagnostics: diags, } - return nil, c.CheckSet([]string{"test_string"}) } c := testContext2(t, &ContextOpts{ @@ -820,7 +838,9 @@ func TestContext2Validate_resourceConfig_bad(t *testing.T) { ), }) - p.ValidateResourceReturnErrors = []error{fmt.Errorf("bad")} + p.ValidateResourceTypeConfigResponse = providers.ValidateResourceTypeConfigResponse{ + Diagnostics: tfdiags.Diagnostics{}.Append(fmt.Errorf("bad")), + } diags := c.Validate() if !diags.HasErrors() { @@ -896,9 +916,14 @@ func TestContext2Validate_tainted(t *testing.T) { State: state, }) - p.ValidateResourceFn = func( - t string, c *ResourceConfig) ([]string, []error) { - return nil, c.CheckSet([]string{"foo"}) + p.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + var diags tfdiags.Diagnostics + if req.Config.GetAttr("foo").IsNull() { + diags.Append(errors.New("foo is not set")) + } + return providers.ValidateResourceTypeConfigResponse{ + Diagnostics: diags, + } } diags := c.Validate() @@ -986,14 +1011,14 @@ func TestContext2Validate_varRefFilled(t *testing.T) { }, }) - var value interface{} - p.ValidateResourceFn = func(t string, c *ResourceConfig) ([]string, []error) { - value, _ = c.Get("foo") - return nil, nil + var value cty.Value + p.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + value = req.Config.GetAttr("foo") + return providers.ValidateResourceTypeConfigResponse{} } c.Validate() - if value != "bar" { + if !value.RawEquals(cty.StringVal("bar")) { t.Fatalf("bad: %#v", value) } } diff --git a/terraform/eval_diff_test.go b/terraform/eval_diff_test.go index 2c49dd74b..0ac8413fd 100644 --- a/terraform/eval_diff_test.go +++ b/terraform/eval_diff_test.go @@ -1,17 +1,12 @@ package terraform import ( - "fmt" "testing" - - "github.com/hashicorp/hcl2/hcl/hclsyntax" - - "github.com/hashicorp/hcl2/hcl" - "github.com/hashicorp/terraform/configs" ) func TestProcessIgnoreChanges(t *testing.T) { - var evalDiff *EvalDiff + t.Fatalf("TestProcessIgnoreChanges not yet updated for new processIgnoreChanges signature") + /*var evalDiff *EvalDiff var instanceDiff *InstanceDiff var testDiffs = func(t *testing.T, ignoreChanges []string, newAttribute string) (*EvalDiff, *InstanceDiff) { @@ -108,5 +103,5 @@ func TestProcessIgnoreChanges(t *testing.T) { } } }) - } + }*/ } diff --git a/terraform/eval_validate_test.go b/terraform/eval_validate_test.go index 962f2504a..acf9a1fc0 100644 --- a/terraform/eval_validate_test.go +++ b/terraform/eval_validate_test.go @@ -19,17 +19,14 @@ import ( func TestEvalValidateResource_managedResource(t *testing.T) { mp := simpleMockProvider() - mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) { - expected := "test_object" - if rt != expected { - t.Fatalf("wrong resource type\ngot: %#v\nwant: %#v", rt, expected) + mp.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + if got, want := req.TypeName, "test_object"; got != want { + t.Fatalf("wrong resource type\ngot: %#v\nwant: %#v", got, want) } - expected = "bar" - val, _ := c.Get("test_string") - if val != expected { - t.Fatalf("wrong value for test_string\ngot: %#v\nwant: %#v", val, expected) + 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) } - return + return providers.ValidateResourceTypeConfigResponse{} } p := providers.Interface(mp) @@ -60,24 +57,21 @@ func TestEvalValidateResource_managedResource(t *testing.T) { t.Fatalf("err: %s", err) } - if !mp.ValidateResourceCalled { - t.Fatal("Expected ValidateResource to be called, but it was not!") + if !mp.ValidateResourceTypeConfigCalled { + t.Fatal("Expected ValidateResourceTypeConfig to be called, but it was not!") } } func TestEvalValidateResource_managedResourceCount(t *testing.T) { mp := simpleMockProvider() - mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) { - expected := "test_object" - if rt != expected { - t.Fatalf("wrong resource type\ngot: %#v\nwant: %#v", rt, expected) + mp.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + if got, want := req.TypeName, "test_object"; got != want { + t.Fatalf("wrong resource type\ngot: %#v\nwant: %#v", got, want) } - expected = "bar" - val, _ := c.Get("test_string") - if val != expected { - t.Fatalf("wrong value for test_string\ngot: %#v\nwant: %#v", val, expected) + 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) } - return + return providers.ValidateResourceTypeConfigResponse{} } p := providers.Interface(mp) @@ -109,24 +103,21 @@ func TestEvalValidateResource_managedResourceCount(t *testing.T) { t.Fatalf("err: %s", err) } - if !mp.ValidateResourceCalled { - t.Fatal("Expected ValidateResource to be called, but it was not!") + if !mp.ValidateResourceTypeConfigCalled { + t.Fatal("Expected ValidateResourceTypeConfig to be called, but it was not!") } } func TestEvalValidateResource_dataSource(t *testing.T) { mp := simpleMockProvider() - mp.ValidateDataSourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) { - expected := "test_object" - if rt != expected { - t.Fatalf("expected: %s, got: %s", expected, rt) + mp.ValidateDataSourceConfigFn = func(req providers.ValidateDataSourceConfigRequest) providers.ValidateDataSourceConfigResponse { + if got, want := req.TypeName, "test_object"; got != want { + t.Fatalf("wrong resource type\ngot: %#v\nwant: %#v", got, want) } - expected = "bar" - val, _ := c.Get("test_string") - if val != expected { - t.Fatalf("expected: %s, got: %s", expected, val) + 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) } - return + return providers.ValidateDataSourceConfigResponse{} } p := providers.Interface(mp) @@ -158,15 +149,15 @@ func TestEvalValidateResource_dataSource(t *testing.T) { t.Fatalf("err: %s", err) } - if !mp.ValidateDataSourceCalled { - t.Fatal("Expected ValidateDataSource to be called, but it was not!") + if !mp.ValidateDataSourceConfigCalled { + t.Fatal("Expected ValidateDataSourceConfig to be called, but it was not!") } } func TestEvalValidateResource_validReturnsNilError(t *testing.T) { mp := simpleMockProvider() - mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) { - return + mp.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + return providers.ValidateResourceTypeConfigResponse{} } p := providers.Interface(mp) @@ -198,10 +189,13 @@ func TestEvalValidateResource_validReturnsNilError(t *testing.T) { func TestEvalValidateResource_warningsAndErrorsPassedThrough(t *testing.T) { mp := simpleMockProvider() - mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) { - ws = append(ws, "warn") - es = append(es, errors.New("err")) - return + mp.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.SimpleWarning("warn")) + diags = diags.Append(errors.New("err")) + return providers.ValidateResourceTypeConfigResponse{ + Diagnostics: diags, + } } p := providers.Interface(mp) @@ -246,9 +240,12 @@ func TestEvalValidateResource_warningsAndErrorsPassedThrough(t *testing.T) { func TestEvalValidateResource_ignoreWarnings(t *testing.T) { mp := simpleMockProvider() - mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) { - ws = append(ws, "warn") - return + mp.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.SimpleWarning("warn")) + return providers.ValidateResourceTypeConfigResponse{ + Diagnostics: diags, + } } p := providers.Interface(mp) @@ -282,8 +279,8 @@ func TestEvalValidateResource_ignoreWarnings(t *testing.T) { func TestEvalValidateResource_invalidDependsOn(t *testing.T) { mp := simpleMockProvider() - mp.ValidateResourceFn = func(rt string, c *ResourceConfig) (ws []string, es []error) { - return + mp.ValidateResourceTypeConfigFn = func(req providers.ValidateResourceTypeConfigRequest) providers.ValidateResourceTypeConfigResponse { + return providers.ValidateResourceTypeConfigResponse{} } // We'll check a _valid_ config first, to make sure we're not failing @@ -390,8 +387,8 @@ func TestEvalValidateProvisioner_valid(t *testing.T) { t.Errorf("node.Eval returned non-nil result") } - if !mp.ValidateCalled { - t.Fatalf("p.Validate not called") + if !mp.ValidateProvisionerConfigCalled { + t.Fatalf("p.ValidateProvisionerConfig not called") } } @@ -429,7 +426,13 @@ func TestEvalValidateProvisioner_warning(t *testing.T) { }, } - mp.ValidateReturnWarns = []string{"foo is deprecated"} + { + var diags tfdiags.Diagnostics + diags = diags.Append(tfdiags.SimpleWarning("foo is deprecated")) + mp.ValidateProvisionerConfigResponse = provisioners.ValidateProvisionerConfigResponse{ + Diagnostics: diags, + } + } _, err := node.Eval(ctx) if err == nil { @@ -442,7 +445,7 @@ func TestEvalValidateProvisioner_warning(t *testing.T) { t.Fatalf("wrong number of diagsnostics in %#v; want one warning", diags) } - if got, want := diags[0].Description().Summary, mp.ValidateReturnWarns[0]; got != want { + if got, want := diags[0].Description().Summary, mp.ValidateProvisionerConfigResponse.Diagnostics[0].Description().Summary; got != want { t.Fatalf("wrong warning %q; want %q", got, want) } } diff --git a/terraform/graph_builder_plan_test.go b/terraform/graph_builder_plan_test.go index 65533d512..7a1a13421 100644 --- a/terraform/graph_builder_plan_test.go +++ b/terraform/graph_builder_plan_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/hashicorp/terraform/addrs" + "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/providers" ) @@ -14,22 +15,20 @@ func TestPlanGraphBuilder_impl(t *testing.T) { func TestPlanGraphBuilder(t *testing.T) { awsProvider := &MockProvider{ - GetSchemaResponse: provider.GetSchemaResponse{ - Provider: providers.Schema{ - Block: simpleTestSchema(), - }, - ResourceTypes: map[string]providers.Schema{ - "aws_security_group": {Block: simpleTestSchema()}, - "aws_instance": {Block: simpleTestSchema()}, - "aws_load_balancer": {Block: simpleTestSchema()}, + GetSchemaReturn: &ProviderSchema{ + Provider: simpleTestSchema(), + ResourceTypes: map[string]*configschema.Block{ + "aws_security_group": simpleTestSchema(), + "aws_instance": simpleTestSchema(), + "aws_load_balancer": simpleTestSchema(), }, }, } openstackProvider := &MockProvider{ - GetSchemaResponse: providers.GetSchemaResponse{ - Provider: providers.Schema{Block: simpleTestSchema()}, - ResourceTypes: map[string]providers.Schema{ - "openstack_floating_ip": {Block: simpleTestSchema()}, + GetSchemaReturn: &ProviderSchema{ + Provider: simpleTestSchema(), + ResourceTypes: map[string]*configschema.Block{ + "openstack_floating_ip": simpleTestSchema(), }, }, } diff --git a/terraform/hook_test.go b/terraform/hook_test.go index 48316b53c..616ab3119 100644 --- a/terraform/hook_test.go +++ b/terraform/hook_test.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/states" ) @@ -90,7 +91,7 @@ func (h *testHook) PreImportState(addr addrs.AbsResourceInstance, importID strin return HookActionContinue, nil } -func (h *testHook) PostImportState(addr addrs.AbsResourceInstance, imported []*states.ImportedObject) (HookAction, error) { +func (h *testHook) PostImportState(addr addrs.AbsResourceInstance, imported []providers.ImportedResource) (HookAction, error) { h.Calls = append(h.Calls, &testHookCall{"PostImportState", addr.String()}) return HookActionContinue, nil } diff --git a/terraform/provider_mock.go b/terraform/provider_mock.go index 83cfc134c..e8995a7f1 100644 --- a/terraform/provider_mock.go +++ b/terraform/provider_mock.go @@ -1,9 +1,11 @@ package terraform import ( + "encoding/json" "fmt" "sync" + "github.com/hashicorp/terraform/config/hcl2shim" "github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/providers" @@ -73,6 +75,9 @@ type MockProvider struct { ImportResourceStateResponse providers.ImportResourceStateResponse ImportResourceStateRequest providers.ImportResourceStateRequest ImportResourceStateFn func(providers.ImportResourceStateRequest) providers.ImportResourceStateResponse + // Legacy return type for existing tests, which will be shimmed into an + // ImportResourceStateResponse if set + ImportStateReturn []*InstanceState ReadDataSourceCalled bool ReadDataSourceResponse providers.ReadDataSourceResponse @@ -259,6 +264,29 @@ func (p *MockProvider) ImportResourceState(r providers.ImportResourceStateReques p.Lock() defer p.Unlock() + if p.ImportStateReturn != nil { + for _, is := range p.ImportStateReturn { + is.Attributes["id"] = is.ID + schema := p.GetSchemaReturn.ResourceTypes[r.TypeName] + private, err := json.Marshal(is.Meta) + if err != nil { + panic(err) + } + + state, err := hcl2shim.HCL2ValueFromFlatmap(is.Attributes, schema.ImpliedType()) + if err != nil { + panic(err) + } + p.ImportResourceStateResponse.ImportedResources = append( + p.ImportResourceStateResponse.ImportedResources, + providers.ImportedResource{ + TypeName: r.TypeName, + State: state, + Private: private, + }) + } + } + p.ImportResourceStateCalled = true p.ImportResourceStateRequest = r if p.ImportResourceStateFn != nil { diff --git a/terraform/schemas_test.go b/terraform/schemas_test.go index 1283b60b7..85f0dccdd 100644 --- a/terraform/schemas_test.go +++ b/terraform/schemas_test.go @@ -12,7 +12,7 @@ func simpleTestSchemas() *Schemas { "test": provider.GetSchemaReturn, }, provisioners: map[string]*configschema.Block{ - "test": provisioner.GetConfigSchemaReturnSchema, + "test": provisioner.GetSchemaResponse.Provisioner, }, } }