From 4f4eba49aba1045cf7ceda2a6b0bb512b8befe8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ramon=20R=C3=BCttimann?= Date: Tue, 5 May 2020 19:03:54 +0200 Subject: [PATCH] Refactor code to make it simpler to use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramon Rüttimann --- modules/docker/build.go | 8 +- modules/docker/docker_compose.go | 6 +- modules/docker/inspect.go | 2 +- modules/docker/run.go | 12 +-- modules/docker/stop.go | 8 +- modules/helm/cmd.go | 2 +- modules/helm/options.go | 2 +- modules/logger/logger.go | 160 ++++++++++++++++--------------- modules/logger/logger_test.go | 48 ++++------ modules/packer/packer.go | 4 +- modules/shell/command.go | 20 ++-- modules/shell/command_test.go | 4 +- modules/terraform/cmd.go | 4 +- modules/terraform/options.go | 2 +- 14 files changed, 134 insertions(+), 148 deletions(-) diff --git a/modules/docker/build.go b/modules/docker/build.go index 08934fe37..c4965b8f3 100644 --- a/modules/docker/build.go +++ b/modules/docker/build.go @@ -20,8 +20,8 @@ type BuildOptions struct { // solely focus on the most important ones. OtherOptions []string - // Set one or more loggers that should be used. See the logger package for more info. - Log *logger.Loggers + // Set a logger that should be used. See the logger package for more info. + Logger *logger.Logger } // Build runs the 'docker build' command at the given path with the given options and fails the test if there are any @@ -32,7 +32,7 @@ func Build(t testing.TestingT, path string, options *BuildOptions) { // BuildE runs the 'docker build' command at the given path with the given options and returns any errors. func BuildE(t testing.TestingT, path string, options *BuildOptions) error { - options.Log.Logf(t, "Running 'docker build' in %s", path) + options.Logger.Logf(t, "Running 'docker build' in %s", path) args, err := formatDockerBuildArgs(path, options) if err != nil { @@ -42,7 +42,7 @@ func BuildE(t testing.TestingT, path string, options *BuildOptions) error { cmd := shell.Command{ Command: "docker", Args: args, - Log: options.Log, + Logger: options.Logger, } _, buildErr := shell.RunCommandAndGetOutputE(t, cmd) diff --git a/modules/docker/docker_compose.go b/modules/docker/docker_compose.go index d9aac6ae7..8d121d948 100644 --- a/modules/docker/docker_compose.go +++ b/modules/docker/docker_compose.go @@ -10,8 +10,8 @@ import ( type Options struct { WorkingDir string EnvVars map[string]string - // Set one or more loggers that should be used. See the logger package for more info. - Log *logger.Loggers + // Set a logger that should be used. See the logger package for more info. + Logger *logger.Logger } // RunDockerCompose runs docker-compose with the given arguments and options and return stdout/stderr. @@ -32,7 +32,7 @@ func RunDockerComposeE(t testing.TestingT, options *Options, args ...string) (st Args: append([]string{"--project-name", t.Name()}, args...), WorkingDir: options.WorkingDir, Env: options.EnvVars, - Log: options.Log, + Logger: options.Logger, } return shell.RunCommandAndGetOutputE(t, cmd) diff --git a/modules/docker/inspect.go b/modules/docker/inspect.go index 04777b593..f789efdd8 100644 --- a/modules/docker/inspect.go +++ b/modules/docker/inspect.go @@ -96,7 +96,7 @@ func InspectE(t *testing.T, id string) (*ContainerInspect, error) { Command: "docker", Args: []string{"container", "inspect", id}, // inspect is a short-running command, don't print the output. - Log: logger.With(logger.Discard), + Logger: logger.Discard, } out, err := shell.RunCommandAndGetStdOutE(t, cmd) diff --git a/modules/docker/run.go b/modules/docker/run.go index 49ee8f66b..f818748a9 100644 --- a/modules/docker/run.go +++ b/modules/docker/run.go @@ -48,8 +48,8 @@ type RunOptions struct { // solely focus on the most important ones. OtherOptions []string - // Set one or more loggers that should be used. See the logger package for more info. - Log *logger.Loggers + // Set a logger that should be used. See the logger package for more info. + Logger *logger.Logger } // Run runs the 'docker run' command on the given image with the given options and return stdout/stderr. This method @@ -62,7 +62,7 @@ func Run(t testing.TestingT, image string, options *RunOptions) string { // RunE runs the 'docker run' command on the given image with the given options and return stdout/stderr, or any error. func RunE(t testing.TestingT, image string, options *RunOptions) (string, error) { - options.Log.Logf(t, "Running 'docker run' on image '%s'", image) + options.Logger.Logf(t, "Running 'docker run' on image '%s'", image) args, err := formatDockerRunArgs(image, options) if err != nil { @@ -72,7 +72,7 @@ func RunE(t testing.TestingT, image string, options *RunOptions) (string, error) cmd := shell.Command{ Command: "docker", Args: args, - Log: options.Log, + Logger: options.Logger, } return shell.RunCommandAndGetOutputE(t, cmd) @@ -89,7 +89,7 @@ func RunAndGetID(t testing.TestingT, image string, options *RunOptions) string { // RunAndGetIDE runs the 'docker run' command on the given image with the given options and returns the container ID // that is returned in stdout, or any error. func RunAndGetIDE(t testing.TestingT, image string, options *RunOptions) (string, error) { - options.Log.Logf(t, "Running 'docker run' on image '%s', returning stdout", image) + options.Logger.Logf(t, "Running 'docker run' on image '%s', returning stdout", image) args, err := formatDockerRunArgs(image, options) if err != nil { @@ -99,7 +99,7 @@ func RunAndGetIDE(t testing.TestingT, image string, options *RunOptions) (string cmd := shell.Command{ Command: "docker", Args: args, - Log: options.Log, + Logger: options.Logger, } return shell.RunCommandAndGetStdOutE(t, cmd) diff --git a/modules/docker/stop.go b/modules/docker/stop.go index e14f7c7c9..e5a43c600 100644 --- a/modules/docker/stop.go +++ b/modules/docker/stop.go @@ -14,8 +14,8 @@ type StopOptions struct { // Seconds to wait for stop before killing the container (default 10) Time int - // Set one or more loggers that should be used. See the logger package for more info. - Log *logger.Loggers + // Set a logger that should be used. See the logger package for more info. + Logger *logger.Logger } // Stop runs the 'docker stop' command for the given containers and return the stdout/stderr. This method fails @@ -28,7 +28,7 @@ func Stop(t testing.TestingT, containers []string, options *StopOptions) string // StopE runs the 'docker stop' command for the given containers and returns any errors. func StopE(t testing.TestingT, containers []string, options *StopOptions) (string, error) { - options.Log.Logf(t, "Running 'docker stop' on containers '%s'", containers) + options.Logger.Logf(t, "Running 'docker stop' on containers '%s'", containers) args, err := formatDockerStopArgs(containers, options) if err != nil { @@ -38,7 +38,7 @@ func StopE(t testing.TestingT, containers []string, options *StopOptions) (strin cmd := shell.Command{ Command: "docker", Args: args, - Log: options.Log, + Logger: options.Logger, } return shell.RunCommandAndGetOutputE(t, cmd) diff --git a/modules/helm/cmd.go b/modules/helm/cmd.go index 40af7e20d..d4e3c47ac 100644 --- a/modules/helm/cmd.go +++ b/modules/helm/cmd.go @@ -61,7 +61,7 @@ func RunHelmCommandAndGetOutputE(t testing.TestingT, options *Options, cmd strin Args: args, WorkingDir: ".", Env: options.EnvVars, - Log: options.Log, + Logger: options.Logger, } return shell.RunCommandAndGetOutputE(t, helmCmd) } diff --git a/modules/helm/options.go b/modules/helm/options.go index f9340ba09..4c6a91fb8 100644 --- a/modules/helm/options.go +++ b/modules/helm/options.go @@ -14,5 +14,5 @@ type Options struct { HomePath string // The path to the helm home to use when calling out to helm. Empty string means use default ($HOME/.helm). EnvVars map[string]string // Environment variables to set when running helm Version string // Version of chart - Log *logger.Loggers // Set one or more loggers that should be used. See the logger package for more info. + Logger *logger.Logger // Set a non-default logger that should be used. See the logger package for more info. } diff --git a/modules/logger/logger.go b/modules/logger/logger.go index 8223a3e48..d290c6eee 100644 --- a/modules/logger/logger.go +++ b/modules/logger/logger.go @@ -6,7 +6,6 @@ import ( "io" "os" "runtime" - "strconv" "strings" gotesting "testing" "time" @@ -14,52 +13,76 @@ import ( "github.com/gruntwork-io/terratest/modules/testing" ) -// defaultLogf will be used if the caller uses the function -// Logf, where on the first call to that function, a sane -// default logging function will be set. We keep that in a -// global variable so that we don't need to define it on -// every call to Logf. -var defaultLogf LogFunc +var ( + // Default is the default logger that is used for the Logf function, if no one is provided. It uses the + // TerratestLogger to log messages. This can be overwritten to change the logging globally. + Default = New(terratestLogger{}) + // Discard discards all logging. + Discard = New(discardLogger{}) + // Terratest logs the given format and arguments, formatted using fmt.Sprintf, to stdout, along with a timestamp and + // information about what test and file is doing the logging. Before Go 1.14, this is an alternative to t.Logf as it + // logs to stdout immediately, rather than buffering all log output and only displaying it at the very end of the test. + // This is useful because: + // + // 1. It allows you to iterate faster locally, as you get feedback on whether your code changes are working as expected + // right away, rather than at the very end of the test run. + // + // 2. If you have a bug in your code that causes a test to never complete or if the test code crashes, t.Logf would + // show you no log output whatsoever, making debugging very hard, where as this method will show you all the log + // output available. + // + // 3. If you have a test that takes a long time to complete, some CI systems will kill the test suite prematurely + // because there is no log output with t.Logf (e.g., CircleCI kills tests after 10 minutes of no log output). With + // this log method, you get log output continuously. + // + Terratest = New(terratestLogger{}) + // TestingT can be used to use Go's testing.T to log. If this is used, but no testing.T is provided, it will fallback + // to Default. + TestingT = New(testingT{}) +) -type Loggers []LogFunc -type LogFunc func(t testing.TestingT, format string, args ...interface{}) +type TestLogger interface { + Logf(t testing.TestingT, format string, args ...interface{}) +} -func With(l ...LogFunc) *Loggers { - lo := Loggers(l) - return &lo +type Logger struct { + l TestLogger } -// Logf logs to all given loggers. If no loggers are given (or it is nil), it will -// use the default logger. This allows for the following usecases: -// var l *Loggers -// l.Logf(...) -// l = With(TestingT) -// l.Logf(...) -func (l *Loggers) Logf(t testing.TestingT, format string, args ...interface{}) { - if tt, ok := t.(*gotesting.T); ok { +func New(l TestLogger) *Logger { + return &Logger{ + l, + } +} + +func (l *Logger) Logf(t testing.TestingT, format string, args ...interface{}) { + if tt, ok := t.(helper); ok { tt.Helper() } - // if l is not initialised or no loggers - // are supplied, use the default logging. - if l == nil || len(*l) == 0 { - logDefaultLogf(t, format, args...) + // methods can be called on (typed) nil pointers. In this case, use the Default function to log. This enables the + // caller to do `var l *Logger` and then use the logger already. + if l == nil || l.l == nil { + Default.Logf(t, format, args...) return } - for _, logf := range *l { - logf(t, format, args...) - } + l.l.Logf(t, format, args...) } -// Discard discards all logging. -func Discard(_ testing.TestingT, format string, args ...interface{}) {} +// helper is used to mark this library as a "helper", and thus not appearing in the line numbers. testing.T implements +// this interface, for example. +type helper interface { + Helper() +} -// TestingT can be used to explicitly use Go's testing.T to log. -// It is also used as the default if Go version >= 1.14 (if detected -// correctly). If this is used, but no testing.T is provided, it will -// fallback to Logger. -func TestingT(t testing.TestingT, format string, args ...interface{}) { +type discardLogger struct{} + +func (_ discardLogger) Logf(_ testing.TestingT, format string, args ...interface{}) {} + +type testingT struct{} + +func (_ testingT) Logf(t testing.TestingT, format string, args ...interface{}) { // this should never fail tt, ok := t.(*gotesting.T) if !ok { @@ -73,64 +96,45 @@ func TestingT(t testing.TestingT, format string, args ...interface{}) { return } -// Logger is the conventional logging utility that terratest uses. -// Default up until Go 1.14. -func Logger(t testing.TestingT, format string, args ...interface{}) { +type terratestLogger struct{} + +func (_ terratestLogger) Logf(t testing.TestingT, format string, args ...interface{}) { DoLog(t, 3, os.Stdout, fmt.Sprintf(format, args...)) } -// Logf logs the given format and arguments with the default logging utility. If the Go -// version can be determined and is 1.14 or above, t.Logf will be used (Go 1.14 introduced -// streaming log output). Else, a default logger will be used that adds a timestamp and -// information about what test and file is doing the logging. -// Compared to the Go's builtin testing.T.Logf, this will always print the output instead -// of buffering it and only display it at the very end of the test. +// Deprecated: use Logger instead, as it provides more flexibility on logging. +// Logf logs the given format and arguments, formatted using fmt.Sprintf, to stdout, along with a timestamp and information +// about what test and file is doing the logging. Before Go 1.14, this is an alternative to t.Logf as it logs to stdout +// immediately, rather than buffering all log output and only displaying it at the very end of the test. This is useful +// because: +// +// 1. It allows you to iterate faster locally, as you get feedback on whether your code changes are working as expected +// right away, rather than at the very end of the test run. +// +// 2. If you have a bug in your code that causes a test to never complete or if the test code crashes, t.Logf would +// show you no log output whatsoever, making debugging very hard, where as this method will show you all the log +// output available. // -// To have more control over logging, use With(...LogFunc) to get a custom logger. -// Builtin alternatives are Discard, TestingT and Logger. +// 3. If you have a test that takes a long time to complete, some CI systems will kill the test suite prematurely +// because there is no log output with t.Logf (e.g., CircleCI kills tests after 10 minutes of no log output). With +// this log method, you get log output continuously. +// Although t.Logf now supports streaming output since Go 1.14, this is kept for compatibility purposes. func Logf(t testing.TestingT, format string, args ...interface{}) { - if tt, ok := t.(*gotesting.T); ok { + if tt, ok := t.(helper); ok { tt.Helper() } - logDefaultLogf(t, format, args...) -} - -func logDefaultLogf(t testing.TestingT, format string, args ...interface{}) { - if defaultLogf == nil { - // if a gotesting.T is given and the go version is 1.14, use - // gotesting.T.Logf - if tt, ok := t.(*gotesting.T); ok && hasStreamingLogf(runtime.Version()) { - tt.Helper() - // we should not assign tt.Logf directly as testing.T may change - // during the execution of the test (consider subtests, for example). - defaultLogf = TestingT - } else { - defaultLogf = Logger - defaultLogf(t, "streaming logf not supported, falling back to legacy logger") - } - } - - defaultLogf(t, format, args...) -} - -// hasStreamingLogf returns true if the go runtime version -// is >= Go 1.14, where streaming Logf output has been -// introduced (https://github.com/golang/go/issues/24929) -func hasStreamingLogf(goVersion string) bool { - noMajor := strings.TrimPrefix(goVersion, "go1.") - ver, err := strconv.ParseFloat(noMajor, 32) - if err != nil { - return false - } - - return ver >= 14 + DoLog(t, 2, os.Stdout, fmt.Sprintf(format, args...)) } // Log logs the given arguments to stdout, along with a timestamp and information about what test and file is doing the // logging. This is an alternative to t.Logf that logs to stdout immediately, rather than buffering all log output and // only displaying it at the very end of the test. See the Logf method for more info. func Log(t testing.TestingT, args ...interface{}) { + if tt, ok := t.(helper); ok { + tt.Helper() + } + DoLog(t, 2, os.Stdout, args...) } diff --git a/modules/logger/logger_test.go b/modules/logger/logger_test.go index 154d346ed..b51b5a898 100644 --- a/modules/logger/logger_test.go +++ b/modules/logger/logger_test.go @@ -21,41 +21,25 @@ func TestDoLog(t *testing.T) { assert.Regexp(t, fmt.Sprintf("^%s .+? [[:word:]]+.go:[0-9]+: %s$", t.Name(), text), strings.TrimSpace(buffer.String())) } -func TestVersion(t *testing.T) { - t.Parallel() - - cases := []struct { - version string - hasStreaming bool - }{ - {"go1.14", true}, - {"go1.14.1", true}, - {"go1.13.5", false}, - {"go1.15", true}, - {"ae0365fab0", false}, // simulate some commit ID - } +type customLogger struct { + logs []string +} - for _, test := range cases { - assert.Equal(t, test.hasStreaming, hasStreamingLogf(test.version)) - } +func (c *customLogger) Logf(t tftesting.TestingT, format string, args ...interface{}) { + c.logs = append(c.logs, fmt.Sprintf(format, args...)) } func TestCustomLogger(t *testing.T) { - var logs []string - customLogf := func(t tftesting.TestingT, format string, args ...interface{}) { - logs = append(logs, fmt.Sprintf(format, args...)) - } - - Logf(t, "this should be logged with legacylogger or testing.T if go >=1.14") - var l *Loggers + Logf(t, "this should be logged with the default logger") - l.Logf(t, "this should be logged with legacylogger or testing.T if go >=1.14") - l = With() - l.Logf(t, "this should be logged with legacylogger or testing.T if go >=1.14") + var l *Logger + l.Logf(t, "this should be logged with the default logger too") - // try all loggers, though this may spam the output a bit. - l = With(customLogf, Logger, TestingT, Discard) + l = New(nil) + l.Logf(t, "this should be logged with the default logger too!") + c := &customLogger{} + l = New(c) l.Logf(t, "log output 1") l.Logf(t, "log output 2") @@ -63,8 +47,8 @@ func TestCustomLogger(t *testing.T) { l.Logf(t, "subtest log") }) - assert.Len(t, logs, 3) - assert.Equal(t, "log output 1", logs[0]) - assert.Equal(t, "log output 2", logs[1]) - assert.Equal(t, "subtest log", logs[2]) + assert.Len(t, c.logs, 3) + assert.Equal(t, "log output 1", c.logs[0]) + assert.Equal(t, "log output 2", c.logs[1]) + assert.Equal(t, "subtest log", c.logs[2]) } diff --git a/modules/packer/packer.go b/modules/packer/packer.go index 96a4e5f00..8ba16e126 100644 --- a/modules/packer/packer.go +++ b/modules/packer/packer.go @@ -27,7 +27,7 @@ type Options struct { MaxRetries int // Maximum number of times to retry errors matching RetryableErrors TimeBetweenRetries time.Duration // The amount of time to wait between retries WorkingDir string // The directory to run packer in - Log *logger.Loggers + Logger *logger.Logger // If set, use a non-default logger } // BuildArtifacts can take a map of identifierName <-> Options and then parallelize @@ -89,7 +89,7 @@ func BuildArtifact(t testing.TestingT, options *Options) string { // BuildArtifactE builds the given Packer template and return the generated Artifact ID. func BuildArtifactE(t testing.TestingT, options *Options) (string, error) { - options.Log.Logf(t, "Running Packer to generate a custom artifact for template %s", options.Template) + options.Logger.Logf(t, "Running Packer to generate a custom artifact for template %s", options.Template) cmd := shell.Command{ Command: "packer", diff --git a/modules/shell/command.go b/modules/shell/command.go index b4ac85c9f..e178bd059 100644 --- a/modules/shell/command.go +++ b/modules/shell/command.go @@ -23,10 +23,8 @@ type Command struct { Args []string // The args to pass to the command WorkingDir string // The working directory Env map[string]string // Additional environment variables to set - // Use the specified logger for the command's output. Use - // logger.With(logger.Discard) - // to not print the output while executing the command. - Log *logger.Loggers + // Use the specified logger for the command's output. Use logger.Discard to not print the output while executing the command. + Logger *logger.Logger } // RunCommand runs a shell command and redirects its stdout and stderr to the stdout of the atomic script itself. @@ -89,7 +87,7 @@ func RunCommandAndGetStdOutE(t testing.TestingT, command Command) (string, error // Depending on the logger, the stdout and stderr of that command will also be // printed to the stdout and stderr of this Go program to make debugging easier. func runCommandAndStoreOutputE(t testing.TestingT, command Command, storedStdout *[]string, storedStderr *[]string) error { - command.Log.Logf(t, "Running command %s with args %s", command.Command, command.Args) + command.Logger.Logf(t, "Running command %s with args %s", command.Command, command.Args) cmd := exec.Command(command.Command, command.Args...) cmd.Dir = command.WorkingDir @@ -111,7 +109,7 @@ func runCommandAndStoreOutputE(t testing.TestingT, command Command, storedStdout return err } - if err := readStdoutAndStderr(t, command.Log.Logf, stdout, stderr, storedStdout, storedStderr); err != nil { + if err := readStdoutAndStderr(t, command.Logger, stdout, stderr, storedStdout, storedStderr); err != nil { return err } @@ -124,7 +122,7 @@ func runCommandAndStoreOutputE(t testing.TestingT, command Command, storedStdout // This function captures stdout and stderr into the given variables while still printing it to the stdout and stderr // of this Go program -func readStdoutAndStderr(t testing.TestingT, logf logger.LogFunc, stdout, stderr io.ReadCloser, storedStdout, storedStderr *[]string) error { +func readStdoutAndStderr(t testing.TestingT, log *logger.Logger, stdout, stderr io.ReadCloser, storedStdout, storedStderr *[]string) error { stdoutReader := bufio.NewReader(stdout) stderrReader := bufio.NewReader(stderr) @@ -135,11 +133,11 @@ func readStdoutAndStderr(t testing.TestingT, logf logger.LogFunc, stdout, stderr var stdoutErr, stderrErr error go func() { defer wg.Done() - stdoutErr = readData(t, logf, stdoutReader, mutex, storedStdout) + stdoutErr = readData(t, log, stdoutReader, mutex, storedStdout) }() go func() { defer wg.Done() - stderrErr = readData(t, logf, stderrReader, mutex, storedStderr) + stderrErr = readData(t, log, stderrReader, mutex, storedStderr) }() wg.Wait() @@ -153,7 +151,7 @@ func readStdoutAndStderr(t testing.TestingT, logf logger.LogFunc, stdout, stderr return nil } -func readData(t testing.TestingT, logf logger.LogFunc, reader *bufio.Reader, mutex *sync.Mutex, allOutput *[]string) error { +func readData(t testing.TestingT, log *logger.Logger, reader *bufio.Reader, mutex *sync.Mutex, allOutput *[]string) error { var line string var err error for { @@ -171,7 +169,7 @@ func readData(t testing.TestingT, logf logger.LogFunc, reader *bufio.Reader, mut break } - logf(t, line) + log.Logf(t, line) mutex.Lock() *allOutput = append(*allOutput, line) mutex.Unlock() diff --git a/modules/shell/command_test.go b/modules/shell/command_test.go index 3d674765c..378ef87d8 100644 --- a/modules/shell/command_test.go +++ b/modules/shell/command_test.go @@ -90,7 +90,7 @@ wait cmd := Command{ Command: "bash", Args: []string{"-c", bashCode}, - Log: logger.With(logger.Discard), + Logger: logger.Discard, } out := RunCommandAndGetOutput(t, cmd) @@ -115,7 +115,7 @@ echo cmd := Command{ Command: "bash", Args: []string{"-c", bashCode}, - Log: logger.With(logger.Discard), // don't print that line to stdout + Logger: logger.Discard, // don't print that line to stdout } out, err := RunCommandAndGetOutputE(t, cmd) diff --git a/modules/terraform/cmd.go b/modules/terraform/cmd.go index 43393019b..25743c414 100644 --- a/modules/terraform/cmd.go +++ b/modules/terraform/cmd.go @@ -15,7 +15,7 @@ func generateCommand(options *Options, args ...string) shell.Command { Args: args, WorkingDir: options.TerraformDir, Env: options.EnvVars, - Log: options.Log, + Logger: options.Logger, } return cmd } @@ -90,7 +90,7 @@ func GetExitCodeForTerraformCommand(t testing.TestingT, additionalOptions *Optio func GetExitCodeForTerraformCommandE(t testing.TestingT, additionalOptions *Options, additionalArgs ...string) (int, error) { options, args := GetCommonOptions(additionalOptions, additionalArgs...) - additionalOptions.Log.Logf(t, "Running %s with args %v", options.TerraformBinary, args) + additionalOptions.Logger.Logf(t, "Running %s with args %v", options.TerraformBinary, args) cmd := generateCommand(options, args...) _, err := shell.RunCommandAndGetOutputE(t, cmd) if err == nil { diff --git a/modules/terraform/options.go b/modules/terraform/options.go index 0536190ce..5787619d9 100644 --- a/modules/terraform/options.go +++ b/modules/terraform/options.go @@ -25,5 +25,5 @@ type Options struct { NoColor bool // Whether the -no-color flag will be set for any Terraform command or not SshAgent *ssh.SshAgent // Overrides local SSH agent with the given in-process agent NoStderr bool // Disable stderr redirection - Log *logger.Loggers // Set one or more loggers that should be used. See the logger package for more info. + Logger *logger.Logger // Set a non-default logger that should be used. See the logger package for more info. }