Skip to content

Commit

Permalink
Extending implementation of HasProviderBlock() to include detection o…
Browse files Browse the repository at this point in the history
…f provider blocks in configuration files within the configuration directory (#150)
  • Loading branch information
bendbennett committed Jul 19, 2023
1 parent 516e68b commit 6a8f3da
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 68 deletions.
46 changes: 38 additions & 8 deletions helper/resource/testing_new.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down Expand Up @@ -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),
},
)

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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),
},
)

Expand Down
14 changes: 12 additions & 2 deletions helper/resource/testing_new_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion internal/plugintest/working_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
175 changes: 119 additions & 56 deletions internal/teststep/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 != ""
}

Expand All @@ -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
}

Expand All @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}
6 changes: 5 additions & 1 deletion internal/teststep/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 6a8f3da

Please sign in to comment.