mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
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:
commit
fba61b050a
@ -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"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user