Skip to content

Commit

Permalink
Option for less verbose output (#1510)
Browse files Browse the repository at this point in the history
* Option for less verbose output

This moves majority of Terragrunt's output to DEBUG level, and sets
default output mode to ERROR. The idea is that in default run user should
see much less output.

Closes: #432

* Updated after review

Apart from small fixes, this:
- adds deprecation check for command line arguments, and gives a
  warning if `--terragrunt-debug` is used;
- imports `logrus` under its own name to avoid confusion;

Related: #432

* Updates after review | 2

Main change - global LogEntry object introduced in `util/logger.go`. It
helps us log properly when we didn't yet parse command line arguments

* Fix tests for `cli/cli_app.go`

P.S. Tests rock!

* Rework global logger

Global logger should be a fallback option, rather a way to go. So
instead of using the same everywhere, we use global if no other logger
is available (for example, if we have not yet parsed arguments).

This change also addresses other PR review comments, like:
- wrong documentation;
- using `logrus.WarnLevel.String()` instead of hardcoded strings;
- updated `isDeprecatedOption()`, with a more clear usage;

* Fix typo in docs section

* Apply `go fmt` properly

* Apply `go fmt` properly | 2

* Fix `TestParseTerragruntOptionsFromArgs` test

* Terragrunt should output all log to stderr

* Set stderr as default output

* Update TestApplySkipTrue()

Add `--terragrunt-log-level info`, so that we could test it.

* Fix tests

This fixes tests that rely on double output of `run_shell`, as well as
brings back `--terragrunt-debug`, but in slightly different form: to
only generate `terragrunt-debug.tfvars.json`

* Remove `--terragrunt-debug` from excluded and fix `\n`

Terragrunt integration tests depend on newlines, and to ensure that
logrus can properly print newlines with `\n` `DisableQuote: true` is
needed [1]. In particular, this fixes
`TestIncludeDirsDependencyConsistencyRegression` and
`TestIncludeDirsStrict`.

[1] - sirupsen/logrus#608

* Bring `--terragrunt-debug` tests back
  • Loading branch information
amnk authored Feb 2, 2021
1 parent af5d6eb commit a7c0d43
Show file tree
Hide file tree
Showing 31 changed files with 281 additions and 200 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ vendor
.terragrunt-cache
.bundle
.ruby-version
.terraform.lock.hcl
.terraform.lock.hcl
terragrunt
2 changes: 1 addition & 1 deletion aws_helper/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func AssumeRoleAndUpdateEnvIfNecessary(terragruntOptions *options.TerragruntOpti
return nil
}

terragruntOptions.Logger.Printf("Assuming IAM role %s", terragruntOptions.IamRole)
terragruntOptions.Logger.Debugf("Assuming IAM role %s", terragruntOptions.IamRole)
creds, err := AssumeIamRole(terragruntOptions.IamRole)
if err != nil {
return err
Expand Down
51 changes: 47 additions & 4 deletions cli/args.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/gruntwork-io/terragrunt/options"
"github.com/gruntwork-io/terragrunt/util"
"github.com/hashicorp/go-version"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -121,13 +122,28 @@ func parseTerragruntOptionsFromArgs(terragruntVersion string, args []string, wri

strictInclude := parseBooleanArg(args, OPT_TERRAGRUNT_STRICT_INCLUDE, false)

debug := parseBooleanArg(args, OPT_TERRAGRUNT_DEBUG, false)
// Those correspond to logrus levels
logLevel, err := parseStringArg(args, OPT_TERRAGRUNT_LOGLEVEL, logrus.WarnLevel.String())
if err != nil {
return nil, err
}

loggingLevel, err := logrus.ParseLevel(logLevel)
if err != nil {
util.GlobalFallbackLogEntry.Errorf(err.Error())
return nil, err
}

opts, err := options.NewTerragruntOptions(filepath.ToSlash(terragruntConfigPath))
if err != nil {
return nil, err
}

debug := parseBooleanArg(args, OPT_TERRAGRUNT_DEBUG, false)
if debug {
opts.Debug = true
}

envValue, envProvided := os.LookupEnv("TERRAGRUNT_PARALLELISM")
parallelism, err := parseIntArg(args, OPT_TERRAGRUNT_PARALLELISM, envValue, envProvided, options.DEFAULT_PARALLELISM)
if err != nil {
Expand All @@ -143,7 +159,9 @@ func parseTerragruntOptionsFromArgs(terragruntVersion string, args []string, wri
opts.TerraformCommand = util.FirstArg(opts.TerraformCliArgs)
opts.WorkingDir = filepath.ToSlash(workingDir)
opts.DownloadDir = filepath.ToSlash(downloadDir)
opts.Logger = util.CreateLoggerWithWriter(errWriter, "")
opts.LogLevel = loggingLevel
opts.Logger = util.CreateLogEntry("", loggingLevel)
opts.Logger.Logger.SetOutput(errWriter)
opts.RunTerragrunt = RunTerragrunt
opts.Source = terraformSource
opts.SourceUpdate = sourceUpdate
Expand All @@ -169,7 +187,6 @@ func parseTerragruntOptionsFromArgs(terragruntVersion string, args []string, wri
opts.Parallelism = parallelism
opts.Check = parseBooleanArg(args, OPT_TERRAGRUNT_CHECK, os.Getenv("TERRAGRUNT_CHECK") == "true")
opts.HclFile = filepath.ToSlash(terragruntHclFilePath)
opts.Debug = debug
opts.AwsProviderPatchOverrides = awsProviderPatchOverrides

return opts, nil
Expand Down Expand Up @@ -217,7 +234,7 @@ func filterTerraformExtraArgs(terragruntOptions *options.TerragruntOptions, terr
if util.FileExists(file) {
out = append(out, fmt.Sprintf("-var-file=%s", file))
} else {
terragruntOptions.Logger.Printf("Skipping var-file %s as it does not exist", file)
terragruntOptions.Logger.Debugf("Skipping var-file %s as it does not exist", file)
}
}
}
Expand Down Expand Up @@ -290,11 +307,25 @@ func filterTerragruntArgs(args []string) []string {
return out
}

// isDeprecatedOption checks if provided option is deprecated, and returns its substitution with the check
// if option is not deprecated - we are returning same value
func isDeprecatedOption(optionName string) (string, bool) {
newOption, deprecated := DEPRECATED_ARGUMENTS[optionName]
if deprecated {
return newOption, true
}
return optionName, false
}

// Find a boolean argument (e.g. --foo) of the given name in the given list of arguments. If it's present, return true.
// If it isn't, return defaultValue.
func parseBooleanArg(args []string, argName string, defaultValue bool) bool {
for _, arg := range args {
if arg == fmt.Sprintf("--%s", argName) {
newOption, deprecated := isDeprecatedOption(argName)
if deprecated {
util.GlobalFallbackLogEntry.Warnf("Command line option %s is deprecated, please consider using %s", argName, newOption)
}
return true
}
}
Expand All @@ -306,6 +337,10 @@ func parseBooleanArg(args []string, argName string, defaultValue bool) bool {
func parseStringArg(args []string, argName string, defaultValue string) (string, error) {
for i, arg := range args {
if arg == fmt.Sprintf("--%s", argName) {
newOption, deprecated := isDeprecatedOption(argName)
if deprecated {
util.GlobalFallbackLogEntry.Warnf("Command line option %s is deprecated, please consider using %s", argName, newOption)
}
if (i + 1) < len(args) {
return args[i+1], nil
} else {
Expand All @@ -321,6 +356,10 @@ func parseStringArg(args []string, argName string, defaultValue string) (string,
func parseIntArg(args []string, argName string, envValue string, envProvided bool, defaultValue int) (int, error) {
for i, arg := range args {
if arg == fmt.Sprintf("--%s", argName) {
newOption, deprecated := isDeprecatedOption(argName)
if deprecated {
util.GlobalFallbackLogEntry.Warnf("Command line option %s is deprecated, please consider using %s", argName, newOption)
}
if (i + 1) < len(args) {
return strconv.Atoi(args[i+1])
} else {
Expand All @@ -342,6 +381,10 @@ func parseMultiStringArg(args []string, argName string, defaultValue []string) (

for i, arg := range args {
if arg == fmt.Sprintf("--%s", argName) {
newOption, deprecated := isDeprecatedOption(argName)
if deprecated {
util.GlobalFallbackLogEntry.Warnf("Command line option %s is deprecated, please consider using %s", argName, newOption)
}
if (i + 1) < len(args) {
stringArgs = append(stringArgs, args[i+1])
} else {
Expand Down
52 changes: 30 additions & 22 deletions cli/args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ import (
"github.com/gruntwork-io/terragrunt/errors"
"github.com/gruntwork-io/terragrunt/options"
"github.com/gruntwork-io/terragrunt/util"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const defaultLogLevel = options.DEFAULT_LOG_LEVEL

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

Expand All @@ -35,55 +38,55 @@ func TestParseTerragruntOptionsFromArgs(t *testing.T) {
}{
{
[]string{},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, defaultLogLevel, false),
nil,
},

{
[]string{"foo", "bar"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{"foo", "bar"}, false, "", false, false, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{"foo", "bar"}, false, "", false, false, defaultLogLevel, false),
nil,
},

{
[]string{"--foo", "--bar"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{"--foo", "--bar"}, false, "", false, false, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{"--foo", "--bar"}, false, "", false, false, defaultLogLevel, false),
nil,
},

{
[]string{"--foo", "apply", "--bar"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{"--foo", "apply", "--bar"}, false, "", false, false, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{"--foo", "apply", "--bar"}, false, "", false, false, defaultLogLevel, false),
nil,
},

{
[]string{"--terragrunt-non-interactive"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, true, "", false, false, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, true, "", false, false, defaultLogLevel, false),
nil,
},

{
[]string{"--terragrunt-include-external-dependencies"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, true, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, true, defaultLogLevel, false),
nil,
},

{
[]string{"--terragrunt-config", fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath)},
mockOptions(t, fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, false),
mockOptions(t, fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, defaultLogLevel, false),
nil,
},

{
[]string{"--terragrunt-working-dir", "/some/path"},
mockOptions(t, util.JoinPath("/some/path", config.DefaultTerragruntConfigPath), "/some/path", []string{}, false, "", false, false, false),
mockOptions(t, util.JoinPath("/some/path", config.DefaultTerragruntConfigPath), "/some/path", []string{}, false, "", false, false, defaultLogLevel, false),
nil,
},

{
[]string{"--terragrunt-source", "/some/path"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "/some/path", false, false, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "/some/path", false, false, defaultLogLevel, false),
nil,
},

Expand All @@ -95,13 +98,13 @@ func TestParseTerragruntOptionsFromArgs(t *testing.T) {

{
[]string{"--terragrunt-ignore-dependency-errors"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", true, false, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", true, false, defaultLogLevel, false),
nil,
},

{
[]string{"--terragrunt-ignore-external-dependencies"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, false),
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, defaultLogLevel, false),
nil,
},

Expand All @@ -113,23 +116,22 @@ func TestParseTerragruntOptionsFromArgs(t *testing.T) {

{
[]string{"--terragrunt-config", fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath), "--terragrunt-non-interactive"},
mockOptions(t, fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath), workingDir, []string{}, true, "", false, false, false),
mockOptions(t, fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath), workingDir, []string{}, true, "", false, false, defaultLogLevel, false),
nil,
},

{
[]string{"--foo", "--terragrunt-config", fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath), "bar", "--terragrunt-non-interactive", "--baz", "--terragrunt-working-dir", "/some/path", "--terragrunt-source", "github.com/foo/bar//baz?ref=1.0.3"},
mockOptions(t, fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath), "/some/path", []string{"--foo", "bar", "--baz"}, true, "github.com/foo/bar//baz?ref=1.0.3", false, false, false),
mockOptions(t, fmt.Sprintf("/some/path/%s", config.DefaultTerragruntConfigPath), "/some/path", []string{"--foo", "bar", "--baz"}, true, "github.com/foo/bar//baz?ref=1.0.3", false, false, defaultLogLevel, false),
nil,
},

// Adding the --terragrunt-debug flag should result in an Options with Debug set to true
// Adding the --terragrunt-log-level flag should result in DebugLevel configured
{
[]string{"--terragrunt-debug"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, true),
[]string{"--terragrunt-log-level", "debug"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, logrus.DebugLevel, false),
nil,
},

{
[]string{"--terragrunt-config"},
nil,
Expand All @@ -147,6 +149,11 @@ func TestParseTerragruntOptionsFromArgs(t *testing.T) {
nil,
ArgMissingValue("terragrunt-config"),
},
{
[]string{"--terragrunt-debug"},
mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, []string{}, false, "", false, false, defaultLogLevel, true),
nil,
},
}

for _, testCase := range testCases {
Expand Down Expand Up @@ -178,7 +185,7 @@ func assertOptionsEqual(t *testing.T, expected options.TerragruntOptions, actual
assert.Equal(t, expected.AwsProviderPatchOverrides, actual.AwsProviderPatchOverrides, msgAndArgs...)
}

func mockOptions(t *testing.T, terragruntConfigPath string, workingDir string, terraformCliArgs []string, nonInteractive bool, terragruntSource string, ignoreDependencyErrors bool, includeExternalDependencies bool, debugMode bool) *options.TerragruntOptions {
func mockOptions(t *testing.T, terragruntConfigPath string, workingDir string, terraformCliArgs []string, nonInteractive bool, terragruntSource string, ignoreDependencyErrors bool, includeExternalDependencies bool, logLevel logrus.Level, debug bool) *options.TerragruntOptions {
opts, err := options.NewTerragruntOptionsForTest(terragruntConfigPath)
if err != nil {
t.Fatalf("error: %v\n", errors.WithStackTrace(err))
Expand All @@ -190,20 +197,21 @@ func mockOptions(t *testing.T, terragruntConfigPath string, workingDir string, t
opts.Source = terragruntSource
opts.IgnoreDependencyErrors = ignoreDependencyErrors
opts.IncludeExternalDependencies = includeExternalDependencies
opts.Debug = debugMode
opts.Logger.Level = logLevel
opts.Debug = debug

return opts
}

func mockOptionsWithIamRole(t *testing.T, terragruntConfigPath string, workingDir string, terraformCliArgs []string, nonInteractive bool, terragruntSource string, ignoreDependencyErrors bool, iamRole string) *options.TerragruntOptions {
opts := mockOptions(t, terragruntConfigPath, workingDir, terraformCliArgs, nonInteractive, terragruntSource, ignoreDependencyErrors, false, false)
opts := mockOptions(t, terragruntConfigPath, workingDir, terraformCliArgs, nonInteractive, terragruntSource, ignoreDependencyErrors, false, defaultLogLevel, false)
opts.IamRole = iamRole

return opts
}

func mockOptionsWithOverrideAttrs(t *testing.T, terragruntConfigPath string, workingDir string, terraformCliArgs []string, overrideAttrs map[string]string) *options.TerragruntOptions {
opts := mockOptions(t, terragruntConfigPath, workingDir, terraformCliArgs, false, "", false, false, false)
opts := mockOptions(t, terragruntConfigPath, workingDir, terraformCliArgs, false, "", false, false, defaultLogLevel, false)
opts.AwsProviderPatchOverrides = overrideAttrs
return opts
}
Expand Down Expand Up @@ -577,7 +585,7 @@ func createTempFile(t *testing.T) string {
}

func mockCmdOptions(t *testing.T, workingDir string, terraformCliArgs []string) *options.TerragruntOptions {
o := mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, terraformCliArgs, true, "", false, false, false)
o := mockOptions(t, util.JoinPath(workingDir, config.DefaultTerragruntConfigPath), workingDir, terraformCliArgs, true, "", false, false, defaultLogLevel, false)
return o
}

Expand Down
4 changes: 2 additions & 2 deletions cli/aws_provider_patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func applyAwsProviderPatch(terragruntOptions *options.TerragruntOptions) error {
}

for _, terraformFile := range terraformFilesInModules {
util.Debugf(terragruntOptions.Logger, "Looking at file %s", terraformFile)
terragruntOptions.Logger.Debugf("Looking at file %s", terraformFile)
originalTerraformFileContents, err := util.ReadFileAsString(terraformFile)
if err != nil {
return err
Expand All @@ -67,7 +67,7 @@ func applyAwsProviderPatch(terragruntOptions *options.TerragruntOptions) error {
}

if codeWasUpdated {
terragruntOptions.Logger.Printf("Patching AWS provider in %s", terraformFile)
terragruntOptions.Logger.Debugf("Patching AWS provider in %s", terraformFile)
if err := util.WriteFileWithSamePermissions(terraformFile, terraformFile, []byte(updatedTerraformFileContents)); err != nil {
return err
}
Expand Down
Loading

0 comments on commit a7c0d43

Please sign in to comment.