mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-26 05:03:09 +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"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/json"
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||||
"k8s.io/apimachinery/pkg/util/yaml"
|
"k8s.io/apimachinery/pkg/util/yaml"
|
||||||
@ -50,6 +49,7 @@ type PatchOptions struct {
|
|||||||
resource.FilenameOptions
|
resource.FilenameOptions
|
||||||
|
|
||||||
Local bool
|
Local bool
|
||||||
|
DryRun bool
|
||||||
|
|
||||||
OutputFormat string
|
OutputFormat string
|
||||||
}
|
}
|
||||||
@ -91,6 +91,7 @@ func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||||||
Example: patchExample,
|
Example: patchExample,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
options.OutputFormat = cmdutil.GetFlagString(cmd, "output")
|
options.OutputFormat = cmdutil.GetFlagString(cmd, "output")
|
||||||
|
options.DryRun = cmdutil.GetFlagBool(cmd, "dry-run")
|
||||||
err := RunPatch(f, out, cmd, args, options)
|
err := RunPatch(f, out, cmd, args, options)
|
||||||
cmdutil.CheckErr(err)
|
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()))
|
cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List()))
|
||||||
cmdutil.AddPrinterFlags(cmd)
|
cmdutil.AddPrinterFlags(cmd)
|
||||||
cmdutil.AddRecordFlag(cmd)
|
cmdutil.AddRecordFlag(cmd)
|
||||||
|
cmdutil.AddDryRunFlag(cmd)
|
||||||
cmdutil.AddInclude3rdPartyFlags(cmd)
|
cmdutil.AddInclude3rdPartyFlags(cmd)
|
||||||
|
|
||||||
usage := "identifying the resource to update"
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !options.Local {
|
if !options.Local && !options.DryRun {
|
||||||
dataChangedMsg := "not patched"
|
|
||||||
didPatch := false
|
|
||||||
helper := resource.NewHelper(client, mapping)
|
helper := resource.NewHelper(client, mapping)
|
||||||
patchedObj, err := helper.Patch(namespace, name, patchType, patchBytes)
|
patchedObj, err := helper.Patch(namespace, name, patchType, patchBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -191,18 +191,7 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin
|
|||||||
}
|
}
|
||||||
count++
|
count++
|
||||||
|
|
||||||
oldData, err := json.Marshal(info.Object)
|
didPatch := !reflect.DeepEqual(info.Object, patchedObj)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
newData, err := json.Marshal(patchedObj)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(oldData, newData) {
|
|
||||||
didPatch = true
|
|
||||||
dataChangedMsg = "patched"
|
|
||||||
}
|
|
||||||
|
|
||||||
// After computing whether we changed data, refresh the resource info with the resulting object
|
// After computing whether we changed data, refresh the resource info with the resulting object
|
||||||
if err := info.Refresh(patchedObj, true); err != nil {
|
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" {
|
if len(options.OutputFormat) > 0 && options.OutputFormat != "name" {
|
||||||
return cmdutil.PrintObject(cmd, info.Object, out)
|
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 object was not successfully patched, exit with error code 1
|
||||||
if !didPatch {
|
if !didPatch {
|
||||||
@ -239,14 +228,24 @@ func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin
|
|||||||
return err
|
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
|
// TODO: if we ever want to go generic, this allows a clean -o yaml without trying to print columns or anything
|
||||||
// rawExtension := &runtime.Unknown{
|
// rawExtension := &runtime.Unknown{
|
||||||
// Raw: originalPatchedObjJS,
|
// Raw: originalPatchedObjJS,
|
||||||
// }
|
// }
|
||||||
|
if didPatch {
|
||||||
if err := info.Refresh(targetObj, true); err != nil {
|
if err := info.Refresh(targetObj, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(options.OutputFormat) > 0 && options.OutputFormat != "name" {
|
||||||
return cmdutil.PrintObject(cmd, info.Object, out)
|
return cmdutil.PrintObject(cmd, info.Object, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdutil.PrintSuccess(options.OutputFormat == "name", out, info.Object, options.DryRun, patchOperation(didPatch))
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
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