diff --git a/.changes/unreleased/ENHANCEMENTS-20231130-092645.yaml b/.changes/unreleased/ENHANCEMENTS-20231130-092645.yaml new file mode 100644 index 000000000..f3983a3b8 --- /dev/null +++ b/.changes/unreleased/ENHANCEMENTS-20231130-092645.yaml @@ -0,0 +1,6 @@ +kind: ENHANCEMENTS +body: 'helper/resource: Automatically add `required_providers` configuration to `TestStep.Config` + Terraform language configuration when using Terraform >= 1.0.*' +time: 2023-11-30T09:26:45.606859Z +custom: + Issue: "216" diff --git a/helper/resource/testcase_providers_test.go b/helper/resource/testcase_providers_test.go index 023e76dc4..45af1c784 100644 --- a/helper/resource/testcase_providers_test.go +++ b/helper/resource/testcase_providers_test.go @@ -16,6 +16,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-testing/internal/plugintest" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -223,7 +225,8 @@ provider "test" {} "test": {}, }, }, - expected: `provider "test" {}`, + expected: ` +provider "test" {}`, }, } @@ -365,9 +368,7 @@ func TestTest_TestCase_ProtoV5ProviderFactories(t *testing.T) { Test(&mockT{}, TestCase{ ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ - "test": func() (tfprotov5.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProtov5ProviderServer(testprovider.Protov5Provider{}), }, Steps: []TestStep{ { @@ -401,9 +402,7 @@ func TestTest_TestCase_ProtoV6ProviderFactories(t *testing.T) { Test(&mockT{}, TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, Steps: []TestStep{ { @@ -438,7 +437,7 @@ func TestTest_TestCase_ProviderFactories(t *testing.T) { Test(&mockT{}, TestCase{ ProviderFactories: map[string]func() (*schema.Provider, error){ "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return nil, nil + return &schema.Provider{}, nil }, }, Steps: []TestStep{ diff --git a/helper/resource/testing_new.go b/helper/resource/testing_new.go index 96ad3eec0..2134abb9d 100644 --- a/helper/resource/testing_new.go +++ b/helper/resource/testing_new.go @@ -228,13 +228,23 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest var testStepConfig teststep.Config + rawCfg, err := step.providerConfig(ctx, hasProviderBlock, helper.TerraformVersion()) + + if err != nil { + logging.HelperResourceError(ctx, + "TestStep error generating provider configuration", + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("TestStep %d/%d error generating provider configuration: %s", stepNumber, len(c.Steps), err) + } + // Return value from step.providerConfig() is assigned to Raw as this was previously being // passed to wd.SetConfig() directly when the second argument to wd.SetConfig() accepted a // configuration string. confRequest := teststep.PrepareConfigurationRequest{ Directory: step.ConfigDirectory, File: step.ConfigFile, - Raw: step.providerConfig(ctx, hasProviderBlock), + Raw: rawCfg, TestStepConfigRequest: config.TestStepConfigRequest{ StepNumber: stepIndex + 1, TestName: t.Name(), @@ -354,7 +364,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if cfg != nil { logging.HelperResourceTrace(ctx, "TestStep is Config mode") - err := testStepNewConfig(ctx, t, c, wd, step, providers, stepIndex) + err := testStepNewConfig(ctx, t, c, wd, step, providers, stepIndex, helper) if step.ExpectError != nil { logging.HelperResourceDebug(ctx, "Checking TestStep ExpectError") @@ -413,7 +423,15 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest } } - mergedConfig := step.mergedConfig(ctx, c, hasTerraformBlock, hasProviderBlock) + mergedConfig, err := step.mergedConfig(ctx, c, hasTerraformBlock, hasProviderBlock, helper.TerraformVersion()) + + if err != nil { + logging.HelperResourceError(ctx, + "Error generating merged configuration", + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("Error generating merged configuration: %s", err) + } confRequest := teststep.PrepareConfigurationRequest{ Directory: step.ConfigDirectory, @@ -469,7 +487,7 @@ func planIsEmpty(plan *tfjson.Plan) bool { return true } -func testIDRefresh(ctx context.Context, t testing.T, c TestCase, wd *plugintest.WorkingDir, step TestStep, r *terraform.ResourceState, providers *providerFactories, stepIndex int) error { +func testIDRefresh(ctx context.Context, t testing.T, c TestCase, wd *plugintest.WorkingDir, step TestStep, r *terraform.ResourceState, providers *providerFactories, stepIndex int, helper *plugintest.Helper) error { t.Helper() // Build the state. The state is just the resource with an ID. There @@ -521,11 +539,17 @@ func testIDRefresh(ctx context.Context, t testing.T, c TestCase, wd *plugintest. t.Fatalf("Error setting import test config: %s", err) } + rawCfg, err := step.providerConfig(ctx, hasProviderBlock, helper.TerraformVersion()) + + if err != nil { + t.Fatalf("Error generating import provider config: %s", err) + } + defer func() { confRequest := teststep.PrepareConfigurationRequest{ Directory: step.ConfigDirectory, File: step.ConfigFile, - Raw: step.providerConfig(ctx, hasProviderBlock), + Raw: rawCfg, TestStepConfigRequest: config.TestStepConfigRequest{ StepNumber: stepIndex + 1, TestName: t.Name(), diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index 5df394d94..2ad170cff 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -19,7 +19,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/internal/plugintest" ) -func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugintest.WorkingDir, step TestStep, providers *providerFactories, stepIndex int) error { +func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugintest.WorkingDir, step TestStep, providers *providerFactories, stepIndex int, helper *plugintest.Helper) error { t.Helper() configRequest := teststep.PrepareConfigurationRequest{ @@ -61,7 +61,15 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint } } - mergedConfig := step.mergedConfig(ctx, c, hasTerraformBlock, hasProviderBlock) + mergedConfig, err := step.mergedConfig(ctx, c, hasTerraformBlock, hasProviderBlock, helper.TerraformVersion()) + + if err != nil { + logging.HelperResourceError(ctx, + "Error generating merged configuration", + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("Error generating merged configuration: %s", err) + } confRequest := teststep.PrepareConfigurationRequest{ Directory: step.ConfigDirectory, @@ -75,7 +83,7 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint testStepConfig := teststep.Configuration(confRequest) - err := wd.SetConfig(ctx, testStepConfig, step.ConfigVariables) + err = wd.SetConfig(ctx, testStepConfig, step.ConfigVariables) if err != nil { return fmt.Errorf("Error setting config: %w", err) } @@ -323,7 +331,7 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint // this fails. If refresh isn't read-only, then this will have // caught a different bug. if idRefreshCheck != nil { - if err := testIDRefresh(ctx, t, c, wd, step, idRefreshCheck, providers, stepIndex); err != nil { + if err := testIDRefresh(ctx, t, c, wd, step, idRefreshCheck, providers, stepIndex, helper); err != nil { return fmt.Errorf( "[ERROR] Test: ID-only test failed: %s", err) } diff --git a/helper/resource/testing_test.go b/helper/resource/testing_test.go index e3a401cd1..00137efc9 100644 --- a/helper/resource/testing_test.go +++ b/helper/resource/testing_test.go @@ -13,9 +13,8 @@ import ( "strings" "testing" - testinginterface "github.com/mitchellh/go-testing-interface" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + testinginterface "github.com/mitchellh/go-testing-interface" "github.com/hashicorp/terraform-plugin-testing/terraform" ) @@ -35,7 +34,7 @@ func TestParallelTest(t *testing.T) { IsUnitTest: true, ProviderFactories: map[string]func() (*schema.Provider, error){ "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return nil, nil + return &schema.Provider{}, nil }, }, Steps: []TestStep{ diff --git a/helper/resource/teststep_providers.go b/helper/resource/teststep_providers.go index 1e2aa843e..bd9f43b86 100644 --- a/helper/resource/teststep_providers.go +++ b/helper/resource/teststep_providers.go @@ -5,10 +5,18 @@ package resource import ( "context" + "encoding/json" "fmt" "strings" + + "github.com/hashicorp/go-version" ) +// tfBlockMinReqTFVersion is used to prevent errors arising from +// adding required providers to the terraform block when Terraform +// is any version prior to v1.0.0 +const tfBlockMinReqTFVersion = "1.0.0" + // mergedConfig prepends any necessary terraform configuration blocks to the // TestStep Config. // @@ -21,7 +29,7 @@ import ( // When TestStep.ConfigDirectory is used, the expectation is that the // Terraform configuration files will specify a terraform configuration // block and/or provider blocks as necessary. -func (s TestStep) mergedConfig(ctx context.Context, testCase TestCase, configHasTerraformBlock, configHasProviderBlock bool) string { +func (s TestStep) mergedConfig(ctx context.Context, testCase TestCase, configHasTerraformBlock, configHasProviderBlock bool, tfVersion *version.Version) (string, error) { var config strings.Builder // Prevent issues with existing configurations containing the terraform @@ -29,24 +37,36 @@ func (s TestStep) mergedConfig(ctx context.Context, testCase TestCase, configHas if configHasTerraformBlock { config.WriteString(s.Config) - return config.String() + return config.String(), nil } if testCase.hasProviders(ctx) { - config.WriteString(testCase.providerConfig(ctx, configHasProviderBlock)) + cfg, err := s.providerConfigTestCase(ctx, configHasProviderBlock, testCase, tfVersion) + + if err != nil { + return "", err + } + + config.WriteString(cfg) } else { - config.WriteString(s.providerConfig(ctx, configHasProviderBlock)) + cfg, err := s.providerConfig(ctx, configHasProviderBlock, tfVersion) + + if err != nil { + return "", err + } + + config.WriteString(cfg) } config.WriteString(s.Config) - return config.String() + return config.String(), nil } // providerConfig takes the list of providers in a TestStep and returns a // config with only empty provider blocks. This is useful for Import, where no // config is provided, but the providers must be defined. -func (s TestStep) providerConfig(_ context.Context, skipProviderBlock bool) string { +func (s TestStep) providerConfig(_ context.Context, skipProviderBlock bool, tfVersion *version.Version) (string, error) { var providerBlocks, requiredProviderBlocks strings.Builder for name, externalProvider := range s.ExternalProviders { @@ -71,6 +91,140 @@ func (s TestStep) providerConfig(_ context.Context, skipProviderBlock bool) stri requiredProviderBlocks.WriteString(" }\n") } + minReqVersion, err := version.NewVersion(tfBlockMinReqTFVersion) + + if err != nil { + return "", err + } + + for name := range s.ProviderFactories { + if tfVersion.LessThan(minReqVersion) { + break + } + + requiredProviderBlocks.WriteString(addTerraformBlockSource(name, s.Config)) + } + + for name := range s.ProtoV5ProviderFactories { + if tfVersion.LessThan(minReqVersion) { + break + } + + requiredProviderBlocks.WriteString(addTerraformBlockSource(name, s.Config)) + } + + for name := range s.ProtoV6ProviderFactories { + if tfVersion.LessThan(minReqVersion) { + break + } + + requiredProviderBlocks.WriteString(addTerraformBlockSource(name, s.Config)) + } + + if requiredProviderBlocks.Len() > 0 { + return fmt.Sprintf(` +terraform { + required_providers { +%[1]s + } +} + +%[2]s +`, strings.TrimSuffix(requiredProviderBlocks.String(), "\n"), providerBlocks.String()), nil + } + + return providerBlocks.String(), nil +} + +func (s TestStep) providerConfigTestCase(_ context.Context, skipProviderBlock bool, testCase TestCase, tfVersion *version.Version) (string, error) { + var providerBlocks, requiredProviderBlocks strings.Builder + + providerNames := make(map[string]struct{}, len(testCase.Providers)) + + for name := range testCase.Providers { + providerNames[name] = struct{}{} + } + + for name := range testCase.ProviderFactories { + delete(providerNames, name) + } + + // [BF] The Providers field handling predates the logic being moved to this + // method. It's not entirely clear to me at this time why this field + // is being used and not the others, but leaving it here just in case + // it does have a special purpose that wasn't being unit tested prior. + for name := range providerNames { + providerBlocks.WriteString(fmt.Sprintf("provider %q {}\n", name)) + + requiredProviderBlocks.WriteString(fmt.Sprintf(" %s = {\n", name)) + + requiredProviderBlocks.WriteString(" }\n") + } + + for name, externalProvider := range testCase.ExternalProviders { + if !skipProviderBlock { + providerBlocks.WriteString(fmt.Sprintf("provider %q {}\n", name)) + } + + if externalProvider.Source == "" && externalProvider.VersionConstraint == "" { + continue + } + + requiredProviderBlocks.WriteString(fmt.Sprintf(" %s = {\n", name)) + + if externalProvider.Source != "" { + requiredProviderBlocks.WriteString(fmt.Sprintf(" source = %q\n", externalProvider.Source)) + } + + if externalProvider.VersionConstraint != "" { + requiredProviderBlocks.WriteString(fmt.Sprintf(" version = %q\n", externalProvider.VersionConstraint)) + } + + requiredProviderBlocks.WriteString(" }\n") + } + + minReqVersion, err := version.NewVersion(tfBlockMinReqTFVersion) + + if err != nil { + return "", err + } + + for name := range testCase.ProviderFactories { + if tfVersion.LessThan(minReqVersion) { + break + } + + providerFactoryBlocks := addTerraformBlockSource(name, s.Config) + + if len(providerFactoryBlocks) > 0 { + requiredProviderBlocks.WriteString(providerFactoryBlocks) + } + } + + for name := range testCase.ProtoV5ProviderFactories { + if tfVersion.LessThan(minReqVersion) { + break + } + + protov5ProviderFactoryBlocks := addTerraformBlockSource(name, s.Config) + + if len(protov5ProviderFactoryBlocks) > 0 { + requiredProviderBlocks.WriteString(protov5ProviderFactoryBlocks) + } + } + + for name := range testCase.ProtoV6ProviderFactories { + if tfVersion.LessThan(minReqVersion) { + break + } + + protov6ProviderFactoryBlocks := addTerraformBlockSource(name, s.Config) + + if len(protov6ProviderFactoryBlocks) > 0 { + requiredProviderBlocks.WriteString(addTerraformBlockSource(name, s.Config)) + } + } + if requiredProviderBlocks.Len() > 0 { return fmt.Sprintf(` terraform { @@ -80,8 +234,25 @@ terraform { } %[2]s -`, strings.TrimSuffix(requiredProviderBlocks.String(), "\n"), providerBlocks.String()) +`, strings.TrimSuffix(requiredProviderBlocks.String(), "\n"), providerBlocks.String()), nil + } + + return providerBlocks.String(), nil +} + +func addTerraformBlockSource(name, config string) string { + var js json.RawMessage + + // Do not process JSON. + if err := json.Unmarshal([]byte(config), &js); err == nil { + return "" } + var providerBlocks strings.Builder + + providerBlocks.WriteString(fmt.Sprintf(" %s = {\n", name)) + providerBlocks.WriteString(fmt.Sprintf(" source = %q\n", getProviderAddr(name))) + providerBlocks.WriteString(" }\n") + return providerBlocks.String() } diff --git a/helper/resource/teststep_providers_test.go b/helper/resource/teststep_providers_test.go index 0bad2bebe..e4d1fd7fb 100644 --- a/helper/resource/teststep_providers_test.go +++ b/helper/resource/teststep_providers_test.go @@ -16,6 +16,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/go-cty/cty" + "github.com/hashicorp/go-version" "github.com/hashicorp/terraform-plugin-go/tfprotov5" "github.com/hashicorp/terraform-plugin-go/tfprotov6" "github.com/hashicorp/terraform-plugin-go/tftypes" @@ -33,7 +34,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) -func TestStepMergedConfig(t *testing.T) { +func TestStepMergedConfig_TF_0_15(t *testing.T) { t.Parallel() testCases := map[string]struct { @@ -661,7 +662,736 @@ resource "test_test" "test" {} t.Run(name, func(t *testing.T) { t.Parallel() - got := testCase.testStep.mergedConfig(context.Background(), testCase.testCase, testCase.configHasTerraformBlock, testCase.configHasProviderBlock) + got, err := testCase.testStep.mergedConfig(context.Background(), testCase.testCase, testCase.configHasTerraformBlock, testCase.configHasProviderBlock, tfversion.Version0_15_0) + + if err != nil { + t.Errorf("cannot generate merged config: %s", err) + } + + if diff := cmp.Diff(strings.TrimSpace(got), strings.TrimSpace(testCase.expected)); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} + +func TestStepMergedConfig_TF_1_6(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + testCase TestCase + testStep TestStep + configHasTerraformBlock bool + configHasProviderBlock bool + expected string + }{ + "testcase-externalproviders-and-protov5providerfactories": { + testCase: TestCase{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ + "localtest": nil, + }, + }, + testStep: TestStep{ + Config: ` +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} + + +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + "testcase-externalproviders-and-protov6providerfactories": { + testCase: TestCase{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "localtest": nil, + }, + }, + testStep: TestStep{ + Config: ` +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} + + +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + "testcase-externalproviders-and-providerfactories": { + testCase: TestCase{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "localtest": nil, + }, + }, + testStep: TestStep{ + Config: ` +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} + + +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + "testcase-externalproviders-missing-source-and-versionconstraint": { + testCase: TestCase{ + ExternalProviders: map[string]ExternalProvider{ + "test": {}, + }, + }, + testStep: TestStep{ + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +provider "test" {} + +resource "test_test" "test" {} +`, + }, + "testcase-externalproviders-source-and-versionconstraint": { + testCase: TestCase{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + VersionConstraint: "1.2.3", + }, + }, + }, + testStep: TestStep{ + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + version = "1.2.3" + } + } +} + +provider "test" {} + + +resource "test_test" "test" {} +`, + }, + "testcase-externalproviders-source": { + testCase: TestCase{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + }, + }, + }, + testStep: TestStep{ + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + +provider "test" {} + + +resource "test_test" "test" {} +`, + }, + "testcase-externalproviders-versionconstraint": { + testCase: TestCase{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + VersionConstraint: "1.2.3", + }, + }, + }, + testStep: TestStep{ + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + version = "1.2.3" + } + } +} + +provider "test" {} + + +resource "test_test" "test" {} +`, + }, + "testcase-protov5providerfactories": { + testCase: TestCase{ + ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ + "test": nil, + }, + }, + testStep: TestStep{ + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + + + +resource "test_test" "test" {} +`, + }, + "testcase-protov6providerfactories": { + testCase: TestCase{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "test": nil, + }, + }, + testStep: TestStep{ + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + + + +resource "test_test" "test" {} +`, + }, + "testcase-providerfactories": { + testCase: TestCase{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": nil, + }, + }, + testStep: TestStep{ + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + + + +resource "test_test" "test" {} +`, + }, + "teststep-externalproviders-and-protov5providerfactories": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ + "localtest": nil, + }, + Config: ` +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} + + +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + "teststep-externalproviders-and-protov6providerfactories": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "localtest": nil, + }, + Config: ` +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} + + +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + "teststep-externalproviders-and-providerfactories": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "localtest": nil, + }, + Config: ` +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} + + +resource "externaltest_test" "test" {} + +resource "localtest_test" "test" {} +`, + }, + "teststep-externalproviders-config-with-provider-block-quoted": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + VersionConstraint: "1.2.3", + }, + }, + Config: ` +provider "test" {} + +resource "test_test" "test" {} +`, + }, + configHasProviderBlock: true, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + version = "1.2.3" + } + } +} + + + +provider "test" {} + +resource "test_test" "test" {} +`, + }, + "teststep-externalproviders-config-with-provider-block-unquoted": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + VersionConstraint: "1.2.3", + }, + }, + Config: ` +provider test {} + +resource "test_test" "test" {} +`, + }, + configHasProviderBlock: true, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + version = "1.2.3" + } + } +} + + + +provider test {} + +resource "test_test" "test" {} +`, + }, + "teststep-externalproviders-config-with-terraform-block": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + VersionConstraint: "1.2.3", + }, + }, + Config: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + version = "1.2.3" + } + } +} + +resource "test_test" "test" {} +`, + }, + configHasTerraformBlock: true, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + version = "1.2.3" + } + } +} + +resource "test_test" "test" {} +`, + }, + "teststep-externalproviders-missing-source-and-versionconstraint": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": {}, + }, + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +provider "test" {} + +resource "test_test" "test" {} +`, + }, + "teststep-externalproviders-source-and-versionconstraint": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + VersionConstraint: "1.2.3", + }, + }, + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + version = "1.2.3" + } + } +} + +provider "test" {} + + +resource "test_test" "test" {} +`, + }, + "teststep-externalproviders-source": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + }, + }, + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + +provider "test" {} + + +resource "test_test" "test" {} +`, + }, + "teststep-externalproviders-versionconstraint": { + testCase: TestCase{}, + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + VersionConstraint: "1.2.3", + }, + }, + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + version = "1.2.3" + } + } +} + +provider "test" {} + + +resource "test_test" "test" {} +`, + }, + "teststep-protov5providerfactories": { + testCase: TestCase{}, + testStep: TestStep{ + ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ + "test": nil, + }, + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + + + +resource "test_test" "test" {} +`, + }, + "teststep-protov6providerfactories": { + testCase: TestCase{}, + testStep: TestStep{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "test": nil, + }, + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + + + +resource "test_test" "test" {} +`, + }, + "teststep-providerfactories": { + testCase: TestCase{}, + testStep: TestStep{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": nil, + }, + Config: ` +resource "test_test" "test" {} +`, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + + + +resource "test_test" "test" {} +`, + }, + } + + v, err := version.NewVersion("1.6.0") + + if err != nil { + t.Errorf("error generating version: %s", err) + } + + for name, testCase := range testCases { + name, testCase := name, testCase + + t.Run(name, func(t *testing.T) { + t.Parallel() + + got, err := testCase.testStep.mergedConfig(context.Background(), testCase.testCase, testCase.configHasTerraformBlock, testCase.configHasProviderBlock, v) + + if err != nil { + t.Errorf("cannot generate merged config: %s", err) + } if diff := cmp.Diff(strings.TrimSpace(got), strings.TrimSpace(testCase.expected)); diff != "" { t.Errorf("unexpected difference: %s", diff) @@ -670,7 +1400,7 @@ resource "test_test" "test" {} } } -func TestStepProviderConfig(t *testing.T) { +func TestStepProviderConfig_TF_0_15(t *testing.T) { t.Parallel() testCases := map[string]struct { @@ -876,7 +1606,266 @@ provider "test" {} t.Run(name, func(t *testing.T) { t.Parallel() - got := testCase.testStep.providerConfig(context.Background(), testCase.skipProviderBlock) + got, err := testCase.testStep.providerConfig(context.Background(), testCase.skipProviderBlock, tfversion.Version0_15_0) + + if err != nil { + t.Errorf("cannot generate provider config: %s", err) + } + + if diff := cmp.Diff(strings.TrimSpace(got), strings.TrimSpace(testCase.expected)); diff != "" { + t.Errorf("unexpected difference: %s", diff) + } + }) + } +} + +func TestStepProviderConfig_TF_1_6(t *testing.T) { + t.Parallel() + + testCases := map[string]struct { + testStep TestStep + skipProviderBlock bool + expected string + }{ + "externalproviders-and-protov5providerfactories": { + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ + "localtest": nil, + }, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} +`, + }, + "externalproviders-and-protov6providerfactories": { + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "localtest": nil, + }, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} +`, + }, + "externalproviders-and-providerfactories": { + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "externaltest": { + Source: "registry.terraform.io/hashicorp/externaltest", + VersionConstraint: "1.2.3", + }, + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "localtest": nil, + }, + }, + expected: ` +terraform { + required_providers { + externaltest = { + source = "registry.terraform.io/hashicorp/externaltest" + version = "1.2.3" + } + localtest = { + source = "registry.terraform.io/hashicorp/localtest" + } + } +} + +provider "externaltest" {} +`, + }, + "externalproviders-missing-source-and-versionconstraint": { + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": {}, + }, + }, + expected: `provider "test" {}`, + }, + "externalproviders-skip-provider-block": { + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + VersionConstraint: "1.2.3", + }, + }, + }, + skipProviderBlock: true, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + version = "1.2.3" + } + } +} +`, + }, + "externalproviders-source-and-versionconstraint": { + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + VersionConstraint: "1.2.3", + }, + }, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + version = "1.2.3" + } + } +} + +provider "test" {} +`, + }, + "externalproviders-source": { + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + Source: "registry.terraform.io/hashicorp/test", + }, + }, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +} + +provider "test" {} +`, + }, + "externalproviders-versionconstraint": { + testStep: TestStep{ + ExternalProviders: map[string]ExternalProvider{ + "test": { + VersionConstraint: "1.2.3", + }, + }, + }, + expected: ` +terraform { + required_providers { + test = { + version = "1.2.3" + } + } +} + +provider "test" {} +`, + }, + "protov5providerfactories": { + testStep: TestStep{ + ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ + "test": nil, + }, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +}`, + }, + "protov6providerfactories": { + testStep: TestStep{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "test": nil, + }, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +}`, + }, + "providerfactories": { + testStep: TestStep{ + ProviderFactories: map[string]func() (*schema.Provider, error){ + "test": nil, + }, + }, + expected: ` +terraform { + required_providers { + test = { + source = "registry.terraform.io/hashicorp/test" + } + } +}`, + }, + } + + v, err := version.NewVersion("1.6.0") + + if err != nil { + t.Errorf("error generating version: %s", err) + } + + for name, testCase := range testCases { + name, testCase := name, testCase + + t.Run(name, func(t *testing.T) { + t.Parallel() + + got, err := testCase.testStep.providerConfig(context.Background(), testCase.skipProviderBlock, v) + + if err != nil { + t.Errorf("cannot generate provider config: %s", err) + } if diff := cmp.Diff(strings.TrimSpace(got), strings.TrimSpace(testCase.expected)); diff != "" { t.Errorf("unexpected difference: %s", diff) @@ -1350,9 +2339,7 @@ func TestTest_TestStep_ProtoV5ProviderFactories(t *testing.T) { { Config: "# not empty", ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ - "test": func() (tfprotov5.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProtov5ProviderServer(testprovider.Protov5Provider{}), }, }, }, @@ -1386,9 +2373,7 @@ func TestTest_TestStep_ProtoV6ProviderFactories(t *testing.T) { { Config: "# not empty", ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, }, }, @@ -1486,7 +2471,7 @@ func TestTest_TestStep_ProviderFactories(t *testing.T) { Config: "# not empty", ProviderFactories: map[string]func() (*schema.Provider, error){ "test": func() (*schema.Provider, error) { //nolint:unparam // required signature - return nil, nil + return &schema.Provider{}, nil }, }, }, diff --git a/internal/testing/testprovider/provider_protov5.go b/internal/testing/testprovider/provider_protov5.go new file mode 100644 index 000000000..65b4ee5ef --- /dev/null +++ b/internal/testing/testprovider/provider_protov5.go @@ -0,0 +1,51 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package testprovider + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/datasource" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/provider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/resource" +) + +var _ provider.Protov5Provider = Protov5Provider{} + +// Protov5Provider is a declarative provider implementation for unit testing in this +// Go module. The provider is unimplemented except for the Schema method. +type Protov5Provider struct { + ConfigureResponse *provider.Protov5ConfigureResponse + DataSources map[string]DataSource + Resources map[string]Resource + SchemaResponse *provider.Protov5SchemaResponse + StopResponse *provider.Protov5StopResponse + ValidateConfigResponse *provider.Protov5ValidateConfigResponse +} + +func (p Protov5Provider) Configure(ctx context.Context, req provider.Protov5ConfigureRequest, resp *provider.Protov5ConfigureResponse) { + +} + +func (p Protov5Provider) DataSourcesMap() map[string]datasource.DataSource { + return nil +} + +func (p Protov5Provider) ResourcesMap() map[string]resource.Resource { + return nil +} + +func (p Protov5Provider) Stop(ctx context.Context, req provider.Protov5StopRequest, resp *provider.Protov5StopResponse) { +} + +func (p Protov5Provider) Schema(ctx context.Context, req provider.Protov5SchemaRequest, resp *provider.Protov5SchemaResponse) { + resp.Schema = &tfprotov5.Schema{ + Block: &tfprotov5.SchemaBlock{}, + } +} + +func (p Protov5Provider) ValidateConfig(ctx context.Context, req provider.Protov5ValidateConfigRequest, resp *provider.Protov5ValidateConfigResponse) { +} diff --git a/internal/testing/testsdk/provider/provider_protov5.go b/internal/testing/testsdk/provider/provider_protov5.go new file mode 100644 index 000000000..27f4f1659 --- /dev/null +++ b/internal/testing/testsdk/provider/provider_protov5.go @@ -0,0 +1,53 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package provider + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-go/tftypes" + + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/datasource" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/resource" +) + +type Protov5Provider interface { + Configure(context.Context, Protov5ConfigureRequest, *Protov5ConfigureResponse) + DataSourcesMap() map[string]datasource.DataSource + ResourcesMap() map[string]resource.Resource + Schema(context.Context, Protov5SchemaRequest, *Protov5SchemaResponse) + Stop(context.Context, Protov5StopRequest, *Protov5StopResponse) + ValidateConfig(context.Context, Protov5ValidateConfigRequest, *Protov5ValidateConfigResponse) +} + +type Protov5ConfigureRequest struct { + Config tftypes.Value +} + +type Protov5ConfigureResponse struct { + Diagnostics []*tfprotov6.Diagnostic +} + +type Protov5SchemaRequest struct{} + +type Protov5SchemaResponse struct { + Diagnostics []*tfprotov5.Diagnostic + Schema *tfprotov5.Schema +} + +type Protov5StopRequest struct{} + +type Protov5StopResponse struct { + Error error +} + +type Protov5ValidateConfigRequest struct { + Config tftypes.Value +} + +type Protov5ValidateConfigResponse struct { + Diagnostics []*tfprotov5.Diagnostic +} diff --git a/internal/testing/testsdk/providerserver/providerserver_protov5.go b/internal/testing/testsdk/providerserver/providerserver_protov5.go new file mode 100644 index 000000000..1c945f68f --- /dev/null +++ b/internal/testing/testsdk/providerserver/providerserver_protov5.go @@ -0,0 +1,104 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package providerserver + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/provider" +) + +var _ tfprotov5.ProviderServer = Protov5ProviderServer{} + +// NewProtov5ProviderServer returns a protocol version 5 provider server which only +// implements GetProviderSchema, for consumption with ProtoV5ProviderFactories. +func NewProtov5ProviderServer(p provider.Protov5Provider) func() (tfprotov5.ProviderServer, error) { + return NewProtov5ProviderServerWithError(p, nil) +} + +// NewProtov5ProviderServerWithError returns a protocol version 5 provider server, +// and an associated error for consumption with ProtoV5ProviderFactories. +func NewProtov5ProviderServerWithError(p provider.Protov5Provider, err error) func() (tfprotov5.ProviderServer, error) { + providerServer := Protov5ProviderServer{ + Provider: p, + } + + return func() (tfprotov5.ProviderServer, error) { + return providerServer, err + } +} + +// Protov5ProviderServer is a version 5 provider server that only implements GetProviderSchema. +type Protov5ProviderServer struct { + Provider provider.Protov5Provider +} + +func (s Protov5ProviderServer) GetMetadata(ctx context.Context, request *tfprotov5.GetMetadataRequest) (*tfprotov5.GetMetadataResponse, error) { + return &tfprotov5.GetMetadataResponse{}, nil +} + +func (s Protov5ProviderServer) ApplyResourceChange(ctx context.Context, req *tfprotov5.ApplyResourceChangeRequest) (*tfprotov5.ApplyResourceChangeResponse, error) { + return &tfprotov5.ApplyResourceChangeResponse{}, nil +} + +func (s Protov5ProviderServer) ConfigureProvider(ctx context.Context, req *tfprotov5.ConfigureProviderRequest) (*tfprotov5.ConfigureProviderResponse, error) { + return &tfprotov5.ConfigureProviderResponse{}, nil +} + +func (s Protov5ProviderServer) GetProviderSchema(ctx context.Context, req *tfprotov5.GetProviderSchemaRequest) (*tfprotov5.GetProviderSchemaResponse, error) { + providerReq := provider.Protov5SchemaRequest{} + providerResp := &provider.Protov5SchemaResponse{} + + s.Provider.Schema(ctx, providerReq, providerResp) + + resp := &tfprotov5.GetProviderSchemaResponse{ + DataSourceSchemas: map[string]*tfprotov5.Schema{}, + Diagnostics: providerResp.Diagnostics, + Provider: providerResp.Schema, + ResourceSchemas: map[string]*tfprotov5.Schema{}, + ServerCapabilities: &tfprotov5.ServerCapabilities{ + PlanDestroy: true, + }, + } + + return resp, nil +} + +func (s Protov5ProviderServer) ImportResourceState(ctx context.Context, req *tfprotov5.ImportResourceStateRequest) (*tfprotov5.ImportResourceStateResponse, error) { + return &tfprotov5.ImportResourceStateResponse{}, nil +} + +func (s Protov5ProviderServer) PlanResourceChange(ctx context.Context, req *tfprotov5.PlanResourceChangeRequest) (*tfprotov5.PlanResourceChangeResponse, error) { + return &tfprotov5.PlanResourceChangeResponse{}, nil +} + +func (s Protov5ProviderServer) PrepareProviderConfig(ctx context.Context, request *tfprotov5.PrepareProviderConfigRequest) (*tfprotov5.PrepareProviderConfigResponse, error) { + return &tfprotov5.PrepareProviderConfigResponse{}, nil +} + +func (s Protov5ProviderServer) ReadDataSource(ctx context.Context, req *tfprotov5.ReadDataSourceRequest) (*tfprotov5.ReadDataSourceResponse, error) { + return &tfprotov5.ReadDataSourceResponse{}, nil +} + +func (s Protov5ProviderServer) ReadResource(ctx context.Context, req *tfprotov5.ReadResourceRequest) (*tfprotov5.ReadResourceResponse, error) { + return &tfprotov5.ReadResourceResponse{}, nil +} + +func (s Protov5ProviderServer) StopProvider(ctx context.Context, req *tfprotov5.StopProviderRequest) (*tfprotov5.StopProviderResponse, error) { + return &tfprotov5.StopProviderResponse{}, nil +} + +func (s Protov5ProviderServer) UpgradeResourceState(ctx context.Context, req *tfprotov5.UpgradeResourceStateRequest) (*tfprotov5.UpgradeResourceStateResponse, error) { + return &tfprotov5.UpgradeResourceStateResponse{}, nil +} + +func (s Protov5ProviderServer) ValidateDataSourceConfig(ctx context.Context, request *tfprotov5.ValidateDataSourceConfigRequest) (*tfprotov5.ValidateDataSourceConfigResponse, error) { + return &tfprotov5.ValidateDataSourceConfigResponse{}, nil +} + +func (s Protov5ProviderServer) ValidateResourceTypeConfig(ctx context.Context, request *tfprotov5.ValidateResourceTypeConfigRequest) (*tfprotov5.ValidateResourceTypeConfigResponse, error) { + return &tfprotov5.ValidateResourceTypeConfigResponse{}, nil +} diff --git a/tfversion/all_test.go b/tfversion/all_test.go index 3fa2b27b1..aa326d6bf 100644 --- a/tfversion/all_test.go +++ b/tfversion/all_test.go @@ -12,6 +12,8 @@ import ( r "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/internal/plugintest" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -21,9 +23,7 @@ func Test_All_RunTest(t *testing.T) { //nolint:paralleltest r.UnitTest(t, r.TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.Any( diff --git a/tfversion/any_test.go b/tfversion/any_test.go index 89f8fd313..76eacaa01 100644 --- a/tfversion/any_test.go +++ b/tfversion/any_test.go @@ -12,6 +12,8 @@ import ( r "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/internal/plugintest" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -21,9 +23,7 @@ func Test_Any_RunTest(t *testing.T) { //nolint:paralleltest r.UnitTest(t, r.TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.Any( diff --git a/tfversion/require_above_test.go b/tfversion/require_above_test.go index cbcdf8ca1..865e0c77b 100644 --- a/tfversion/require_above_test.go +++ b/tfversion/require_above_test.go @@ -11,6 +11,8 @@ import ( r "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/internal/plugintest" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/tfversion" testinginterface "github.com/mitchellh/go-testing-interface" @@ -22,9 +24,7 @@ func Test_RequireAbove(t *testing.T) { //nolint:paralleltest r.UnitTest(t, r.TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.RequireAbove(version.Must(version.NewVersion("1.1.0"))), diff --git a/tfversion/require_not_test.go b/tfversion/require_not_test.go index ec23fa6f0..fa05887f5 100644 --- a/tfversion/require_not_test.go +++ b/tfversion/require_not_test.go @@ -11,6 +11,8 @@ import ( r "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/internal/plugintest" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/tfversion" testinginterface "github.com/mitchellh/go-testing-interface" @@ -22,9 +24,7 @@ func Test_RequireNot(t *testing.T) { //nolint:paralleltest r.UnitTest(t, r.TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.RequireNot(version.Must(version.NewVersion("1.1.0"))), diff --git a/tfversion/skip_below_test.go b/tfversion/skip_below_test.go index 202130b45..39ed9411c 100644 --- a/tfversion/skip_below_test.go +++ b/tfversion/skip_below_test.go @@ -10,6 +10,8 @@ import ( "github.com/hashicorp/terraform-plugin-go/tfprotov6" r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/tfversion" ) @@ -44,9 +46,7 @@ func Test_SkipBelow_RunTest(t *testing.T) { //nolint:paralleltest r.UnitTest(t, r.TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipBelow(version.Must(version.NewVersion("1.1.0"))), diff --git a/tfversion/skip_between_test.go b/tfversion/skip_between_test.go index c5dccc333..3d53aa94a 100644 --- a/tfversion/skip_between_test.go +++ b/tfversion/skip_between_test.go @@ -10,6 +10,8 @@ import ( "github.com/hashicorp/terraform-plugin-go/tfprotov6" r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/tfversion" testinginterface "github.com/mitchellh/go-testing-interface" @@ -59,9 +61,7 @@ func Test_SkipBetween_RunTest_AboveMax(t *testing.T) { //nolint:paralleltest r.UnitTest(&testinginterface.RuntimeT{}, r.TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipBetween(version.Must(version.NewVersion("1.2.0")), version.Must(version.NewVersion("1.3.0"))), @@ -80,9 +80,7 @@ func Test_SkipBetween_RunTest_EqToMin(t *testing.T) { //nolint:paralleltest r.UnitTest(&testinginterface.RuntimeT{}, r.TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipBetween(version.Must(version.NewVersion("1.2.0")), version.Must(version.NewVersion("1.3.0"))), diff --git a/tfversion/skip_if_test.go b/tfversion/skip_if_test.go index 55dd9270a..b53bd0d7d 100644 --- a/tfversion/skip_if_test.go +++ b/tfversion/skip_if_test.go @@ -10,6 +10,8 @@ import ( "github.com/hashicorp/terraform-plugin-go/tfprotov6" r "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testprovider" + "github.com/hashicorp/terraform-plugin-testing/internal/testing/testsdk/providerserver" "github.com/hashicorp/terraform-plugin-testing/tfversion" testinginterface "github.com/mitchellh/go-testing-interface" @@ -42,9 +44,7 @@ func Test_SkipIf_RunTest(t *testing.T) { //nolint:paralleltest r.UnitTest(&testinginterface.RuntimeT{}, r.TestCase{ ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ - "test": func() (tfprotov6.ProviderServer, error) { //nolint:unparam // required signature - return nil, nil - }, + "test": providerserver.NewProviderServer(testprovider.Provider{}), }, TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.SkipIf(version.Must(version.NewVersion("1.2.0"))),