2023-07-03 20:21:30 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2022-08-06 14:21:18 +00:00
|
|
|
package resource
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
2022-12-24 16:57:19 +00:00
|
|
|
"regexp"
|
2022-08-06 14:21:18 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2022-12-24 16:57:19 +00:00
|
|
|
var configProviderBlockRegex = regexp.MustCompile(`provider "?[a-zA-Z0-9_-]+"? {`)
|
|
|
|
|
|
|
|
// configHasProviderBlock returns true if the Config has declared a provider
|
|
|
|
// configuration block, e.g. provider "examplecloud" {...}
|
|
|
|
func (s TestStep) configHasProviderBlock(_ context.Context) bool {
|
|
|
|
return configProviderBlockRegex.MatchString(s.Config)
|
|
|
|
}
|
|
|
|
|
|
|
|
// configHasTerraformBlock returns true if the Config has declared a terraform
|
|
|
|
// configuration block, e.g. terraform {...}
|
|
|
|
func (s TestStep) configHasTerraformBlock(_ context.Context) bool {
|
|
|
|
return strings.Contains(s.Config, "terraform {")
|
|
|
|
}
|
|
|
|
|
|
|
|
// mergedConfig prepends any necessary terraform configuration blocks to the
|
|
|
|
// TestStep Config.
|
|
|
|
//
|
|
|
|
// If there are ExternalProviders configurations in either the TestCase or
|
|
|
|
// TestStep, the terraform configuration block should be included with the
|
|
|
|
// step configuration to prevent errors with providers outside the
|
|
|
|
// registry.terraform.io hostname or outside the hashicorp namespace.
|
|
|
|
func (s TestStep) mergedConfig(ctx context.Context, testCase TestCase) string {
|
|
|
|
var config strings.Builder
|
|
|
|
|
|
|
|
// Prevent issues with existing configurations containing the terraform
|
|
|
|
// configuration block.
|
|
|
|
if s.configHasTerraformBlock(ctx) {
|
|
|
|
config.WriteString(s.Config)
|
|
|
|
|
|
|
|
return config.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
if testCase.hasProviders(ctx) {
|
|
|
|
config.WriteString(testCase.providerConfig(ctx, s.configHasProviderBlock(ctx)))
|
|
|
|
} else {
|
|
|
|
config.WriteString(s.providerConfig(ctx, s.configHasProviderBlock(ctx)))
|
|
|
|
}
|
|
|
|
|
|
|
|
config.WriteString(s.Config)
|
|
|
|
|
|
|
|
return config.String()
|
|
|
|
}
|
|
|
|
|
2022-08-06 14:21:18 +00:00
|
|
|
// 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.
|
2022-12-24 16:57:19 +00:00
|
|
|
func (s TestStep) providerConfig(_ context.Context, skipProviderBlock bool) string {
|
2022-08-06 14:21:18 +00:00
|
|
|
var providerBlocks, requiredProviderBlocks strings.Builder
|
|
|
|
|
|
|
|
for name, externalProvider := range s.ExternalProviders {
|
2022-12-24 16:57:19 +00:00
|
|
|
if !skipProviderBlock {
|
|
|
|
providerBlocks.WriteString(fmt.Sprintf("provider %q {}\n", name))
|
|
|
|
}
|
2022-08-06 14:21:18 +00:00
|
|
|
|
|
|
|
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")
|
|
|
|
}
|
|
|
|
|
|
|
|
if requiredProviderBlocks.Len() > 0 {
|
|
|
|
return fmt.Sprintf(`
|
|
|
|
terraform {
|
|
|
|
required_providers {
|
|
|
|
%[1]s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
%[2]s
|
|
|
|
`, strings.TrimSuffix(requiredProviderBlocks.String(), "\n"), providerBlocks.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
return providerBlocks.String()
|
|
|
|
}
|