Commit 9f003f7d authored by deads2k's avatar deads2k

allow patch to handle multiple types

parent 9d776d99
...@@ -754,6 +754,7 @@ _kubectl_patch() ...@@ -754,6 +754,7 @@ _kubectl_patch()
flags+=("--patch=") flags+=("--patch=")
two_word_flags+=("-p") two_word_flags+=("-p")
flags+=("--record") flags+=("--record")
flags+=("--type=")
flags+=("--alsologtostderr") flags+=("--alsologtostderr")
flags+=("--api-version=") flags+=("--api-version=")
flags+=("--certificate-authority=") flags+=("--certificate-authority=")
......
...@@ -40,6 +40,10 @@ Please refer to the models in ...@@ -40,6 +40,10 @@ Please refer to the models in
\fB\-\-record\fP=false \fB\-\-record\fP=false
Record current kubectl command in the resource annotation. Record current kubectl command in the resource annotation.
.PP
\fB\-\-type\fP="strategic"
The type of patch being provided; one of [json merge strategic]
.SH OPTIONS INHERITED FROM PARENT COMMANDS .SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP .PP
...@@ -150,6 +154,9 @@ kubectl patch \-f node.json \-p '{"spec":{"unschedulable":true}}' ...@@ -150,6 +154,9 @@ kubectl patch \-f node.json \-p '{"spec":{"unschedulable":true}}'
# Update a container's image; spec.containers[*].name is required because it's a merge key # Update a container's image; spec.containers[*].name is required because it's a merge key
kubectl patch pod valid\-pod \-p '{"spec":{"containers":[{"name":"kubernetes\-serve\-hostname","image":"new image"}]}}' kubectl patch pod valid\-pod \-p '{"spec":{"containers":[{"name":"kubernetes\-serve\-hostname","image":"new image"}]}}'
# Update a container's image using a json patch with positional arrays
kubectl patch pod valid\-pod \-type='json' \-p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'
.fi .fi
.RE .RE
......
...@@ -61,6 +61,9 @@ kubectl patch -f node.json -p '{"spec":{"unschedulable":true}}' ...@@ -61,6 +61,9 @@ kubectl patch -f node.json -p '{"spec":{"unschedulable":true}}'
# Update a container's image; spec.containers[*].name is required because it's a merge key # Update a container's image; spec.containers[*].name is required because it's a merge key
kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}' kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'
# Update a container's image using a json patch with positional arrays
kubectl patch pod valid-pod -type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'
``` ```
### Options ### Options
...@@ -70,6 +73,7 @@ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve ...@@ -70,6 +73,7 @@ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name). -o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
-p, --patch="": The patch to be applied to the resource JSON file. -p, --patch="": The patch to be applied to the resource JSON file.
--record[=false]: Record current kubectl command in the resource annotation. --record[=false]: Record current kubectl command in the resource annotation.
--type="strategic": The type of patch being provided; one of [json merge strategic]
``` ```
### Options inherited from parent commands ### Options inherited from parent commands
...@@ -104,7 +108,7 @@ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve ...@@ -104,7 +108,7 @@ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 22-Jan-2016 ###### Auto generated by spf13/cobra on 12-Feb-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS --> <!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_patch.md?pixel)]() [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_patch.md?pixel)]()
......
...@@ -441,6 +441,14 @@ runTests() { ...@@ -441,6 +441,14 @@ runTests() {
kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]}}' kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]}}'
# Post-condition: valid-pod POD has image nginx # Post-condition: valid-pod POD has image nginx
kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:' kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
# prove that patch can use different types
kubectl patch "${kube_flags[@]}" pod valid-pod --type="json" -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"nginx2"}]'
# Post-condition: valid-pod POD has image nginx
kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx2:'
# prove that patch can use different types
kubectl patch "${kube_flags[@]}" pod valid-pod --type="json" -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"nginx"}]'
# Post-condition: valid-pod POD has image nginx
kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
# prove that yaml input works too # prove that yaml input works too
YAML_PATCH=$'spec:\n containers:\n - name: kubernetes-serve-hostname\n image: changed-with-yaml\n' YAML_PATCH=$'spec:\n containers:\n - name: kubernetes-serve-hostname\n image: changed-with-yaml\n'
kubectl patch "${kube_flags[@]}" pod valid-pod -p="${YAML_PATCH}" kubectl patch "${kube_flags[@]}" pod valid-pod -p="${YAML_PATCH}"
......
...@@ -19,6 +19,7 @@ package cmd ...@@ -19,6 +19,7 @@ package cmd
import ( import (
"fmt" "fmt"
"io" "io"
"strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
...@@ -26,9 +27,12 @@ import ( ...@@ -26,9 +27,12 @@ import (
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/yaml" "k8s.io/kubernetes/pkg/util/yaml"
) )
var patchTypes = map[string]api.PatchType{"json": api.JSONPatchType, "merge": api.MergePatchType, "strategic": api.StrategicMergePatchType}
// PatchOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // PatchOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags() // referencing the cmd.Flags()
type PatchOptions struct { type PatchOptions struct {
...@@ -49,7 +53,10 @@ kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}' ...@@ -49,7 +53,10 @@ kubectl patch node k8s-node-1 -p '{"spec":{"unschedulable":true}}'
kubectl patch -f node.json -p '{"spec":{"unschedulable":true}}' kubectl patch -f node.json -p '{"spec":{"unschedulable":true}}'
# Update a container's image; spec.containers[*].name is required because it's a merge key # Update a container's image; spec.containers[*].name is required because it's a merge key
kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'` kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve-hostname","image":"new image"}]}}'
# Update a container's image using a json patch with positional arrays
kubectl patch pod valid-pod -type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'`
) )
func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command { func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command {
...@@ -69,6 +76,7 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -69,6 +76,7 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command {
} }
cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.") cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.")
cmd.MarkFlagRequired("patch") cmd.MarkFlagRequired("patch")
cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List()))
cmdutil.AddOutputFlagsForMutation(cmd) cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddRecordFlag(cmd) cmdutil.AddRecordFlag(cmd)
...@@ -83,6 +91,16 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri ...@@ -83,6 +91,16 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
return err return err
} }
patchType := api.StrategicMergePatchType
patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type"))
if len(patchTypeString) != 0 {
ok := false
patchType, ok = patchTypes[patchTypeString]
if !ok {
return cmdutil.UsageError(cmd, fmt.Sprintf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), patchTypeString))
}
}
patch := cmdutil.GetFlagString(cmd, "patch") patch := cmdutil.GetFlagString(cmd, "patch")
if len(patch) == 0 { if len(patch) == 0 {
return cmdutil.UsageError(cmd, "Must specify -p to patch") return cmdutil.UsageError(cmd, "Must specify -p to patch")
...@@ -121,7 +139,7 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri ...@@ -121,7 +139,7 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
} }
helper := resource.NewHelper(client, mapping) helper := resource.NewHelper(client, mapping)
_, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) _, err = helper.Patch(namespace, name, patchType, patchBytes)
if err != nil { if err != nil {
return err return err
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment