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:
flabatut 2023-11-11 23:45:08 +01:00 committed by GitHub
parent e756712e80
commit b8a729d8c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29709 additions and 7 deletions

View File

@ -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) {
reader, writer := io.Pipe()
scannerStopped := make(chan struct{})
ch := make(chan error)
doneCh := make(chan struct{})
go func() {
defer close(scannerStopped)
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
fmt.Fprintln(stdout, scanner.Text())
defer close(doneCh)
reader := bufio.NewReader(reader)
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()
if err == nil {
ch := make(chan error)
go func() {
ch <- c.Wait()
}()
@ -154,7 +166,7 @@ func LiveOutput(ctx context.Context, c *exec.Cmd, stripArgsValuesOnExitError boo
err = <-ch
}
_ = writer.Close()
<-scannerStopped
<-doneCh
}
if err != nil {

View File

@ -3,6 +3,7 @@ package helmexec
import (
"bytes"
"context"
_ "embed"
"os/exec"
"reflect"
"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) {
tests := []struct {
name string
@ -55,6 +59,12 @@ func TestLiveOutput(t *testing.T) {
wantW string
wantErr bool
}{
{
name: "live_output_data",
cmd: exec.Command("cat", "testdata/live-output-data.txt"),
wantW: liveOutputData,
wantErr: false,
},
{
name: "echo_template",
cmd: exec.Command("echo", "template"),

29680
pkg/helmexec/testdata/live-output-data.txt vendored Normal file

File diff suppressed because one or more lines are too long