Merge pull request #21099 from deads2k/extend-patch

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2016-02-15 14:49:02 -08:00
commit 47acbd62ec
5 changed files with 41 additions and 3 deletions

View File

@ -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=")

View File

@ -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}}'
# 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

View File

@ -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
-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
* [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)]()

View File

@ -461,6 +461,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}"

View File

@ -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 (
"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}}'
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 {
} }
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
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
} }
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
} }