diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/diff/diff.go b/staging/src/k8s.io/kubectl/pkg/cmd/diff/diff.go index 31c1e60bb7e..75ee84b7d6b 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/diff/diff.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/diff/diff.go @@ -22,6 +22,8 @@ import ( "io/ioutil" "os" "path/filepath" + "regexp" + "strings" "github.com/jonboulle/clockwork" "github.com/spf13/cobra" @@ -55,7 +57,10 @@ var ( Output is always YAML. KUBECTL_EXTERNAL_DIFF environment variable can be used to select your own - diff command. By default, the "diff" command available in your path will be + diff command. Users can use external commands with params too, example: + KUBECTL_EXTERNAL_DIFF="colordiff -N -u" + + By default, the "diff" command available in your path will be run with "-u" (unified diff) and "-N" (treat absent files as empty) options. Exit status: @@ -168,7 +173,18 @@ type DiffProgram struct { func (d *DiffProgram) getCommand(args ...string) (string, exec.Cmd) { diff := "" if envDiff := os.Getenv("KUBECTL_EXTERNAL_DIFF"); envDiff != "" { - diff = envDiff + diffCommand := strings.Split(envDiff, " ") + diff = diffCommand[0] + + if len(diffCommand) > 1 { + // Regex accepts: Alphanumeric (case-insensitive) and dash + isValidChar := regexp.MustCompile(`^[a-zA-Z0-9-]+$`).MatchString + for i := 1; i < len(diffCommand); i++ { + if isValidChar(diffCommand[i]) { + args = append(args, diffCommand[i]) + } + } + } } else { diff = "diff" args = append([]string{"-u", "-N"}, args...) diff --git a/staging/src/k8s.io/kubectl/pkg/cmd/diff/diff_test.go b/staging/src/k8s.io/kubectl/pkg/cmd/diff/diff_test.go index 2b833e551db..434415ecf49 100644 --- a/staging/src/k8s.io/kubectl/pkg/cmd/diff/diff_test.go +++ b/staging/src/k8s.io/kubectl/pkg/cmd/diff/diff_test.go @@ -52,18 +52,27 @@ func (f *FakeObject) Live() runtime.Object { } func TestDiffProgram(t *testing.T) { - os.Setenv("KUBECTL_EXTERNAL_DIFF", "echo") - streams, _, stdout, _ := genericclioptions.NewTestIOStreams() - diff := DiffProgram{ - IOStreams: streams, - Exec: exec.New(), - } - err := diff.Run("one", "two") - if err != nil { - t.Fatal(err) - } - if output := stdout.String(); output != "one two\n" { - t.Fatalf(`stdout = %q, expected "one two\n"`, output) + externalDiffCommands := [3]string{"diff", "diff -ruN", "diff --report-identical-files"} + + for i, c := range externalDiffCommands { + os.Setenv("KUBECTL_EXTERNAL_DIFF", c) + streams, _, stdout, _ := genericclioptions.NewTestIOStreams() + diff := DiffProgram{ + IOStreams: streams, + Exec: exec.New(), + } + err := diff.Run("/dev/zero", "/dev/zero") + if err != nil { + t.Fatal(err) + } + + // Testing diff --report-identical-files + if i == 2 { + output_msg := "Files /dev/zero and /dev/zero are identical\n" + if output := stdout.String(); output != output_msg { + t.Fatalf(`stdout = %q, expected = %s"`, output, output_msg) + } + } } }