fix: Do not include stderr content in result of `{{ exec }}` (#1298)
Seems like this was a regression since f676c61425 and #1159
Fixes #1258
This commit is contained in:
parent
63c8df9873
commit
7db31846cf
|
|
@ -5,19 +5,55 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func newExitError(helmCmdPath string, exitStatus int, errorMessage string) ExitError {
|
||||
func newExitError(path string, args []string, exitStatus int, err error, stderr, combined string) ExitError {
|
||||
var out string
|
||||
|
||||
out += fmt.Sprintf("PATH:\n%s", Indent(path, " "))
|
||||
|
||||
out += "\n\nARGS:"
|
||||
for i, a := range args {
|
||||
out += fmt.Sprintf("\n%s", Indent(fmt.Sprintf("%d: %s (%d bytes)", i, a, len(a)), " "))
|
||||
}
|
||||
|
||||
out += fmt.Sprintf("\n\nERROR:\n%s", Indent(err.Error(), " "))
|
||||
|
||||
out += fmt.Sprintf("\n\nEXIT STATUS\n%s", Indent(fmt.Sprintf("%d", exitStatus), " "))
|
||||
|
||||
if len(stderr) > 0 {
|
||||
out += fmt.Sprintf("\n\nSTDERR:\n%s", Indent(stderr, " "))
|
||||
}
|
||||
|
||||
if len(combined) > 0 {
|
||||
out += fmt.Sprintf("\n\nCOMBINED OUTPUT:\n%s", Indent(combined, " "))
|
||||
}
|
||||
|
||||
return ExitError{
|
||||
Message: fmt.Sprintf("the following cmd exited with status %d:\n%s\n\n%s", exitStatus, indent(strings.TrimSpace(helmCmdPath)), indent(strings.TrimSpace(errorMessage))),
|
||||
Message: fmt.Sprintf("command %q exited with non-zero status:\n\n%s", path, out),
|
||||
Code: exitStatus,
|
||||
}
|
||||
}
|
||||
|
||||
func indent(text string) string {
|
||||
// indents a block of text with an indent string
|
||||
func Indent(text, indent string) string {
|
||||
var b strings.Builder
|
||||
|
||||
b.Grow(len(text) * 2)
|
||||
|
||||
lines := strings.Split(text, "\n")
|
||||
for i := range lines {
|
||||
lines[i] = " " + lines[i]
|
||||
|
||||
last := len(lines) - 1
|
||||
|
||||
for i, j := range lines {
|
||||
if i > 0 && i < last && j != "" {
|
||||
b.WriteString("\n")
|
||||
}
|
||||
|
||||
if j != "" {
|
||||
b.WriteString(indent + j)
|
||||
}
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// ExitError is created whenever your shell command exits with a non-zero exit status
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
|
@ -33,10 +34,10 @@ func (shell ShellRunner) Execute(cmd string, args []string, env map[string]strin
|
|||
preparedCmd := exec.Command(cmd, args...)
|
||||
preparedCmd.Dir = shell.Dir
|
||||
preparedCmd.Env = mergeEnv(os.Environ(), env)
|
||||
return combinedOutput(preparedCmd, shell.Logger)
|
||||
return Output(preparedCmd)
|
||||
}
|
||||
|
||||
func combinedOutput(c *exec.Cmd, logger *zap.SugaredLogger) ([]byte, error) {
|
||||
func Output(c *exec.Cmd) ([]byte, error) {
|
||||
if c.Stdout != nil {
|
||||
return nil, errors.New("exec: Stdout already set")
|
||||
}
|
||||
|
|
@ -45,13 +46,11 @@ func combinedOutput(c *exec.Cmd, logger *zap.SugaredLogger) ([]byte, error) {
|
|||
}
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
c.Stdout = &stdout
|
||||
c.Stderr = &stderr
|
||||
var combined bytes.Buffer
|
||||
c.Stdout = io.MultiWriter(&stdout, &combined)
|
||||
c.Stderr = io.MultiWriter(&stderr, &combined)
|
||||
err := c.Run()
|
||||
|
||||
o := stdout.Bytes()
|
||||
e := stderr.Bytes()
|
||||
|
||||
if err != nil {
|
||||
// TrimSpace is necessary, because otherwise helmfile prints the redundant new-lines after each error like:
|
||||
//
|
||||
|
|
@ -64,14 +63,13 @@ func combinedOutput(c *exec.Cmd, logger *zap.SugaredLogger) ([]byte, error) {
|
|||
// so that helmfile could return its own exit code accordingly
|
||||
waitStatus := ee.Sys().(syscall.WaitStatus)
|
||||
exitStatus := waitStatus.ExitStatus()
|
||||
cmd := fmt.Sprintf("%s %s", c.Path, strings.Join(c.Args, " "))
|
||||
err = newExitError(cmd, exitStatus, string(e))
|
||||
err = newExitError(c.Path, c.Args, exitStatus, ee, stderr.String(), combined.String())
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected error: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
return o, err
|
||||
return stdout.Bytes(), err
|
||||
}
|
||||
|
||||
func mergeEnv(orig []string, new map[string]string) []string {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package tmpl
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/roboll/helmfile/pkg/helmexec"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io"
|
||||
|
|
@ -97,25 +98,9 @@ func (c *Context) Exec(command string, args []interface{}, inputs ...string) (st
|
|||
g.Go(func() error {
|
||||
// We use CombinedOutput to produce helpful error messages
|
||||
// See https://github.com/roboll/helmfile/issues/1158
|
||||
bs, err := cmd.CombinedOutput()
|
||||
bs, err := helmexec.Output(cmd)
|
||||
if err != nil {
|
||||
args := strings.Join(strArgs, ", ")
|
||||
shownCmd := []string{command}
|
||||
if len(args) > 0 {
|
||||
shownCmd = append(shownCmd, args)
|
||||
}
|
||||
|
||||
var out string
|
||||
|
||||
out += fmt.Sprintf("\n\nCOMMAND:\n%s", Indent(strings.Join(shownCmd, " "), " "))
|
||||
|
||||
out += fmt.Sprintf("\n\nERROR:\n%s", Indent(err.Error(), " "))
|
||||
|
||||
if len(bs) > 0 {
|
||||
out += fmt.Sprintf("\n\nCOMBINED OUTPUT:\n%s", Indent(string(bs), " "))
|
||||
}
|
||||
|
||||
return fmt.Errorf("%v%s", err, out)
|
||||
return err
|
||||
}
|
||||
|
||||
bytes = bs
|
||||
|
|
@ -130,29 +115,6 @@ func (c *Context) Exec(command string, args []interface{}, inputs ...string) (st
|
|||
return string(bytes), nil
|
||||
}
|
||||
|
||||
// indents a block of text with an indent string
|
||||
func Indent(text, indent string) string {
|
||||
var b strings.Builder
|
||||
|
||||
b.Grow(len(text) * 2)
|
||||
|
||||
lines := strings.Split(text, "\n")
|
||||
|
||||
last := len(lines) - 1
|
||||
|
||||
for i, j := range lines {
|
||||
if i > 0 && i < last && j != "" {
|
||||
b.WriteString("\n")
|
||||
}
|
||||
|
||||
if j != "" {
|
||||
b.WriteString(indent + j)
|
||||
}
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (c *Context) ReadFile(filename string) (string, error) {
|
||||
var path string
|
||||
if filepath.IsAbs(filename) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue