Skip to content

Commit e94ef4d

Browse files
Support custom diff commands
1 parent bb7b4a7 commit e94ef4d

File tree

6 files changed

+60
-14
lines changed

6 files changed

+60
-14
lines changed

cmd/kubeapply/subcmd/diff.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ func execDiff(
223223
ctx,
224224
clusterConfig.AbsSubpaths(),
225225
clusterConfig.ServerSideApply,
226+
"",
226227
)
227228
return results, "", err
228229
}

pkg/cluster/client.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,15 @@ type ClusterClient interface {
2929

3030
// Diff gets the diffs between the configs at the given path and the actual state of resources
3131
// in the cluster.
32-
DiffStructured(ctx context.Context, paths []string, serverSide bool) ([]diff.Result, error)
32+
//
33+
// The diffCommand argument can be set to use a custom diff command in place of the default
34+
// (kubeapply kdiff).
35+
DiffStructured(
36+
ctx context.Context,
37+
paths []string,
38+
serverSide bool,
39+
diffCommand string,
40+
) ([]diff.Result, error)
3341

3442
// Summary returns a summary of all workloads in the cluster.
3543
Summary(ctx context.Context) (string, error)

pkg/cluster/fake_client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ func (cc *FakeClusterClient) DiffStructured(
103103
ctx context.Context,
104104
paths []string,
105105
serverSide bool,
106+
diffCommand string,
106107
) ([]diff.Result, error) {
107108
return []diff.Result{
108109
{

pkg/cluster/kube/ordered_client.go

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"os/exec"
1111
"path/filepath"
1212
"regexp"
13+
"strings"
1314

1415
"github.com/briandowns/spinner"
1516
"github.com/segmentio/kubeapply/data"
@@ -18,8 +19,22 @@ import (
1819
)
1920

2021
const (
21-
structuredDiffScript = "kdiff-wrapper.sh"
22-
rawDiffScript = "raw-diff.sh"
22+
rawDiffScript = `#!/bin/bash
23+
24+
diff -u -N $1 $2
25+
26+
# Ensure that we only exit with non-zero status is there was a real error
27+
if [[ $? -gt 1 ]]; then
28+
exit 1
29+
fi`
30+
31+
structuredDiffScript = `#!/bin/bash
32+
33+
# This is used as the custom differ for kubectl diff. We need a wrapper script instead
34+
# of calling 'kubeapply kdiff' directly because kubectl wants a single executable (without
35+
# any subcommands or arguments).
36+
37+
kubeapply kdiff $1 $2`
2338
)
2439

2540
// TODO: Switch to a YAML library that supports doing this splitting for us.
@@ -149,10 +164,9 @@ func (k *OrderedClient) Diff(
149164
ctx context.Context,
150165
configPaths []string,
151166
structured bool,
167+
diffCommand string,
152168
spinner *spinner.Spinner,
153169
) ([]byte, error) {
154-
var diffCmd string
155-
156170
tempDir, err := ioutil.TempDir("", "diff")
157171
if err != nil {
158172
return nil, err
@@ -184,18 +198,36 @@ func (k *OrderedClient) Diff(
184198
}
185199

186200
envVars := []string{}
187-
var diffScript string
201+
var diffScriptBody string
188202

189203
if structured {
190-
diffScript = structuredDiffScript
204+
if diffCommand == "" {
205+
diffScriptBody = structuredDiffScript
206+
} else {
207+
diffScriptBody = strings.Replace(
208+
structuredDiffScript,
209+
"kubeapply kdiff",
210+
diffCommand,
211+
-1,
212+
)
213+
}
191214
} else {
192-
diffScript = rawDiffScript
215+
if diffCommand == "" {
216+
diffScriptBody = rawDiffScript
217+
} else {
218+
diffScriptBody = strings.Replace(
219+
rawDiffScript,
220+
"diff",
221+
diffCommand,
222+
-1,
223+
)
224+
}
193225
}
194226

195-
diffCmd = filepath.Join(tempDir, diffScript)
227+
kubectlDiffCmd := filepath.Join(tempDir, "diff.sh")
196228
err = ioutil.WriteFile(
197-
diffCmd,
198-
data.MustAsset(fmt.Sprintf("scripts/%s", diffScript)),
229+
kubectlDiffCmd,
230+
[]byte(diffScriptBody),
199231
0755,
200232
)
201233
if err != nil {
@@ -204,7 +236,7 @@ func (k *OrderedClient) Diff(
204236

205237
envVars = append(
206238
envVars,
207-
fmt.Sprintf("KUBECTL_EXTERNAL_DIFF=%s", diffCmd),
239+
fmt.Sprintf("KUBECTL_EXTERNAL_DIFF=%s", kubectlDiffCmd),
208240
)
209241

210242
return runKubectlOutput(

pkg/cluster/kube_client.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ func (cc *KubeClusterClient) Diff(
211211
paths []string,
212212
serverSide bool,
213213
) ([]byte, error) {
214-
rawResults, err := cc.execDiff(ctx, paths, false)
214+
rawResults, err := cc.execDiff(ctx, paths, false, "")
215215
if err != nil {
216216
return nil, fmt.Errorf(
217217
"Error running diff: %+v (output: %s)",
@@ -229,8 +229,9 @@ func (cc *KubeClusterClient) DiffStructured(
229229
ctx context.Context,
230230
paths []string,
231231
serverSide bool,
232+
diffCommand string,
232233
) ([]diff.Result, error) {
233-
rawResults, err := cc.execDiff(ctx, paths, true)
234+
rawResults, err := cc.execDiff(ctx, paths, true, diffCommand)
234235
if err != nil {
235236
return nil, fmt.Errorf(
236237
"Error running diff: %+v (output: %s)",
@@ -351,6 +352,7 @@ func (cc *KubeClusterClient) execDiff(
351352
ctx context.Context,
352353
paths []string,
353354
structured bool,
355+
diffCommand string,
354356
) ([]byte, error) {
355357
if cc.useLocks {
356358
acquireCtx, cancel := context.WithTimeout(ctx, lockAcquistionTimeout)
@@ -378,6 +380,7 @@ func (cc *KubeClusterClient) execDiff(
378380
ctx,
379381
paths,
380382
structured,
383+
diffCommand,
381384
cc.spinnerObj,
382385
)
383386
if err != nil || !cc.checkApplyConsistency {

pkg/events/handler.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ func (whh *WebhookHandler) runDiffs(
578578
diffCtx,
579579
clusterClient.Config().AbsSubpaths(),
580580
clusterClient.Config().ServerSideApply,
581+
"",
581582
)
582583
if err != nil {
583584
diffErr = fmt.Errorf(

0 commit comments

Comments
 (0)