Skip to content

Commit

Permalink
tee stdout and stderr for consumers
Browse files Browse the repository at this point in the history
  • Loading branch information
paultyng committed Aug 14, 2020
1 parent 93ae3eb commit fe6623b
Show file tree
Hide file tree
Showing 12 changed files with 71 additions and 90 deletions.
13 changes: 1 addition & 12 deletions tfexec/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"os/exec"
"strconv"
"strings"
)

type applyConfig struct {
Expand Down Expand Up @@ -81,17 +80,7 @@ func (opt *DirOrPlanOption) configureApply(conf *applyConfig) {
}

func (tf *Terraform) Apply(ctx context.Context, opts ...ApplyOption) error {
applyCmd := tf.applyCmd(ctx, opts...)

var errBuf strings.Builder
applyCmd.Stderr = &errBuf

err := applyCmd.Run()
if err != nil {
return parseError(err, errBuf.String())
}

return nil
return tf.runTerraformCmd(tf.applyCmd(ctx, opts...))
}

func (tf *Terraform) applyCmd(ctx context.Context, opts ...ApplyOption) *exec.Cmd {
Expand Down
23 changes: 23 additions & 0 deletions tfexec/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tfexec

import (
"context"
"io"
"os"
"os/exec"
"strings"
Expand Down Expand Up @@ -100,3 +101,25 @@ func (tf *Terraform) buildTerraformCmd(ctx context.Context, args ...string) *exe

return cmd
}

func (tf *Terraform) runTerraformCmd(cmd *exec.Cmd) error {
var errBuf strings.Builder

stdout := tf.stdout
if cmd.Stdout != nil {
stdout = io.MultiWriter(cmd.Stdout, stdout)
}
cmd.Stdout = stdout

stderr := io.MultiWriter(&errBuf, tf.stderr)
if cmd.Stderr != nil {
stderr = io.MultiWriter(cmd.Stderr, stderr)
}
cmd.Stderr = stderr

err := cmd.Run()
if err != nil {
return parseError(err, errBuf.String())
}
return nil
}
13 changes: 1 addition & 12 deletions tfexec/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"os/exec"
"strconv"
"strings"
)

type destroyConfig struct {
Expand Down Expand Up @@ -77,17 +76,7 @@ func (opt *VarOption) configureDestroy(conf *destroyConfig) {
}

func (tf *Terraform) Destroy(ctx context.Context, opts ...DestroyOption) error {
destroyCmd := tf.destroyCmd(ctx, opts...)

var errBuf strings.Builder
destroyCmd.Stderr = &errBuf

err := destroyCmd.Run()
if err != nil {
return parseError(err, errBuf.String())
}

return nil
return tf.runTerraformCmd(tf.destroyCmd(ctx, opts...))
}

func (tf *Terraform) destroyCmd(ctx context.Context, opts ...DestroyOption) *exec.Cmd {
Expand Down
15 changes: 2 additions & 13 deletions tfexec/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"os/exec"
"strconv"
"strings"
)

type importConfig struct {
Expand Down Expand Up @@ -67,18 +66,8 @@ func (opt *VarFileOption) configureImport(conf *importConfig) {
conf.varFile = opt.path
}

func (t *Terraform) Import(ctx context.Context, address, id string, opts ...ImportOption) error {
importCmd := t.importCmd(ctx, address, id, opts...)

var errBuf strings.Builder
importCmd.Stderr = &errBuf

err := importCmd.Run()
if err != nil {
return parseError(err, errBuf.String())
}

return nil
func (tf *Terraform) Import(ctx context.Context, address, id string, opts ...ImportOption) error {
return tf.runTerraformCmd(tf.importCmd(ctx, address, id, opts...))
}

func (tf *Terraform) importCmd(ctx context.Context, address, id string, opts ...ImportOption) *exec.Cmd {
Expand Down
15 changes: 2 additions & 13 deletions tfexec/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"os/exec"
"strings"
)

type initConfig struct {
Expand Down Expand Up @@ -82,18 +81,8 @@ func (opt *VerifyPluginsOption) configureInit(conf *initConfig) {
conf.verifyPlugins = opt.verifyPlugins
}

func (t *Terraform) Init(ctx context.Context, opts ...InitOption) error {
initCmd := t.initCmd(ctx, opts...)

var errBuf strings.Builder
initCmd.Stderr = &errBuf

err := initCmd.Run()
if err != nil {
return parseError(err, errBuf.String())
}

return nil
func (tf *Terraform) Init(ctx context.Context, opts ...InitOption) error {
return tf.runTerraformCmd(tf.initCmd(ctx, opts...))
}

func (tf *Terraform) initCmd(ctx context.Context, opts ...InitOption) *exec.Cmd {
Expand Down
6 changes: 6 additions & 0 deletions tfexec/internal/e2etest/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,14 @@ func runTestVersions(t *testing.T, versions []string, fixtureName string, cb fun
}
}

var stdouterr bytes.Buffer
tf.SetStdout(&stdouterr)
tf.SetStderr(&stdouterr)

// TODO: capture panics here?
cb(t, version.Must(version.NewVersion(tfv)), tf)

t.Logf("CLI Output:\n%s", stdouterr.String())
})
}
}
Expand Down
8 changes: 2 additions & 6 deletions tfexec/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"context"
"encoding/json"
"os/exec"
"strings"
)

type outputConfig struct {
Expand Down Expand Up @@ -36,17 +35,14 @@ type OutputMeta struct {
func (tf *Terraform) Output(ctx context.Context, opts ...OutputOption) (map[string]OutputMeta, error) {
outputCmd := tf.outputCmd(ctx, opts...)

var errBuf strings.Builder
var outBuf bytes.Buffer

outputCmd.Stderr = &errBuf
outputCmd.Stdout = &outBuf

outputs := map[string]OutputMeta{}

err := outputCmd.Run()
err := tf.runTerraformCmd(outputCmd)
if err != nil {
return nil, parseError(err, errBuf.String())
return nil, err
}

err = json.Unmarshal(outBuf.Bytes(), &outputs)
Expand Down
13 changes: 1 addition & 12 deletions tfexec/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"os/exec"
"strconv"
"strings"
)

type planConfig struct {
Expand Down Expand Up @@ -74,17 +73,7 @@ func (opt *DestroyFlagOption) configurePlan(conf *planConfig) {
}

func (tf *Terraform) Plan(ctx context.Context, opts ...PlanOption) error {
planCmd := tf.planCmd(ctx, opts...)

var errBuf strings.Builder
planCmd.Stderr = &errBuf

err := planCmd.Run()
if err != nil {
return parseError(err, errBuf.String())
}

return nil
return tf.runTerraformCmd(tf.planCmd(ctx, opts...))
}

func (tf *Terraform) planCmd(ctx context.Context, opts ...PlanOption) *exec.Cmd {
Expand Down
13 changes: 4 additions & 9 deletions tfexec/providers_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,20 @@ import (
"context"
"encoding/json"
"os/exec"
"strings"

tfjson "github.com/hashicorp/terraform-json"
)

func (tf *Terraform) ProvidersSchema(ctx context.Context) (*tfjson.ProviderSchemas, error) {
var ret tfjson.ProviderSchemas

var errBuf strings.Builder
var outBuf bytes.Buffer

schemaCmd := tf.providersSchemaCmd(ctx)

schemaCmd.Stderr = &errBuf
var ret tfjson.ProviderSchemas
var outBuf bytes.Buffer
schemaCmd.Stdout = &outBuf

err := schemaCmd.Run()
err := tf.runTerraformCmd(schemaCmd)
if err != nil {
return nil, parseError(err, errBuf.String())
return nil, err
}

err = json.Unmarshal(outBuf.Bytes(), &ret)
Expand Down
13 changes: 4 additions & 9 deletions tfexec/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"os/exec"
"strings"

tfjson "github.com/hashicorp/terraform-json"
)
Expand All @@ -17,19 +16,15 @@ func (tf *Terraform) Show(ctx context.Context) (*tfjson.State, error) {
return nil, fmt.Errorf("terraform show -json was added in 0.12.0: %w", err)
}

var ret tfjson.State

var errBuf strings.Builder
var outBuf bytes.Buffer

showCmd := tf.showCmd(ctx)

showCmd.Stderr = &errBuf
var ret tfjson.State
var outBuf bytes.Buffer
showCmd.Stdout = &outBuf

err = showCmd.Run()
err = tf.runTerraformCmd(showCmd)
if err != nil {
return nil, parseError(err, errBuf.String())
return nil, err
}

err = json.Unmarshal(outBuf.Bytes(), &ret)
Expand Down
22 changes: 22 additions & 0 deletions tfexec/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tfexec

import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
Expand All @@ -16,6 +17,8 @@ type Terraform struct {
workingDir string
env map[string]string

stdout io.Writer
stderr io.Writer
logger *log.Logger
logPath string

Expand Down Expand Up @@ -46,6 +49,8 @@ func NewTerraform(workingDir string, execPath string) (*Terraform, error) {
workingDir: workingDir,
env: nil, // explicit nil means copy os.Environ
logger: log.New(ioutil.Discard, "", 0),
stdout: ioutil.Discard,
stderr: ioutil.Discard,
}

return &tf, nil
Expand All @@ -71,10 +76,27 @@ func (tf *Terraform) SetEnv(env map[string]string) error {
return nil
}

// SetLogger specifies a logger for tfexec to use.
func (tf *Terraform) SetLogger(logger *log.Logger) {
tf.logger = logger
}

// SetStdout specifies a writer to stream stdout to for every command.
//
// This should be used for information or logging purposes only, not control
// flow. Any parsing necessary should be added as functionality to this package.
func (tf *Terraform) SetStdout(w io.Writer) {
tf.stdout = w
}

// SetStderr specifies a writer to stream stderr to for every command.
//
// This should be used for information or logging purposes only, not control
// flow. Any parsing necessary should be added as functionality to this package.
func (tf *Terraform) SetStderr(w io.Writer) {
tf.stderr = w
}

// SetLogPath sets the TF_LOG_PATH environment variable for Terraform CLI
// execution.
func (tf *Terraform) SetLogPath(path string) error {
Expand Down
7 changes: 3 additions & 4 deletions tfexec/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,13 @@ func (tf *Terraform) version(ctx context.Context) (*version.Version, map[string]
// for that here and fallback to string parsing

versionCmd := tf.buildTerraformCmd(ctx, "version")
var errBuf strings.Builder

var outBuf bytes.Buffer
versionCmd.Stderr = &errBuf
versionCmd.Stdout = &outBuf

err := versionCmd.Run()
err := tf.runTerraformCmd(versionCmd)
if err != nil {
return nil, nil, parseError(err, errBuf.String())
return nil, nil, err
}

tfVersion, providerVersions, err := parseVersionOutput(outBuf.String())
Expand Down

0 comments on commit fe6623b

Please sign in to comment.