From b9c1fc6f3c292e00757f7ba2cff153600abd27e2 Mon Sep 17 00:00:00 2001 From: Timo Reimann Date: Fri, 2 Mar 2018 01:19:51 +0100 Subject: [PATCH] Support --dry-run in kubectl patch command. --- pkg/kubectl/cmd/patch.go | 48 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/pkg/kubectl/cmd/patch.go b/pkg/kubectl/cmd/patch.go index fd0b3adebb3..0612048824a 100644 --- a/pkg/kubectl/cmd/patch.go +++ b/pkg/kubectl/cmd/patch.go @@ -30,7 +30,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" - "k8s.io/apimachinery/pkg/util/json" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/strategicpatch" "k8s.io/apimachinery/pkg/util/yaml" @@ -49,7 +48,8 @@ var patchTypes = map[string]types.PatchType{"json": types.JSONPatchType, "merge" type PatchOptions struct { resource.FilenameOptions - Local bool + Local bool + DryRun bool OutputFormat string } @@ -91,6 +91,7 @@ func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command { Example: patchExample, Run: func(cmd *cobra.Command, args []string) { options.OutputFormat = cmdutil.GetFlagString(cmd, "output") + options.DryRun = cmdutil.GetFlagBool(cmd, "dry-run") err := RunPatch(f, out, cmd, args, options) cmdutil.CheckErr(err) }, @@ -102,6 +103,7 @@ func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command { cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List())) cmdutil.AddPrinterFlags(cmd) cmdutil.AddRecordFlag(cmd) + cmdutil.AddDryRunFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) usage := "identifying the resource to update" @@ -168,9 +170,7 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin return err } - if !options.Local { - dataChangedMsg := "not patched" - didPatch := false + if !options.Local && !options.DryRun { helper := resource.NewHelper(client, mapping) patchedObj, err := helper.Patch(namespace, name, patchType, patchBytes) if err != nil { @@ -191,18 +191,7 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin } count++ - oldData, err := json.Marshal(info.Object) - if err != nil { - return err - } - newData, err := json.Marshal(patchedObj) - if err != nil { - return err - } - if !reflect.DeepEqual(oldData, newData) { - didPatch = true - dataChangedMsg = "patched" - } + didPatch := !reflect.DeepEqual(info.Object, patchedObj) // After computing whether we changed data, refresh the resource info with the resulting object if err := info.Refresh(patchedObj, true); err != nil { @@ -212,7 +201,7 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin if len(options.OutputFormat) > 0 && options.OutputFormat != "name" { return cmdutil.PrintObject(cmd, info.Object, out) } - cmdutil.PrintSuccess(options.OutputFormat == "name", out, info.Object, false, dataChangedMsg) + cmdutil.PrintSuccess(options.OutputFormat == "name", out, info.Object, false, patchOperation(didPatch)) // if object was not successfully patched, exit with error code 1 if !didPatch { @@ -239,14 +228,24 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin return err } + didPatch := !reflect.DeepEqual(info.Object, targetObj) + // TODO: if we ever want to go generic, this allows a clean -o yaml without trying to print columns or anything // rawExtension := &runtime.Unknown{ // Raw: originalPatchedObjJS, // } - if err := info.Refresh(targetObj, true); err != nil { - return err + if didPatch { + if err := info.Refresh(targetObj, true); err != nil { + return err + } } - return cmdutil.PrintObject(cmd, info.Object, out) + + if len(options.OutputFormat) > 0 && options.OutputFormat != "name" { + return cmdutil.PrintObject(cmd, info.Object, out) + } + + cmdutil.PrintSuccess(options.OutputFormat == "name", out, info.Object, options.DryRun, patchOperation(didPatch)) + return nil }) if err != nil { return err @@ -282,3 +281,10 @@ func getPatchedJSON(patchType types.PatchType, originalJS, patchJS []byte, gvk s return nil, fmt.Errorf("unknown Content-Type header for patch: %v", patchType) } } + +func patchOperation(didPatch bool) string { + if didPatch { + return "patched" + } + return "not patched" +}