fix: support large output with --enable-live-ouput (#1139)
* fix: support large output with --enable-live-ouput This replaces Scanner with ReadString to handle large amount of data returned by helm ouptut when executing diff action - Changing pkg/helmexec/runner_test.go TestLiveOutput test, adding test with large amount of data, reproducing the issue before applying this fix - Changing pkg/helmexec/runner.go Scanner with Readstring Resolves https://github.com/helmfile/helmfile/issues/893 Signed-off-by: Franck Labatut <franck.labatut@ubisoft.com> * fix: prevent data race Signed-off-by: Franck Labatut <franck.labatut@ubisoft.com> --------- Signed-off-by: Franck Labatut <franck.labatut@ubisoft.com>
This commit is contained in:
parent
e756712e80
commit
b8a729d8c4
|
|
@ -127,13 +127,26 @@ func Output(ctx context.Context, c *exec.Cmd, stripArgsValuesOnExitError bool, l
|
||||||
|
|
||||||
func LiveOutput(ctx context.Context, c *exec.Cmd, stripArgsValuesOnExitError bool, stdout io.Writer) ([]byte, error) {
|
func LiveOutput(ctx context.Context, c *exec.Cmd, stripArgsValuesOnExitError bool, stdout io.Writer) ([]byte, error) {
|
||||||
reader, writer := io.Pipe()
|
reader, writer := io.Pipe()
|
||||||
scannerStopped := make(chan struct{})
|
ch := make(chan error)
|
||||||
|
doneCh := make(chan struct{})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(scannerStopped)
|
defer close(doneCh)
|
||||||
scanner := bufio.NewScanner(reader)
|
reader := bufio.NewReader(reader)
|
||||||
for scanner.Scan() {
|
|
||||||
fmt.Fprintln(stdout, scanner.Text())
|
for {
|
||||||
|
// prefer readstring over scanner to handle potential large output
|
||||||
|
// https://stackoverflow.com/a/29444042
|
||||||
|
line, err := reader.ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ch <- err
|
||||||
|
}
|
||||||
|
|
||||||
|
line = strings.TrimSuffix(line, "\n")
|
||||||
|
fmt.Fprintln(stdout, line)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -142,7 +155,6 @@ func LiveOutput(ctx context.Context, c *exec.Cmd, stripArgsValuesOnExitError boo
|
||||||
err := c.Start()
|
err := c.Start()
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ch := make(chan error)
|
|
||||||
go func() {
|
go func() {
|
||||||
ch <- c.Wait()
|
ch <- c.Wait()
|
||||||
}()
|
}()
|
||||||
|
|
@ -154,7 +166,7 @@ func LiveOutput(ctx context.Context, c *exec.Cmd, stripArgsValuesOnExitError boo
|
||||||
err = <-ch
|
err = <-ch
|
||||||
}
|
}
|
||||||
_ = writer.Close()
|
_ = writer.Close()
|
||||||
<-scannerStopped
|
<-doneCh
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package helmexec
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
_ "embed"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -48,6 +49,9 @@ func TestShellRunner_Execute(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:embed testdata/live-output-data.txt
|
||||||
|
var liveOutputData string
|
||||||
|
|
||||||
func TestLiveOutput(t *testing.T) {
|
func TestLiveOutput(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
|
@ -55,6 +59,12 @@ func TestLiveOutput(t *testing.T) {
|
||||||
wantW string
|
wantW string
|
||||||
wantErr bool
|
wantErr bool
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
name: "live_output_data",
|
||||||
|
cmd: exec.Command("cat", "testdata/live-output-data.txt"),
|
||||||
|
wantW: liveOutputData,
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "echo_template",
|
name: "echo_template",
|
||||||
cmd: exec.Command("echo", "template"),
|
cmd: exec.Command("echo", "template"),
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue