diff --git a/pkg/util/iptables/iptables.go b/pkg/util/iptables/iptables.go index 40fde4a1620..761e55c94a1 100644 --- a/pkg/util/iptables/iptables.go +++ b/pkg/util/iptables/iptables.go @@ -20,7 +20,6 @@ import ( "bytes" "context" "fmt" - "io/ioutil" "regexp" "strings" "sync" @@ -327,14 +326,15 @@ func (runner *runner) SaveInto(table Table, buffer *bytes.Buffer) error { args := []string{"-t", string(table)} klog.V(4).Infof("running %s %v", iptablesSaveCmd, args) cmd := runner.exec.Command(iptablesSaveCmd, args...) - // Since CombinedOutput() doesn't support redirecting it to a buffer, - // we need to workaround it by redirecting stdout and stderr to buffer - // and explicitly calling Run() [CombinedOutput() underneath itself - // creates a new buffer, redirects stdout and stderr to it and also - // calls Run()]. cmd.SetStdout(buffer) - cmd.SetStderr(ioutil.Discard) - return cmd.Run() + stderrBuffer := bytes.NewBuffer(nil) + cmd.SetStderr(stderrBuffer) + + err := cmd.Run() + if err != nil { + stderrBuffer.WriteTo(buffer) // ignore error, since we need to return the original error + } + return err } // Restore is part of Interface. diff --git a/pkg/util/iptables/iptables_test.go b/pkg/util/iptables/iptables_test.go index 73240939ec6..dfc58095381 100644 --- a/pkg/util/iptables/iptables_test.go +++ b/pkg/util/iptables/iptables_test.go @@ -943,7 +943,7 @@ COMMIT }, RunScript: []fakeexec.FakeRunAction{ func() ([]byte, []byte, error) { return []byte(output), []byte(stderrOutput), nil }, - func() ([]byte, []byte, error) { return nil, nil, &fakeexec.FakeExitError{Status: 1} }, + func() ([]byte, []byte, error) { return nil, []byte(stderrOutput), &fakeexec.FakeExitError{Status: 1} }, }, } fexec := fakeexec.FakeExec{ @@ -984,6 +984,9 @@ COMMIT if err == nil { t.Errorf("%s: Expected failure", protoStr) } + if string(buffer.Bytes()) != stderrOutput { + t.Errorf("%s: Expected output '%s', got '%v'", protoStr, stderrOutput, string(buffer.Bytes())) + } } func TestSaveIntoIPv4(t *testing.T) {