Merge pull request #60675 from timoreimann/support-dry-run-in-kubectl-patch

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Add support for --dry-run to kubectl patch.

**What this PR does / why we need it**:

Add support for the `--dry-run` flag to `kubectl patch`. This is helpful to be able to preview patches prior to applying them.

**Which issue(s) this PR fixes**:
Refs #11488

**Special notes for your reviewer**:

This PR carries #45712.

**Release note**:
```release-note
`kubectl patch` now supports `--dry-run`.
```
This commit is contained in:
Kubernetes Submit Queue 2018-03-25 12:24:08 -07:00 committed by GitHub
commit fba61b050a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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"
}