Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce --terragrunt-strict flag for validate-inputs #1757

Merged
merged 14 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cli/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ func parseTerragruntOptionsFromArgs(terragruntVersion string, args []string, wri
return nil, err
}

validateStrictMode := parseBooleanArg(args, OPT_TERRAGRUNT_STRICT_VALIDATE, false)

opts, err := options.NewTerragruntOptions(filepath.ToSlash(terragruntConfigPath))
if err != nil {
return nil, err
Expand Down Expand Up @@ -177,6 +179,7 @@ func parseTerragruntOptionsFromArgs(terragruntVersion string, args []string, wri
opts.WorkingDir = filepath.ToSlash(workingDir)
opts.DownloadDir = filepath.ToSlash(downloadDir)
opts.LogLevel = loggingLevel
opts.ValidateStrict = validateStrictMode
opts.Logger = util.CreateLogEntry("", loggingLevel)
opts.Logger.Logger.SetOutput(errWriter)
opts.RunTerragrunt = RunTerragrunt
Expand Down
3 changes: 3 additions & 0 deletions cli/cli_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ const OPT_TERRAGRUNT_HCLFMT_FILE = "terragrunt-hclfmt-file"
const OPT_TERRAGRUNT_DEBUG = "terragrunt-debug"
const OPT_TERRAGRUNT_OVERRIDE_ATTR = "terragrunt-override-attr"
const OPT_TERRAGRUNT_LOGLEVEL = "terragrunt-log-level"
const OPT_TERRAGRUNT_STRICT_VALIDATE = "terragrunt-strict-validate"

var ALL_TERRAGRUNT_BOOLEAN_OPTS = []string{
OPT_NON_INTERACTIVE,
Expand Down Expand Up @@ -79,6 +80,7 @@ var ALL_TERRAGRUNT_STRING_OPTS = []string{
OPT_TERRAGRUNT_HCLFMT_FILE,
OPT_TERRAGRUNT_OVERRIDE_ATTR,
OPT_TERRAGRUNT_LOGLEVEL,
OPT_TERRAGRUNT_STRICT_VALIDATE,
}

const CMD_INIT = "init"
Expand Down Expand Up @@ -235,6 +237,7 @@ GLOBAL OPTIONS:
terragrunt-override-attr A key=value attribute to override in a provider block as part of the aws-provider-patch command. May be specified multiple times.
terragrunt-debug Write terragrunt-debug.tfvars to working folder to help root-cause issues.
terragrunt-log-level Sets the logging level for Terragrunt. Supported levels: panic, fatal, error, warn (default), info, debug, trace.
terragrunt-strict-validate Sets strict mode for the validate-inputs command. By default, strict mode is off. When this flag is passed, strict mode is turned on. When strict mode is turned off, the validate-inputs command will only return an error if required inputs are missing from all input sources (env vars, var files, etc). When strict mode is turned on, an error will be returned if required inputs are missing OR if unused variables are passed to Terragrunt.

VERSION:
{{.Version}}{{if len .Authors}}
Expand Down
15 changes: 11 additions & 4 deletions cli/validate_inputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ func validateTerragruntInputs(terragruntOptions *options.TerragruntOptions, work
terragruntOptions.Logger.Warn("")
} else {
terragruntOptions.Logger.Info("All variables passed in by terragrunt are in use.")
terragruntOptions.Logger.Debug(fmt.Sprintf("Strict mode enabled: %t", terragruntOptions.ValidateStrict))
}

if len(missingVars) > 0 {
Expand All @@ -63,13 +64,19 @@ func validateTerragruntInputs(terragruntOptions *options.TerragruntOptions, work
}
terragruntOptions.Logger.Error("")
} else {
terragruntOptions.Logger.Info("All required inputs are passed in by terragrunt.")
terragruntOptions.Logger.Info("All required inputs are passed in by terragrunt")
terragruntOptions.Logger.Debug(fmt.Sprintf("Strict mode enabled: %t", terragruntOptions.ValidateStrict))
}

// Return an error when there are misaligned inputs.
if len(unusedVars) > 0 || len(missingVars) > 0 {
return fmt.Errorf("Terragrunt configuration has misaligned inputs")
// Return an error when there are misaligned inputs. Terragrunt strict mode defaults to false. When it is false,
// an error will only be returned if required inputs are missing. When strict mode is true, an error will be
// returned if required inputs are missing OR if any unused variables are passed
if len(missingVars) > 0 || len(unusedVars) > 0 && terragruntOptions.ValidateStrict {
return fmt.Errorf(fmt.Sprintf("Terragrunt configuration has misaligned inputs. Strict mode enabled: %t.", terragruntOptions.ValidateStrict))
} else if len(unusedVars) > 0 {
terragruntOptions.Logger.Warn("Terragrunt configuration has misaligned inputs, but running in relaxed mode so ignoring.")
}

return nil
}

Expand Down
6 changes: 6 additions & 0 deletions docs/_docs/04_reference/cli-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ prefix `--terragrunt-` (e.g., `--terragrunt-config`). The currently available op
- [terragrunt-exclude-dir](#terragrunt-exclude-dir)
- [terragrunt-include-dir](#terragrunt-include-dir)
- [terragrunt-strict-include](#terragrunt-strict-include)
- [terragrunt-strict-validate](#terragrunt-strict-validate)
- [terragrunt-ignore-dependency-order](#terragrunt-ignore-dependency-order)
- [terragrunt-ignore-external-dependencies](#terragrunt-ignore-external-dependencies)
- [terragrunt-include-external-dependencies](#terragrunt-include-external-dependencies)
Expand Down Expand Up @@ -610,6 +611,11 @@ will be included. All dependencies of the included directories will be excluded
directories. If no [--terragrunt-include-dir](#terragrunt-include-dir) flags are included, terragrunt will not include
any modules during the execution of the commands.

### terragrunt-strict-validate

**CLI Arg**: `--terragrunt-strict-validate`

When passed in, and running `terragrunt validate-inputs`, enables strict mode for the `validate-inputs` command. When strict mode is enabled, an error will be returned if any variables required by the underlying Terraform configuration are not passed in, OR if any unused variables are passed in. By default, `terragrunt validate-inputs` runs in relaxed mode. In relaxed mode, an error is only returned when a variable required by the underlying Terraform configuration is not passed in.

### terragrunt-ignore-dependency-order

Expand Down
4 changes: 4 additions & 0 deletions options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ type TerragruntOptions struct {
// Log level
LogLevel logrus.Level

// ValidateStrict mode for the validate-inputs command
ValidateStrict bool

// Environment variables at runtime
Env map[string]string

Expand Down Expand Up @@ -197,6 +200,7 @@ func NewTerragruntOptions(terragruntConfigPath string) (*TerragruntOptions, erro
WorkingDir: workingDir,
Logger: logger,
LogLevel: DEFAULT_LOG_LEVEL,
ValidateStrict: false,
Env: map[string]string{},
Source: "",
SourceMap: map[string]string{},
Expand Down
42 changes: 41 additions & 1 deletion test/integration_debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ func TestTerragruntValidateInputs(t *testing.T) {
t.Parallel()

nameDashSplit := strings.Split(name, "-")
runTerragruntValidateInputs(t, module, nil, nameDashSplit[0] == "success")
runTerragruntValidateInputs(t, module, []string{"--terragrunt-strict-validate"}, nameDashSplit[0] == "success")
})
}
}
Expand All @@ -103,6 +103,46 @@ func TestTerragruntValidateInputsWithCLIVarFile(t *testing.T) {
runTerragruntValidateInputs(t, moduleDir, args, true)
}

func TestTerragruntValidateInputsWithStrictMode(t *testing.T) {
t.Parallel()

moduleDir := filepath.Join("fixture-validate-inputs", "success-inputs-only")
args := []string{"--terragrunt-strict-validate"}
runTerragruntValidateInputs(t, moduleDir, args, true)
}

func TestTerragruntValidateInputsWithStrictModeDisabledAndUnusedVar(t *testing.T) {
t.Parallel()

moduleDir := filepath.Join("fixture-validate-inputs", "success-inputs-only")
args := []string{"-var=testvariable=testvalue"}
runTerragruntValidateInputs(t, moduleDir, args, true)
}

func TestTerragruntValidateInputsWithStrictModeEnabledAndUnusedVar(t *testing.T) {
t.Parallel()

moduleDir := filepath.Join("fixture-validate-inputs", "success-inputs-only")
args := []string{"-var=testvariable=testvalue", "--terragrunt-strict-validate"}
runTerragruntValidateInputs(t, moduleDir, args, false)
}

func TestTerragruntValidateInputsWithStrictModeEnabledAndUnusedInputs(t *testing.T) {
t.Parallel()

moduleDir := filepath.Join("fixture-validate-inputs", "fail-unused-inputs")
args := []string{"--terragrunt-strict-validate"}
runTerragruntValidateInputs(t, moduleDir, args, false)
}

func TestTerragruntValidateInputsWithStrictModeDisabledAndUnusedInputs(t *testing.T) {
t.Parallel()

moduleDir := filepath.Join("fixture-validate-inputs", "fail-unused-inputs")
args := []string{}
runTerragruntValidateInputs(t, moduleDir, args, true)
}

func runTerragruntValidateInputs(t *testing.T, moduleDir string, extraArgs []string, isSuccessTest bool) {
maybeNested := filepath.Join(moduleDir, "module")
if util.FileExists(maybeNested) {
Expand Down
3 changes: 2 additions & 1 deletion test/integration_serial_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ func TestTerragruntValidateInputsWithUnusedEnvVar(t *testing.T) {
defer os.Unsetenv("TF_VAR_unused")

moduleDir := filepath.Join("fixture-validate-inputs", "success-inputs-only")
runTerragruntValidateInputs(t, moduleDir, nil, false)
args := []string{"--terragrunt-strict-validate"}
runTerragruntValidateInputs(t, moduleDir, args, false)
}

func TestTerragruntSourceMapEnvArg(t *testing.T) {
Expand Down