Skip to content

Commit

Permalink
Properly set the Stdout/StdErr field for commands (#841)
Browse files Browse the repository at this point in the history
We were incorrectly using the Pipe functions
and logging it by parsing each newline. Simply
setting the Stdout/StdErr fields is the correct way
and avoids detecting newlines.

This also improves logging by not splitting every
single newline into a separate log line. Rather
logging a whole string from Terraform in one shot.

Fixes #835

* Update deployment/terraform/engine.go

Co-authored-by: Felipe Martin <[email protected]>

* added missing import

---------

Co-authored-by: Felipe Martin <[email protected]>
  • Loading branch information
agnivade and fmartingr authored Oct 30, 2024
1 parent 8ea1d23 commit 26c034a
Showing 1 changed file with 12 additions and 41 deletions.
53 changes: 12 additions & 41 deletions deployment/terraform/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
package terraform

import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"os/exec"
"sync"
"strings"

"time"

Expand Down Expand Up @@ -65,6 +64,14 @@ func (t *Terraform) runAWSCommand(ctx context.Context, args []string, dst io.Wri
return _runCommand(cmd, dst)
}

type cmdLogger struct {
}

func (*cmdLogger) Write(in []byte) (int, error) {
mlog.Info(strings.TrimSpace(string(in)))
return len(in), nil
}

func _runCommand(cmd *exec.Cmd, dst io.Writer) error {
// If dst is set, that means we want to capture the output.
// We write a simple case to handle that using CombinedOutput.
Expand All @@ -77,46 +84,10 @@ func _runCommand(cmd *exec.Cmd, dst io.Writer) error {
return err
}

// From here, we want to stream the output concurrently from stderr and stdout
// to mlog.
stderr, err := cmd.StderrPipe()
if err != nil {
return err
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
cmd.Stdout = &cmdLogger{}
cmd.Stderr = cmd.Stdout

if err := cmd.Start(); err != nil {
return err
}

var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
scanner := bufio.NewScanner(stderr)
for scanner.Scan() {
mlog.Info(scanner.Text())
}
}()

go func() {
defer wg.Done()
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
mlog.Info(scanner.Text())
}
}()

// No need to check for scanner.Error as cmd.Wait() already does that.
wg.Wait()

if err := cmd.Wait(); err != nil {
return err
}
return nil
return cmd.Run()
}

func checkTerraformVersion() error {
Expand Down

0 comments on commit 26c034a

Please sign in to comment.