Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Use KUBECTL_EXTERNAL_DIFF for static diffs #558

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions pkg/kubernetes/util/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ func DiffName(m manifest.Manifest) string {
), "/", "-", -1)
}

// DiffStr computes the differences between the strings `is` and `should` using the
// UNIX `diff(1)` utility.
// DiffStr computes the differences between the strings `is` and `should` using diff
// command specified in `KUBECTL_EXTERNAL_DIFF` (if set) or the UNIX `diff(1)` utility.
func DiffStr(name, is, should string) (string, error) {
dir, err := ioutil.TempDir("", "diff")
if err != nil {
Expand All @@ -40,10 +40,13 @@ func DiffStr(name, is, should string) (string, error) {
}

buf := bytes.Buffer{}
errBuf := bytes.Buffer{}
merged := filepath.Join(dir, "MERGED-"+name)
live := filepath.Join(dir, "LIVE-"+name)
cmd := exec.Command("diff", "-u", "-N", live, merged)
command, args := diffCommand(live, merged)
cmd := exec.Command(command, args...)
cmd.Stdout = &buf
cmd.Stderr = &errBuf
err = cmd.Run()

// the diff utility exits with `1` if there are differences. We need to not fail there.
Expand All @@ -52,15 +55,48 @@ func DiffStr(name, is, should string) (string, error) {
return "", err
}
}

out := buf.String()
if out != "" {
out = fmt.Sprintf("diff -u -N %s %s\n%s", live, merged, out)
out = fmt.Sprintf("%s %s\n%s", command, strings.Join(args, " "), out)
}
errOut := errBuf.String()
if errOut != "" {
out += fmt.Sprintf("%s %s\n%s", command, strings.Join(args, " "), errOut)
}

return out, nil
}

// diffCommand returns command and arguments to run to compute differences between
// `live` and `merged` files.
// If set, env variable `KUBECTL_EXTERNAL_DIFF` is used. By default, "diff -u -N" is used.
// For consistency, we want to process KUBECTL_EXTERNAL_DIFF just like kubectl does.
// diffComand was adapted from this kubectl function:
// https://github.com/kubernetes/kubectl/blob/ac49920c0ccb0dd0899d5300fc43713ee2dfcdc9/pkg/cmd/diff/diff.go#L173
func diffCommand(live, merged string) (string, []string) {
diff := ""
args := []string{live, merged}
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...)
}
return diff, args
}

// Diffstat uses `diffstat(1)` utility to summarize a `diff(1)` output
func Diffstat(d string) (*string, error) {
cmd := exec.Command("diffstat", "-C")
Expand Down
7 changes: 6 additions & 1 deletion pkg/tanka/prune.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ func Prune(baseDir string, opts PruneOpts) error {
// here
return err
}
fmt.Print(term.Colordiff(*diff).String())
// in case of non-fatal error diff may be nil
if diff != nil {
fmt.Print(term.Colordiff(*diff).String())
} else {
fmt.Print("<no error but also no diff - this should not happen>\n")
}

// print namespace removal warning
namespaces := []string{}
Expand Down