diff --git a/modules/terraform/format.go b/modules/terraform/format.go index f50072d7c..7b6293a58 100644 --- a/modules/terraform/format.go +++ b/modules/terraform/format.go @@ -56,8 +56,13 @@ func FormatArgs(options *Options, args ...string) []string { terraformArgs = append(terraformArgs, args...) if includeVars { - terraformArgs = append(terraformArgs, FormatTerraformVarsAsArgs(options.Vars)...) - terraformArgs = append(terraformArgs, FormatTerraformArgs("-var-file", options.VarFiles)...) + if options.SetVarsAfterVarFiles { + terraformArgs = append(terraformArgs, FormatTerraformArgs("-var-file", options.VarFiles)...) + terraformArgs = append(terraformArgs, FormatTerraformVarsAsArgs(options.Vars)...) + } else { + terraformArgs = append(terraformArgs, FormatTerraformVarsAsArgs(options.Vars)...) + terraformArgs = append(terraformArgs, FormatTerraformArgs("-var-file", options.VarFiles)...) + } } terraformArgs = append(terraformArgs, FormatTerraformArgs("-target", options.Targets)...) diff --git a/modules/terraform/format_test.go b/modules/terraform/format_test.go index 3a2a325cb..99409053d 100644 --- a/modules/terraform/format_test.go +++ b/modules/terraform/format_test.go @@ -278,3 +278,37 @@ func TestFormatArgsAppliesLockCorrectly(t *testing.T) { assert.Equal(t, testCase.expected, FormatArgs(&Options{}, testCase.command...)) } } + +func TestFormatSetVarsAfterVarFilesFormatsCorrectly(t *testing.T) { + t.Parallel() + + testCases := []struct { + command []string + vars map[string]interface{} + varFiles []string + setVarsAfterVarFiles bool + expected []string + }{ + {[]string{"plan"}, map[string]interface{}{"foo": "bar"}, []string{"test.tfvars"}, true, []string{"plan", "-var-file", "test.tfvars", "-var", "foo=bar", "-lock=false"}}, + {[]string{"plan"}, map[string]interface{}{"foo": "bar", "hello": "world"}, []string{"test.tfvars"}, true, []string{"plan", "-var-file", "test.tfvars", "-var", "foo=bar", "-var", "hello=world", "-lock=false"}}, + {[]string{"plan"}, map[string]interface{}{"foo": "bar", "hello": "world"}, []string{"test.tfvars"}, false, []string{"plan", "-var", "foo=bar", "-var", "hello=world", "-var-file", "test.tfvars", "-lock=false"}}, + {[]string{"plan"}, map[string]interface{}{"foo": "bar"}, []string{"test.tfvars"}, false, []string{"plan", "-var", "foo=bar", "-var-file", "test.tfvars", "-lock=false"}}, + } + + for _, testCase := range testCases { + result := FormatArgs(&Options{SetVarsAfterVarFiles: testCase.setVarsAfterVarFiles, Vars: testCase.vars, VarFiles: testCase.varFiles}, testCase.command...) + + // Make sure that -var and -var-file options are in the expected order relative to each other + // Note that the order of the different -var and -var-file options may change + // See this comment for more info: https://github.com/gruntwork-io/terratest/blob/6fb86056797e3e62ebdd9011ba26605e0976a6f8/modules/terraform/format_test.go#L123-L142 + for idx, arg := range result { + if arg == "-var-file" || arg == "-var" { + assert.Equal(t, testCase.expected[idx], arg) + } + } + + // Make sure that the order of other arguments hasn't been incorrectly modified + assert.Equal(t, testCase.expected[0], result[0]) + assert.Equal(t, testCase.expected[len(testCase.expected)-1], result[len(result)-1]) + } +} diff --git a/modules/terraform/options.go b/modules/terraform/options.go index 7ac78fdb6..9495a6c09 100644 --- a/modules/terraform/options.go +++ b/modules/terraform/options.go @@ -70,6 +70,7 @@ type Options struct { Parallelism int // Set the parallelism setting for Terraform PlanFilePath string // The path to output a plan file to (for the plan command) or read one from (for the apply command) PluginDir string // The path of downloaded plugins to pass to the terraform init command (-plugin-dir) + SetVarsAfterVarFiles bool // Pass -var options after -var-file options to Terraform commands } // Clone makes a deep copy of most fields on the Options object and returns it.