diff --git a/helper/resource/testing_new.go b/helper/resource/testing_new.go index a2d60e7f4..f7a050175 100644 --- a/helper/resource/testing_new.go +++ b/helper/resource/testing_new.go @@ -93,6 +93,8 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest wd.Close() }() + // Return value from c.ProviderConfig() is assigned to Raw as this was previously being + // passed to wd.SetConfig() when the second argument accept a configuration string. if c.hasProviders(ctx) { config, err := teststep.Configuration( teststep.ConfigurationRequest{ @@ -209,13 +211,21 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest protov6: protov6ProviderFactories(c.ProtoV6ProviderFactories).merge(step.ProtoV6ProviderFactories), } - testStepProviderConfig := step.providerConfig(ctx, cfg.HasProviderBlock(ctx)) + hasProviderBlock, err := cfg.HasProviderBlock(ctx) + if err != nil { + logging.HelperResourceError(ctx, + "TestStep error determining whether configuration contains provider block", + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("TestStep %d/%d error determining whether configuration contains provider block: %s", stepNumber, len(c.Steps), err) + } + + // Return value from c.ProviderConfig() is assigned to Raw as this was previously being + // passed to wd.SetConfig() when the second argument accept a configuration string. config, err := teststep.Configuration( teststep.ConfigurationRequest{ - Directory: step.ConfigDirectory, - Raw: step.Config, - TestStepProviderConfig: testStepProviderConfig, + Raw: step.providerConfig(ctx, hasProviderBlock), }, ) @@ -375,10 +385,20 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest var testCaseProviderConfig string var testStepProviderConfig string + hasProviderBlock, err := cfg.HasProviderBlock(ctx) + + if err != nil { + logging.HelperResourceError(ctx, + "Error determining whether configuration contains provider block", + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("Error determining whether configuration contains provider block: %s", err) + } + if c.hasProviders(ctx) { - testCaseProviderConfig = c.providerConfig(ctx, cfg.HasProviderBlock(ctx)) + testCaseProviderConfig = c.providerConfig(ctx, hasProviderBlock) } else { - testStepProviderConfig = step.providerConfig(ctx, cfg.HasProviderBlock(ctx)) + testStepProviderConfig = step.providerConfig(ctx, hasProviderBlock) } appliedCfg, err = teststep.Configuration( @@ -464,11 +484,21 @@ func testIDRefresh(ctx context.Context, t testing.T, c TestCase, wd *plugintest. t.Fatalf("Error creating provider configuration for import test config: %s", err) } - testCaseProviderConfig := c.providerConfig(ctx, cfg.HasProviderBlock(ctx)) + hasProviderBlock, err := cfg.HasProviderBlock(ctx) + + if err != nil { + logging.HelperResourceError(ctx, + "Error determining whether configuration contains provider block for import test config", + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("Error determining whether configuration contains provider block for import test config: %s", err) + } + // Return value from c.ProviderConfig() is assigned to Raw as this was previously being + // passed to wd.SetConfig() when the second argument accept a configuration string. config, err := teststep.Configuration( teststep.ConfigurationRequest{ - Raw: testCaseProviderConfig, + Raw: c.providerConfig(ctx, hasProviderBlock), }, ) diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index 466ab1103..d1059fbfe 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -35,10 +35,20 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint var testCaseProviderConfig string var testStepProviderConfig string + hasProviderBlock, err := cfg.HasProviderBlock(ctx) + + if err != nil { + logging.HelperResourceError(ctx, + "Error determining whether configuration contains provider block", + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("Error determining whether configuration contains provider block: %s", err) + } + if c.hasProviders(ctx) { - testCaseProviderConfig = c.providerConfig(ctx, cfg.HasProviderBlock(ctx)) + testCaseProviderConfig = c.providerConfig(ctx, hasProviderBlock) } else { - testStepProviderConfig = step.providerConfig(ctx, cfg.HasProviderBlock(ctx)) + testStepProviderConfig = step.providerConfig(ctx, hasProviderBlock) } config, err := teststep.Configuration( diff --git a/internal/plugintest/working_dir.go b/internal/plugintest/working_dir.go index 7d467258e..ea8994231 100644 --- a/internal/plugintest/working_dir.go +++ b/internal/plugintest/working_dir.go @@ -112,7 +112,7 @@ func (wd *WorkingDir) SetConfig(ctx context.Context, cfg teststep.Config) error wd.configFilename = outFilename - if cfg.HasDirectory() { + if cfg.HasDirectory(ctx) { err := cfg.WriteDirectory(ctx, wd.baseDir) if err != nil { diff --git a/internal/teststep/config.go b/internal/teststep/config.go index ea7951230..c6d7e4369 100644 --- a/internal/teststep/config.go +++ b/internal/teststep/config.go @@ -13,12 +13,20 @@ import ( "strings" ) -var configProviderBlockRegex = regexp.MustCompile(`provider "?[a-zA-Z0-9_-]+"? {`) +const ( + testCaseProviderConfigFileName = "test_case_provider_config.tf" + testStepProviderConfigFileName = "test_step_provider_config.tf" +) + +var ( + providerConfigBlockRegex = regexp.MustCompile(`provider "?[a-zA-Z0-9_-]+"? {`) + terraformConfigBlockRegex = regexp.MustCompile(`terraform {`) +) type Config interface { HasConfiguration() bool - HasDirectory() bool - HasProviderBlock(context.Context) bool + HasDirectory(context.Context) bool + HasProviderBlock(context.Context) (bool, error) HasRaw(context.Context) bool Raw(context.Context) string WriteDirectory(context.Context, string) error @@ -83,19 +91,38 @@ func (c configuration) HasConfiguration() bool { return false } -func (c configuration) HasDirectory() bool { +func (c configuration) HasDirectory(_ context.Context) bool { return c.directory != "" } // HasProviderBlock returns true if the Config has declared a provider // configuration block, e.g. provider "examplecloud" {...} -// -// TODO: Need to handle configuration supplied through Directory or File. -func (c configuration) HasProviderBlock(_ context.Context) bool { - return configProviderBlockRegex.MatchString(c.raw) +func (c configuration) HasProviderBlock(ctx context.Context) (bool, error) { + switch { + case c.HasRaw(ctx): + return providerConfigBlockRegex.MatchString(c.raw), nil + case c.HasDirectory(ctx): + pwd, err := os.Getwd() + + if err != nil { + return false, err + } + + configDirectory := filepath.Join(pwd, c.directory) + + contains, err := filesContains(configDirectory, providerConfigBlockRegex) + + if err != nil { + return false, err + } + + return contains, nil + } + + return false, nil } -func (c configuration) HasRaw(ctx context.Context) bool { +func (c configuration) HasRaw(_ context.Context) bool { return c.raw != "" } @@ -113,7 +140,7 @@ func (c configuration) Raw(ctx context.Context) string { // Prevent issues with existing configurations containing the terraform // configuration block. - if strings.Contains(c.raw, "terraform {") { + if terraformConfigBlockRegex.MatchString(c.raw) { return c.raw } @@ -129,10 +156,8 @@ func (c configuration) Raw(ctx context.Context) string { } // WriteDirectory copies the contents of c.directory to dest. -// TODO: Need to handle testCaseProviderConfig and testStepProviderConfig when -// copying files from c.directory to working directory for test func (c configuration) WriteDirectory(ctx context.Context, dest string) error { - // Copy all files from c.dir to dest + // Copy all files from c.directory to dest pwd, err := os.Getwd() if err != nil { @@ -148,74 +173,54 @@ func (c configuration) WriteDirectory(ctx context.Context, dest string) error { } // Determine whether any of the files in configDirectory contain terraform block. - containsTerraformConfig, err := c.filesContains(configDirectory, `terraform {`) + containsTerraformConfig, err := filesContains(configDirectory, terraformConfigBlockRegex) if err != nil { return err } - // Write contents of testCaseProviderConfig or testStepProviderConfig t dest. - // TODO: Verify whether there are any naming collisions between the files in - // c.directory and the files that are written below. + // Write contents of testCaseProviderConfig or testStepProviderConfig to dest. if !containsTerraformConfig { if c.testCaseProviderConfig != "" { - path := filepath.Join(dest, "testCaseProviderConfig.tf") + path := filepath.Join(dest, testCaseProviderConfigFileName) - err := os.WriteFile(path, []byte(c.testCaseProviderConfig), 0700) + configFileExists, err := fileExists(configDirectory, testCaseProviderConfigFileName) if err != nil { return err } - } else { - path := filepath.Join(dest, "testStepProviderConfig.tf") - err := os.WriteFile(path, []byte(c.testStepProviderConfig), 0700) + if configFileExists { + return fmt.Errorf("%s already exists in %s, ", testCaseProviderConfigFileName, configDirectory) + } + + err = os.WriteFile(path, []byte(c.testCaseProviderConfig), 0700) if err != nil { return err } - } - } - - return nil -} - -func (c configuration) filesContains(dir, find string) (bool, error) { - dirEntries, err := os.ReadDir(dir) - - if err != nil { - return false, err - } + } else { + path := filepath.Join(dest, testStepProviderConfigFileName) - for _, dirEntry := range dirEntries { - if dirEntry.IsDir() { - continue - } + configFileExists, err := fileExists(configDirectory, testStepProviderConfigFileName) - path := filepath.Join(dir, dirEntry.Name()) + if err != nil { + return err + } - contains, err := c.fileContains(path, find) + if configFileExists { + return fmt.Errorf("%s already exists in %s, ", testStepProviderConfigFileName, configDirectory) + } - if err != nil { - return false, err - } + err = os.WriteFile(path, []byte(c.testStepProviderConfig), 0700) - if contains { - return true, nil + if err != nil { + return err + } } } - return false, nil -} - -func (c configuration) fileContains(path, find string) (bool, error) { - f, err := os.ReadFile(path) - - if err != nil { - return false, err - } - - return strings.Contains(string(f), find), nil + return nil } func copyFiles(path string, dstPath string) error { @@ -276,3 +281,61 @@ func copyFile(path string, dstPath string) error { return nil } + +func filesContains(dir string, find *regexp.Regexp) (bool, error) { + dirEntries, err := os.ReadDir(dir) + + if err != nil { + return false, err + } + + for _, dirEntry := range dirEntries { + if dirEntry.IsDir() { + continue + } + + path := filepath.Join(dir, dirEntry.Name()) + + contains, err := fileContains(path, find) + + if err != nil { + return false, err + } + + if contains { + return true, nil + } + } + + return false, nil +} + +func fileContains(path string, find *regexp.Regexp) (bool, error) { + f, err := os.ReadFile(path) + + if err != nil { + return false, err + } + + return find.MatchString(string(f)), nil +} + +func fileExists(dir, fileName string) (bool, error) { + infos, err := os.ReadDir(dir) + + if err != nil { + return false, err + } + + for _, info := range infos { + if info.IsDir() { + continue + } else { + if fileName == info.Name() { + return true, nil + } + } + } + + return false, nil +} diff --git a/internal/teststep/config_test.go b/internal/teststep/config_test.go index e88ca8940..f4a455ec2 100644 --- a/internal/teststep/config_test.go +++ b/internal/teststep/config_test.go @@ -110,7 +110,11 @@ resource "test_test" "test" {} t.Run(name, func(t *testing.T) { t.Parallel() - got := testCase.config.HasProviderBlock(context.Background()) + got, err := testCase.config.HasProviderBlock(context.Background()) + + if err != nil { + t.Errorf("unexpected error: %s", err) + } if testCase.expected != got { t.Errorf("expected %t, got %t", testCase.expected, got)