diff --git a/pkg/format/format.go b/pkg/format/format.go index 150af44c2a..0386f098da 100644 --- a/pkg/format/format.go +++ b/pkg/format/format.go @@ -37,11 +37,16 @@ func Log(podName string, containerName string, output string) { func LogTo(w io.Writer, pod string, container string, output string) { if output != "" { for _, line := range regex.Split(output, -1) { + // retain the original format of phase outputs for ease + // of processing later. if strings.Contains(line, pkgout.PhaseOpString) { + if _, err := w.Write([]byte(line + "\n")); err != nil { + log.PrintTo(w, err.Error()) + } continue } - if line != "" { + if strings.TrimSpace(line) != "" { fields := field.M{ "Pod": pod, "Container": container, diff --git a/pkg/format/format_test.go b/pkg/format/format_test.go new file mode 100644 index 0000000000..a5f63f9d68 --- /dev/null +++ b/pkg/format/format_test.go @@ -0,0 +1,103 @@ +package format + +import ( + "bytes" + "fmt" + "strings" + "testing" + + "github.com/kanisterio/kanister/pkg/output" + . "gopkg.in/check.v1" +) + +func Test(t *testing.T) { TestingT(t) } + +type FormatTest struct{} + +var _ = Suite(&FormatTest{}) + +func (s *FormatTest) TestLogToForPhaseOutputs(c *C) { + const ( + pod = "test-pod-logto" + container = "test-container-logto" + ) + + // invariant: format.LogTo() will not format phase outputs. + + var testCases = []struct { + keys []string + values []string + }{ + { + keys: []string{"key1"}, + values: []string{"value1"}, + }, + { + keys: []string{"key1", "key2"}, + values: []string{"value1", "value2"}, + }, + { + keys: []string{"key1", "key2", "key3"}, + values: []string{"value1", "value2", "value3"}, + }, + } + + for _, tc := range testCases { + expected := "" + input := &bytes.Buffer{} + actual := &bytes.Buffer{} + + for i, key := range tc.keys { + // create the phase output for each pair of the given k/v + kv := &bytes.Buffer{} + err := output.PrintOutputTo(kv, key, tc.values[i]) + c.Assert(err, IsNil) + + kvRaw := fmt.Sprintf("%s\n", kv.String()) + if _, err := input.WriteString(kvRaw); err != nil { + c.Assert(err, IsNil) + } + + expected += fmt.Sprintf("%s {\"key\":\"%s\",\"value\":\"%s\"}\n", output.PhaseOpString, key, tc.values[i]) + } + LogTo(actual, pod, container, input.String()) + c.Check(expected, DeepEquals, actual.String()) + } +} + +func (s *FormatTest) TestLogToForNormalLogs(c *C) { + const ( + pod = "test-pod-logto" + container = "test-container-logto" + ) + + var testCases = []struct { + input string + expected string + count int // count represents how many "Out"s in the results + }{ + { + input: "", + expected: "", + count: 1, + }, + { + input: "test logs", + expected: `"Out":"test logs"`, + count: 1, + }, + { + input: "test logs\ntest logs", + expected: `"Out":"test logs"`, + count: 2, // the line break causes 2 log lines to be printed + }, + } + + for _, tc := range testCases { + actual := &bytes.Buffer{} + LogTo(actual, pod, container, tc.input) + + c.Assert(strings.Contains(actual.String(), tc.expected), Equals, true) + c.Assert(strings.Count(actual.String(), tc.expected), Equals, tc.count) + } +} diff --git a/pkg/output/output.go b/pkg/output/output.go index 1d8ca40d4a..8608df9c8b 100644 --- a/pkg/output/output.go +++ b/pkg/output/output.go @@ -72,6 +72,11 @@ func PrintOutput(key, value string) error { return fPrintOutput(os.Stdout, key, value) } +// PrintOutput prints the output of the `kando output` command to w. +func PrintOutputTo(w io.Writer, key, value string) error { + return fPrintOutput(w, key, value) +} + func fPrintOutput(w io.Writer, key, value string) error { outString, err := marshalOutput(key, value) if err != nil {