From af89a982c98d50d8a0015016c70f311462d5c57f Mon Sep 17 00:00:00 2001 From: Denis O Date: Fri, 11 Oct 2024 08:59:00 +0300 Subject: [PATCH] Redirect engine messages to stderr (#3468) * Add option to redirect stdout to stderr * Engine tests update * Tests update * Lint issues update --- engine/engine.go | 16 +++++++++++----- engine/engine_test.go | 2 +- test/integration_engine_test.go | 8 ++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/engine/engine.go b/engine/engine.go index 8e8330466e..94f1bdc2da 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -680,7 +680,7 @@ func initialize(ctx context.Context, runOptions *ExecutionOptions, client *proto terragruntOptions.Logger.Debugf("Reading init output for engine in %s", runOptions.WorkingDir) - return ReadEngineOutput(runOptions, func() (*OutputLine, error) { + return ReadEngineOutput(runOptions, true, func() (*OutputLine, error) { output, err := request.Recv() if err != nil { return nil, err @@ -718,7 +718,7 @@ func shutdown(ctx context.Context, runOptions *ExecutionOptions, terragruntEngin terragruntOptions.Logger.Debugf("Reading shutdown output for engine in %s", runOptions.WorkingDir) - return ReadEngineOutput(runOptions, func() (*OutputLine, error) { + return ReadEngineOutput(runOptions, true, func() (*OutputLine, error) { output, err := request.Recv() if err != nil { return nil, err @@ -745,7 +745,7 @@ type outputFn func() (*OutputLine, error) // ReadEngineOutput reads the output from the engine, since grpc plugins don't have common type, // use lambda function to read bytes from the stream -func ReadEngineOutput(runOptions *ExecutionOptions, output outputFn) error { +func ReadEngineOutput(runOptions *ExecutionOptions, forceStdErr bool, output outputFn) error { cmdStdout := runOptions.CmdStdout cmdStderr := runOptions.CmdStderr @@ -756,8 +756,14 @@ func ReadEngineOutput(runOptions *ExecutionOptions, output outputFn) error { } if response.Stdout != "" { - if _, err := cmdStdout.Write([]byte(response.Stdout)); err != nil { - return errors.New(err) + if forceStdErr { // redirect stdout to stderr + if _, err := cmdStderr.Write([]byte(response.Stdout)); err != nil { + return errors.New(err) + } + } else { + if _, err := cmdStdout.Write([]byte(response.Stdout)); err != nil { + return errors.New(err) + } } } diff --git a/engine/engine_test.go b/engine/engine_test.go index 60e16c1ba3..0f741b6f55 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -41,6 +41,6 @@ func TestReadEngineOutput(t *testing.T) { }, nil } - err := engine.ReadEngineOutput(runOptions, outputFn) + err := engine.ReadEngineOutput(runOptions, false, outputFn) assert.NoError(t, err) } diff --git a/test/integration_engine_test.go b/test/integration_engine_test.go index c6af905616..a184821fa5 100644 --- a/test/integration_engine_test.go +++ b/test/integration_engine_test.go @@ -86,7 +86,7 @@ func TestEngineRunAllOpentofu(t *testing.T) { assert.Contains(t, stdout, "resource \"local_file\" \"test\"") assert.Contains(t, stdout, "filename = \"./test.txt\"\n") assert.Contains(t, stdout, "OpenTofu has been successful") - assert.Contains(t, stdout, "Tofu Shutdown completed") + assert.Contains(t, stderr, "Tofu Shutdown completed") assert.Contains(t, stdout, "Apply complete!") } @@ -101,7 +101,7 @@ func TestEngineRunAllOpentofuCustomPath(t *testing.T) { assert.Contains(t, stderr, "[INFO] plugin process exited:") assert.Contains(t, stderr, "plugin process exited:") assert.Contains(t, stdout, "OpenTofu has been successful") - assert.Contains(t, stdout, "Tofu Shutdown completed") + assert.Contains(t, stderr, "Tofu Shutdown completed") assert.Contains(t, stdout, "Apply complete!") // check if cache folder is not empty @@ -208,12 +208,12 @@ func TestEngineOpentofuLatestRunAll(t *testing.T) { tmpEnvPath := copyEnvironment(t, testFixtureOpenTofuLatestRunAll) rootPath := util.JoinPath(tmpEnvPath, testFixtureOpenTofuLatestRunAll) - stdout, _, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt run-all apply -no-color -auto-approve --terragrunt-non-interactive --terragrunt-forward-tf-stdout --terragrunt-working-dir %s", rootPath)) + stdout, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt run-all apply -no-color -auto-approve --terragrunt-non-interactive --terragrunt-forward-tf-stdout --terragrunt-working-dir %s", rootPath)) require.NoError(t, err) assert.Contains(t, stdout, "resource \"local_file\" \"test\"") assert.Contains(t, stdout, "filename = \"./test.txt\"\n") - assert.Contains(t, stdout, "Tofu Shutdown completed") + assert.Contains(t, stderr, "Tofu Shutdown completed") assert.Contains(t, stdout, "Apply complete!") }