Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tee stdout and stderr for consumers #49

Merged
merged 1 commit into from
Aug 14, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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