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, }, } }