diff --git a/util/terraform.go b/util/terraform.go index 23f5d41253..60d6736803 100644 --- a/util/terraform.go +++ b/util/terraform.go @@ -3,15 +3,12 @@ package util import ( "fmt" "os" - "path" - "regexp" "strings" "sync" "github.com/coveooss/gotemplate/v3/collections" "github.com/coveooss/gotemplate/v3/json" "github.com/coveooss/gotemplate/v3/template" - "github.com/coveooss/gotemplate/v3/utils" "github.com/coveooss/gotemplate/v3/yaml" "github.com/coveooss/multilogger" "github.com/coveooss/multilogger/errors" @@ -29,10 +26,7 @@ type ( } ) -var ( - reTfVariables = regexp.MustCompile(`(?ms)^variable\s+".*?"\s+{(\s*\n.*?^}|\s*}$)`) - cacheDefault sync.Map -) +var cacheDefault sync.Map // LoadDefaultValues returns a map of the variables defined in the tfvars file func LoadDefaultValues(folder string, logger *multilogger.Logger, keepInCache bool) (importedVariables map[string]interface{}, allVariables map[string]*tfconfig.Variable, err error) { @@ -51,7 +45,7 @@ func LoadDefaultValues(folder string, logger *multilogger.Logger, keepInCache bo return cached.values, cached.all, nil } - return loadDefaultValues(folder, true, logger) + return loadDefaultValues(folder, logger) } // LoadVariablesFromHcl parses HCL content to get a map of the attributes @@ -162,9 +156,9 @@ func LoadVariablesFromSource(content, fileName, cwd string, applyTemplate bool, return } -func loadDefaultValues(folder string, retry bool, logger *multilogger.Logger) (map[string]interface{}, map[string]*tfconfig.Variable, error) { +func loadDefaultValues(folder string, logger *multilogger.Logger) (map[string]interface{}, map[string]*tfconfig.Variable, error) { module, diags := tfconfig.LoadModule(folder) - if diags.HasErrors() { + if diags.HasErrors() && logger != nil { var err errors.Array for _, diag := range diags { if diag.Pos != nil && diag.Pos.Filename != "" { @@ -174,21 +168,8 @@ func loadDefaultValues(folder string, retry bool, logger *multilogger.Logger) (m err = append(err, fmt.Errorf("(%c) %s, %s", diag.Severity, diag.Summary, diag.Detail)) } } - if !retry { - return nil, nil, err - } - // If we get an error while loading variables, we try to isolate variables definition in a temporary folder. - if logger != nil { - logger.Debugf("First try with terraform native LoadConfigDir failed\n%v", color.HiBlackString(err.Error())) - logger.Debug("Retrying with a temporary folder containing only variables definitions") - } - tmpDir, errTmpDir := createTerraformVariablesTemporaryFolder(folder) - if tmpDir == "" || errTmpDir != nil { - return nil, nil, append(err, errTmpDir) - } - defer func() { os.RemoveAll(tmpDir) }() - return loadDefaultValues(tmpDir, false, logger) + logger.Debugf("Ignored error while trying to load the default variables:\n%v", color.HiBlackString(err.Error())) } variablesMap := map[string]interface{}{} @@ -203,77 +184,3 @@ func loadDefaultValues(folder string, retry bool, logger *multilogger.Logger) (m } return variablesMap, module.Variables, nil } - -func isOverride(filename string) bool { - return path.Base(filename) == "override.tf" || - path.Base(filename) == "override.tf.json" || - strings.HasSuffix(filename, "_override.tf") || - strings.HasSuffix(filename, "_override.tf.json") -} - -// Create a temporary folder containing only the terraform code used to declare and initialize variables. -// This allows us to load the default variable value to make them available to gotemplate code before we -// apply gotemplate on terraform file. If we don't, any terraform code that is not considered as valid -// code will cause an error and make LoadDefaultValues fail. -func createTerraformVariablesTemporaryFolder(folder string) (tmpDir string, err error) { - var files []string - - if _, err = os.Stat(folder); err != nil { - return - } - if files, err = utils.FindFiles(folder, false, false, "*.tf", "*.tf.json"); err != nil { - return - } - - // The variables are spitted up into 4 different files depending if they are declared - // in a .tf file or a .tf.json file and if they are declared in an override file or not. - generated := make(map[string]interface{}) - for _, filename := range files { - name, ext := "regular", path.Ext(filename) - if isOverride(filename) { - name = "override" - } - - var content []byte - if content, err = os.ReadFile(filename); err != nil { - return - } - - if ext == ".tf" { - if found := reTfVariables.FindAllString(string(content), -1); len(found) > 0 { - currentValue, _ := generated[name+ext].(string) - generated[name+ext] = currentValue + fmt.Sprintf("// %s\n%s\n", filename, strings.Join(found, "\n\n")) - } - } else { - ext = ".tf.json" - var jsonContent json.Dictionary - if err = json.Unmarshal(content, &jsonContent); err == nil { - variables := jsonContent.Clone("variable") - if variables.Len() > 0 { - currentValue, _ := generated[name+ext].(json.Dictionary) - generated[name+ext] = variables.Merge(currentValue) - } - } - } - } - - if len(generated) > 0 { - // We write the resulting files - if tmpDir, err = os.MkdirTemp("", "load_defaults"); err != nil { - return - } - for filename, value := range generated { - var content []byte - switch value := value.(type) { - case string: - content = []byte(value) - case json.Dictionary: - content = []byte(value.PrettyPrint()) - } - if err = os.WriteFile(path.Join(tmpDir, filename), content, 0644); err != nil { - return - } - } - } - return -} diff --git a/util/terraform_test.go b/util/terraform_test.go index 6cac805e3e..7cc7a7a0d3 100644 --- a/util/terraform_test.go +++ b/util/terraform_test.go @@ -17,7 +17,8 @@ func TestLoadDefaultValues(t *testing.T) { wantResult map[string]interface{} err string }{ - {"All Types", + { + "All Types", testFixtureDefaultValues, map[string]interface{}{ "a": "A (a.tf)", @@ -34,7 +35,6 @@ func TestLoadDefaultValues(t *testing.T) { }, "", }, - {"Invalid Folder", "Invalid", nil, "Module directory Invalid does not exist or cannot be read"}, } for _, tt := range testCases { t.Run(tt.name, func(t *testing.T) {