Set field manager for kubectl diff --server-side.

Bonus: check diff only dry-runs without persisting.

Co-authored-by: Takahiro HATORI <tahatori@zlab.co.jp>
This commit is contained in:
Julian V. Modesto 2020-03-02 14:06:50 -05:00 committed by Julian V. Modesto
parent e865c0b219
commit bacc2c4960
2 changed files with 16 additions and 3 deletions

View File

@ -57,7 +57,7 @@ var (
KUBECTL_EXTERNAL_DIFF environment variable can be used to select your own 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. By default, the "diff" command available in your path will be
run with "-u" (unified diff) and "-N" (treat absent files as empty) options. run with "-u" (unified diff) and "-N" (treat absent files as empty) options.
Exit status: Exit status:
0 0
No differences were found. No differences were found.
@ -92,6 +92,7 @@ type DiffOptions struct {
FilenameOptions resource.FilenameOptions FilenameOptions resource.FilenameOptions
ServerSideApply bool ServerSideApply bool
FieldManager string
ForceConflicts bool ForceConflicts bool
OpenAPISchema openapi.Resources OpenAPISchema openapi.Resources
@ -296,6 +297,7 @@ type InfoObject struct {
OpenAPI openapi.Resources OpenAPI openapi.Resources
Force bool Force bool
ServerSideApply bool ServerSideApply bool
FieldManager string
ForceConflicts bool ForceConflicts bool
genericclioptions.IOStreams genericclioptions.IOStreams
} }
@ -316,8 +318,9 @@ func (obj InfoObject) Merged() (runtime.Object, error) {
return nil, err return nil, err
} }
options := metav1.PatchOptions{ options := metav1.PatchOptions{
Force: &obj.ForceConflicts, Force: &obj.ForceConflicts,
DryRun: []string{metav1.DryRunAll}, FieldManager: obj.FieldManager,
DryRun: []string{metav1.DryRunAll},
} }
return resource.NewHelper(obj.Info.Client, obj.Info.Mapping).Patch( return resource.NewHelper(obj.Info.Client, obj.Info.Mapping).Patch(
obj.Info.Namespace, obj.Info.Namespace,
@ -441,6 +444,7 @@ func (o *DiffOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
} }
o.ServerSideApply = cmdutil.GetServerSideApplyFlag(cmd) o.ServerSideApply = cmdutil.GetServerSideApplyFlag(cmd)
o.FieldManager = cmdutil.GetFieldManagerFlag(cmd)
o.ForceConflicts = cmdutil.GetForceConflictsFlag(cmd) o.ForceConflicts = cmdutil.GetForceConflictsFlag(cmd)
if o.ForceConflicts && !o.ServerSideApply { if o.ForceConflicts && !o.ServerSideApply {
return fmt.Errorf("--force-conflicts only works with --server-side") return fmt.Errorf("--force-conflicts only works with --server-side")
@ -529,6 +533,7 @@ func (o *DiffOptions) Run() error {
OpenAPI: o.OpenAPISchema, OpenAPI: o.OpenAPISchema,
Force: force, Force: force,
ServerSideApply: o.ServerSideApply, ServerSideApply: o.ServerSideApply,
FieldManager: o.FieldManager,
ForceConflicts: o.ForceConflicts, ForceConflicts: o.ForceConflicts,
IOStreams: o.Diff.IOStreams, IOStreams: o.Diff.IOStreams,
} }

View File

@ -29,8 +29,11 @@ run_kubectl_diff_tests() {
# Test that it works when the live object doesn't exist # Test that it works when the live object doesn't exist
output_message=$(! kubectl diff -f hack/testdata/pod.yaml) output_message=$(! kubectl diff -f hack/testdata/pod.yaml)
kube::test::if_has_string "${output_message}" 'test-pod' kube::test::if_has_string "${output_message}" 'test-pod'
# Ensure diff only dry-runs and doesn't persist change
kube::test::get_object_assert 'pod' "{{range.items}}{{ if eq ${id_field:?} \\\"test-pod\\\" }}found{{end}}{{end}}:" ':'
kubectl apply -f hack/testdata/pod.yaml kubectl apply -f hack/testdata/pod.yaml
kube::test::get_object_assert 'pod' "{{range.items}}{{ if eq ${id_field:?} \\\"test-pod\\\" }}found{{end}}{{end}}:" 'found:'
# Make sure that diffing the resource right after returns nothing (0 exit code). # Make sure that diffing the resource right after returns nothing (0 exit code).
kubectl diff -f hack/testdata/pod.yaml kubectl diff -f hack/testdata/pod.yaml
@ -41,6 +44,11 @@ run_kubectl_diff_tests() {
output_message=$(kubectl diff -f hack/testdata/pod-changed.yaml || test $? -eq 1) output_message=$(kubectl diff -f hack/testdata/pod-changed.yaml || test $? -eq 1)
kube::test::if_has_string "${output_message}" 'k8s.gcr.io/pause:3.0' kube::test::if_has_string "${output_message}" 'k8s.gcr.io/pause:3.0'
# Test found diff with server-side apply
kubectl apply -f hack/testdata/pod.yaml
output_message=$(kubectl diff -f hack/testdata/pod-changed.yaml --server-side --force-conflicts || test $? -eq 1)
kube::test::if_has_string "${output_message}" 'k8s.gcr.io/pause:3.0'
# Test that we have a return code bigger than 1 if there is an error when diffing # Test that we have a return code bigger than 1 if there is an error when diffing
kubectl diff -f hack/testdata/invalid-pod.yaml || test $? -gt 1 kubectl diff -f hack/testdata/invalid-pod.yaml || test $? -gt 1