diff --git a/contrib/completions/bash/kubectl b/contrib/completions/bash/kubectl index d30b21b3eab..3380c2505f7 100644 --- a/contrib/completions/bash/kubectl +++ b/contrib/completions/bash/kubectl @@ -321,9 +321,9 @@ _kubectl_create() must_have_one_noun=() } -_kubectl_update() +_kubectl_replace() { - last_command="kubectl_update" + last_command="kubectl_replace" commands=() flags=() @@ -342,13 +342,11 @@ _kubectl_update() flags+=("--grace-period=") flags+=("--help") flags+=("-h") - flags+=("--patch=") flags+=("--timeout=") must_have_one_flag=() must_have_one_flag+=("--filename=") must_have_one_flag+=("-f") - must_have_one_flag+=("--patch=") must_have_one_noun=() } @@ -906,7 +904,7 @@ _kubectl() commands+=("get") commands+=("describe") commands+=("create") - commands+=("update") + commands+=("replace") commands+=("delete") commands+=("namespace") commands+=("logs") diff --git a/docs/.files_generated b/docs/.files_generated index ea5ef406c64..d0bbd05b491 100644 --- a/docs/.files_generated +++ b/docs/.files_generated @@ -20,9 +20,9 @@ kubectl_logs.md kubectl_namespace.md kubectl_port-forward.md kubectl_proxy.md +kubectl_replace.md kubectl_rolling-update.md kubectl_run.md kubectl_scale.md kubectl_stop.md -kubectl_update.md kubectl_version.md diff --git a/docs/cluster_management.md b/docs/cluster_management.md index bd9b829d57f..ef597f1da00 100644 --- a/docs/cluster_management.md +++ b/docs/cluster_management.md @@ -44,7 +44,7 @@ pods are replicated, upgrades can be done without special coordination. If you want more control over the upgrading process, you may use the following workflow: 1. Mark the node to be rebooted as unschedulable: - `kubectl update nodes $NODENAME --patch='{"apiVersion": "v1", "spec": {"unschedulable": true}}'`. + `kubectl replace nodes $NODENAME --patch='{"apiVersion": "v1", "spec": {"unschedulable": true}}'`. This keeps new pods from landing on the node while you are trying to get them off. 1. Get the pods off the machine, via any of the following strategies: 1. wait for finite-duration pods to complete @@ -53,7 +53,7 @@ If you want more control over the upgrading process, you may use the following w 1. for pods with no replication controller, you need to bring up a new copy of the pod, and assuming it is not part of a service, redirect clients to it. 1. Work on the node 1. Make the node schedulable again: - `kubectl update nodes $NODENAME --patch='{"apiVersion": "v1", "spec": {"unschedulable": false}}'`. + `kubectl replace nodes $NODENAME --patch='{"apiVersion": "v1", "spec": {"unschedulable": false}}'`. If you deleted the node's VM instance and created a new one, then a new schedulable node resource will be created automatically when you create a new VM instance (if you're using a cloud provider that supports node discovery; currently this is only Google Compute Engine, not including CoreOS on Google Compute Engine using kube-register). See [Node](node.md). diff --git a/docs/kubectl.md b/docs/kubectl.md index a06eb863994..8d5fc2b6bbc 100644 --- a/docs/kubectl.md +++ b/docs/kubectl.md @@ -58,13 +58,13 @@ kubectl * [kubectl namespace](kubectl_namespace.md) - SUPERCEDED: Set and view the current Kubernetes namespace * [kubectl port-forward](kubectl_port-forward.md) - Forward one or more local ports to a pod. * [kubectl proxy](kubectl_proxy.md) - Run a proxy to the Kubernetes API server +* [kubectl replace](kubectl_replace.md) - Replace a resource by filename or stdin. * [kubectl rolling-update](kubectl_rolling-update.md) - Perform a rolling update of the given ReplicationController. * [kubectl run](kubectl_run.md) - Run a particular image on the cluster. * [kubectl scale](kubectl_scale.md) - Set a new size for a Replication Controller. * [kubectl stop](kubectl_stop.md) - Gracefully shut down a resource by id or filename. -* [kubectl update](kubectl_update.md) - Update a resource by filename or stdin. * [kubectl version](kubectl_version.md) - Print the client and server version information. -###### Auto generated by spf13/cobra at 2015-05-22 14:24:30.1784975 +0000 UTC +###### Auto generated by spf13/cobra at 2015-06-29 00:10:06.115525904 +0000 UTC [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl.md?pixel)]() diff --git a/docs/kubectl_update.md b/docs/kubectl_replace.md similarity index 61% rename from docs/kubectl_update.md rename to docs/kubectl_replace.md index b3c8ab650a2..4410ecf1ca2 100644 --- a/docs/kubectl_update.md +++ b/docs/kubectl_replace.md @@ -1,44 +1,40 @@ -## kubectl update +## kubectl replace -Update a resource by filename or stdin. +Replace a resource by filename or stdin. ### Synopsis -Update a resource by filename or stdin. +Replace a resource by filename or stdin. JSON and YAML formats are accepted. ``` -kubectl update -f FILENAME +kubectl replace -f FILENAME ``` ### Examples ``` -// Update a pod using the data in pod.json. -$ kubectl update -f pod.json +// Replace a pod using the data in pod.json. +$ kubectl replace -f pod.json -// Update a pod based on the JSON passed into stdin. -$ cat pod.json | kubectl update -f - +// Replace a pod based on the JSON passed into stdin. +$ cat pod.json | kubectl replace -f - -// Partially update a node using strategic merge patch -kubectl --api-version=v1 update node k8s-node-1 --patch='{"spec":{"unschedulable":true}}' - -// Force update, delete and then re-create the resource -kubectl update --force -f pod.json +// Force replace, delete and then re-create the resource +kubectl replace --force -f pod.json ``` ### Options ``` - --cascade=false: Only relevant during a force update. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true. - -f, --filename=[]: Filename, directory, or URL to file to use to update the resource. + --cascade=false: Only relevant during a force replace. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true. + -f, --filename=[]: Filename, directory, or URL to file to use to replace the resource. --force=false: Delete and re-create the specified resource - --grace-period=-1: Only relevant during a force update. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative. - -h, --help=false: help for update - --patch="": A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated. - --timeout=0: Only relevant during a force update. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object + --grace-period=-1: Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative. + -h, --help=false: help for replace + --timeout=0: Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object ``` ### Options inherited from parent commands @@ -73,6 +69,6 @@ kubectl update --force -f pod.json ### SEE ALSO * [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager -###### Auto generated by spf13/cobra at 2015-06-26 00:15:55.835055081 +0000 UTC +###### Auto generated by spf13/cobra at 2015-06-29 00:11:27.040756424 +0000 UTC -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl_update.md?pixel)]() +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl_replace.md?pixel)]() diff --git a/docs/man/man1/.files_generated b/docs/man/man1/.files_generated index 241e191b410..cdadfebb693 100644 --- a/docs/man/man1/.files_generated +++ b/docs/man/man1/.files_generated @@ -19,10 +19,10 @@ kubectl-logs.1 kubectl-namespace.1 kubectl-port-forward.1 kubectl-proxy.1 +kubectl-replace.1 kubectl-rolling-update.1 kubectl-run.1 kubectl-scale.1 kubectl-stop.1 -kubectl-update.1 kubectl-version.1 kubectl.1 diff --git a/docs/man/man1/kubectl-update.1 b/docs/man/man1/kubectl-replace.1 similarity index 68% rename from docs/man/man1/kubectl-update.1 rename to docs/man/man1/kubectl-replace.1 index 3b5632c3dc1..14963e1ef84 100644 --- a/docs/man/man1/kubectl-update.1 +++ b/docs/man/man1/kubectl-replace.1 @@ -3,17 +3,17 @@ .SH NAME .PP -kubectl update \- Update a resource by filename or stdin. +kubectl replace \- Replace a resource by filename or stdin. .SH SYNOPSIS .PP -\fBkubectl update\fP [OPTIONS] +\fBkubectl replace\fP [OPTIONS] .SH DESCRIPTION .PP -Update a resource by filename or stdin. +Replace a resource by filename or stdin. .PP JSON and YAML formats are accepted. @@ -22,11 +22,11 @@ JSON and YAML formats are accepted. .SH OPTIONS .PP \fB\-\-cascade\fP=false - Only relevant during a force update. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true. + Only relevant during a force replace. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true. .PP \fB\-f\fP, \fB\-\-filename\fP=[] - Filename, directory, or URL to file to use to update the resource. + Filename, directory, or URL to file to use to replace the resource. .PP \fB\-\-force\fP=false @@ -34,19 +34,15 @@ JSON and YAML formats are accepted. .PP \fB\-\-grace\-period\fP=\-1 - Only relevant during a force update. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative. + Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative. .PP \fB\-h\fP, \fB\-\-help\fP=false - help for update - -.PP -\fB\-\-patch\fP="" - A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated. + help for replace .PP \fB\-\-timeout\fP=0 - Only relevant during a force update. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object + Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object .SH OPTIONS INHERITED FROM PARENT COMMANDS @@ -152,17 +148,14 @@ JSON and YAML formats are accepted. .RS .nf -// Update a pod using the data in pod.json. -$ kubectl update \-f pod.json +// Replace a pod using the data in pod.json. +$ kubectl replace \-f pod.json -// Update a pod based on the JSON passed into stdin. -$ cat pod.json | kubectl update \-f \- +// Replace a pod based on the JSON passed into stdin. +$ cat pod.json | kubectl replace \-f \- -// Partially update a node using strategic merge patch -kubectl \-\-api\-version=v1 update node k8s\-node\-1 \-\-patch='\{"spec":\{"unschedulable":true\}\}' - -// Force update, delete and then re\-create the resource -kubectl update \-\-force \-f pod.json +// Force replace, delete and then re\-create the resource +kubectl replace \-\-force \-f pod.json .fi .RE diff --git a/docs/man/man1/kubectl.1 b/docs/man/man1/kubectl.1 index 5b92e11e358..1766709b021 100644 --- a/docs/man/man1/kubectl.1 +++ b/docs/man/man1/kubectl.1 @@ -124,7 +124,7 @@ Find more information at .SH SEE ALSO .PP -\fBkubectl\-get(1)\fP, \fBkubectl\-describe(1)\fP, \fBkubectl\-create(1)\fP, \fBkubectl\-update(1)\fP, \fBkubectl\-delete(1)\fP, \fBkubectl\-namespace(1)\fP, \fBkubectl\-logs(1)\fP, \fBkubectl\-rolling\-update(1)\fP, \fBkubectl\-scale(1)\fP, \fBkubectl\-exec(1)\fP, \fBkubectl\-port\-forward(1)\fP, \fBkubectl\-proxy(1)\fP, \fBkubectl\-run(1)\fP, \fBkubectl\-stop(1)\fP, \fBkubectl\-expose(1)\fP, \fBkubectl\-label(1)\fP, \fBkubectl\-config(1)\fP, \fBkubectl\-cluster\-info(1)\fP, \fBkubectl\-api\-versions(1)\fP, \fBkubectl\-version(1)\fP, +\fBkubectl\-get(1)\fP, \fBkubectl\-describe(1)\fP, \fBkubectl\-create(1)\fP, \fBkubectl\-replace(1)\fP, \fBkubectl\-delete(1)\fP, \fBkubectl\-namespace(1)\fP, \fBkubectl\-logs(1)\fP, \fBkubectl\-rolling\-update(1)\fP, \fBkubectl\-scale(1)\fP, \fBkubectl\-exec(1)\fP, \fBkubectl\-port\-forward(1)\fP, \fBkubectl\-proxy(1)\fP, \fBkubectl\-run(1)\fP, \fBkubectl\-stop(1)\fP, \fBkubectl\-expose(1)\fP, \fBkubectl\-label(1)\fP, \fBkubectl\-config(1)\fP, \fBkubectl\-cluster\-info(1)\fP, \fBkubectl\-api\-versions(1)\fP, \fBkubectl\-version(1)\fP, .SH HISTORY diff --git a/docs/node.md b/docs/node.md index bd04ec1e8b2..065168eb85e 100644 --- a/docs/node.md +++ b/docs/node.md @@ -146,7 +146,7 @@ node, but will not affect any existing pods on the node. This is useful as a preparatory step before a node reboot, etc. For example, to mark a node unschedulable, run this command: ``` -kubectl update nodes 10.1.2.3 --patch='{"apiVersion": "v1", "unschedulable": true}' +kubectl replace nodes 10.1.2.3 --patch='{"apiVersion": "v1", "unschedulable": true}' ``` ### Node capacity diff --git a/hack/test-cmd.sh b/hack/test-cmd.sh index 335ccdb5af4..a6766420001 100755 --- a/hack/test-cmd.sh +++ b/hack/test-cmd.sh @@ -377,21 +377,13 @@ for version in "${kube_api_versions[@]}"; do kubectl create -f examples/limitrange/valid-pod.json "${kube_flags[@]}" # Post-condition: valid-pod POD is running kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:' - - ## --patch update pod can change image - # Pre-condition: valid-pod POD is running - kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:' + + ## --force replace pod can change other field, e.g., spec.container.name # Command - kubectl update "${kube_flags[@]}" pod valid-pod --patch='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]}}' - # Post-condition: valid-pod POD has image nginx - kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:' - - ## --force update pod can change other field, e.g., spec.container.name - # Command - kubectl get "${kube_flags[@]}" pod valid-pod -o json | sed 's/"kubernetes-serve-hostname"/"update-k8s-serve-hostname"/g' > tmp-valid-pod.json - kubectl update "${kube_flags[@]}" --force -f tmp-valid-pod.json - # Post-condition: spec.container.name = "update-k8s-serve-hostname" - kube::test::get_object_assert 'pod valid-pod' "{{(index .spec.containers 0).name}}" 'update-k8s-serve-hostname' + kubectl get "${kube_flags[@]}" pod valid-pod -o json | sed 's/"kubernetes-serve-hostname"/"replaced-k8s-serve-hostname"/g' > tmp-valid-pod.json + kubectl replace "${kube_flags[@]}" --force -f tmp-valid-pod.json + # Post-condition: spec.container.name = "replaced-k8s-serve-hostname" + kube::test::get_object_assert 'pod valid-pod' "{{(index .spec.containers 0).name}}" 'replaced-k8s-serve-hostname' ### Overwriting an existing label is not permitted # Pre-condition: name is valid-pod @@ -543,7 +535,7 @@ __EOF__ kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:service-.*-test:' ### Identity - kubectl get service "${kube_flags[@]}" service-${version}-test -o json | kubectl update "${kube_flags[@]}" -f - + kubectl get service "${kube_flags[@]}" service-${version}-test -o json | kubectl replace "${kube_flags[@]}" -f - ### Delete services by id # Pre-condition: redis-master-service service is running @@ -726,16 +718,6 @@ __EOF__ kube::test::describe_object_assert nodes "127.0.0.1" "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:" - ### --patch update can mark node unschedulable - # Pre-condition: node is schedulable - kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '' - kubectl update "${kube_flags[@]}" nodes "127.0.0.1" --patch='{"spec":{"unschedulable":true}}' - # Post-condition: node is unschedulable - kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" 'true' - kubectl update "${kube_flags[@]}" nodes "127.0.0.1" --patch='{"spec":{"unschedulable":null}}' - # Post-condition: node is schedulable - kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '' - ########### # Nodes # ########### diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index c89fe0670df..f14dc63ea81 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -114,7 +114,7 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, cmds.AddCommand(NewCmdGet(f, out)) cmds.AddCommand(NewCmdDescribe(f, out)) cmds.AddCommand(NewCmdCreate(f, out)) - cmds.AddCommand(NewCmdUpdate(f, out)) + cmds.AddCommand(NewCmdReplace(f, out)) cmds.AddCommand(NewCmdDelete(f, out)) cmds.AddCommand(NewCmdNamespace(out)) diff --git a/pkg/kubectl/cmd/label.go b/pkg/kubectl/cmd/label.go index 495607a10e2..a35abcc923f 100644 --- a/pkg/kubectl/cmd/label.go +++ b/pkg/kubectl/cmd/label.go @@ -83,7 +83,7 @@ func updateObject(info *resource.Info, updateFn func(runtime.Object) (runtime.Ob return nil, err } - _, err = helper.Update(info.Namespace, info.Name, true, data) + _, err = helper.Replace(info.Namespace, info.Name, true, data) if err != nil { return nil, err } diff --git a/pkg/kubectl/cmd/update.go b/pkg/kubectl/cmd/replace.go similarity index 52% rename from pkg/kubectl/cmd/update.go rename to pkg/kubectl/cmd/replace.go index 149e8236390..d8489ac4c8d 100644 --- a/pkg/kubectl/cmd/update.go +++ b/pkg/kubectl/cmd/replace.go @@ -19,10 +19,10 @@ package cmd import ( "fmt" "io" + "os" "github.com/spf13/cobra" - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" @@ -31,47 +31,47 @@ import ( ) const ( - update_long = `Update a resource by filename or stdin. + replace_long = `Replace a resource by filename or stdin. JSON and YAML formats are accepted.` - update_example = `// Update a pod using the data in pod.json. -$ kubectl update -f pod.json + replace_example = `// Replace a pod using the data in pod.json. +$ kubectl replace -f pod.json -// Update a pod based on the JSON passed into stdin. -$ cat pod.json | kubectl update -f - +// Replace a pod based on the JSON passed into stdin. +$ cat pod.json | kubectl replace -f - -// Partially update a node using strategic merge patch -kubectl --api-version=v1 update node k8s-node-1 --patch='{"spec":{"unschedulable":true}}' - -// Force update, delete and then re-create the resource -kubectl update --force -f pod.json` +// Force replace, delete and then re-create the resource +kubectl replace --force -f pod.json` ) -func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command { +func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command { var filenames util.StringList cmd := &cobra.Command{ - Use: "update -f FILENAME", - Short: "Update a resource by filename or stdin.", - Long: update_long, - Example: update_example, + Use: "replace -f FILENAME", + // update is deprecated. + Aliases: []string{"update"}, + Short: "Replace a resource by filename or stdin.", + Long: replace_long, + Example: replace_example, Run: func(cmd *cobra.Command, args []string) { - err := RunUpdate(f, out, cmd, args, filenames) - cmdutil.CheckCustomErr("Update failed", err) + err := RunReplace(f, out, cmd, args, filenames) + cmdutil.CheckCustomErr("Replace failed", err) }, } - usage := "Filename, directory, or URL to file to use to update the resource." + usage := "Filename, directory, or URL to file to use to replace the resource." kubectl.AddJsonFilenameFlag(cmd, &filenames, usage) cmd.MarkFlagRequired("filename") - cmd.Flags().String("patch", "", "A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated.") - cmd.MarkFlagRequired("patch") cmd.Flags().Bool("force", false, "Delete and re-create the specified resource") - cmd.Flags().Bool("cascade", false, "Only relevant during a force update. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.") - cmd.Flags().Int("grace-period", -1, "Only relevant during a force update. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.") - cmd.Flags().Duration("timeout", 0, "Only relevant during a force update. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object") + cmd.Flags().Bool("cascade", false, "Only relevant during a force replace. If true, cascade the deletion of the resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.") + cmd.Flags().Int("grace-period", -1, "Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.") + cmd.Flags().Duration("timeout", 0, "Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object") return cmd } -func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error { +func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error { + if os.Args[1] == "update" { + printDeprecationWarning("replace", "update") + } schema, err := f.Validator() if err != nil { return err @@ -83,32 +83,12 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str } force := cmdutil.GetFlagBool(cmd, "force") - patch := cmdutil.GetFlagString(cmd, "patch") - if len(filenames) == 0 && len(patch) == 0 { - return cmdutil.UsageError(cmd, "Must specify --filename or --patch to update") - } - if len(filenames) != 0 && len(patch) != 0 { - return cmdutil.UsageError(cmd, "Can not specify both --filename and --patch") - } - if len(filenames) == 0 && force { - return cmdutil.UsageError(cmd, "--force can only be used with --filename") - } - - // TODO: Make patching work with -f, updating with patched JSON input files if len(filenames) == 0 { - name, err := updateWithPatch(cmd, args, f, patch) - if err != nil { - return err - } - fmt.Fprintf(out, "%s\n", name) - return nil - } - if len(filenames) == 0 { - return cmdutil.UsageError(cmd, "Must specify --filename to update") + return cmdutil.UsageError(cmd, "Must specify --filename to replace") } if force { - return forceUpdate(f, out, cmd, args, filenames) + return forceReplace(f, out, cmd, args, filenames) } mapper, typer := f.Object() @@ -127,11 +107,11 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str return r.Visit(func(info *resource.Info) error { data, err := info.Mapping.Codec.Encode(info.Object) if err != nil { - return cmdutil.AddSourceToErr("updating", info.Source, err) + return cmdutil.AddSourceToErr("replacing", info.Source, err) } - obj, err := resource.NewHelper(info.Client, info.Mapping).Update(info.Namespace, info.Name, true, data) + obj, err := resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, true, data) if err != nil { - return cmdutil.AddSourceToErr("updating", info.Source, err) + return cmdutil.AddSourceToErr("replacing", info.Source, err) } info.Refresh(obj, true) printObjectSpecificMessage(obj, out) @@ -140,44 +120,7 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str }) } -func updateWithPatch(cmd *cobra.Command, args []string, f *cmdutil.Factory, patch string) (string, error) { - cmdNamespace, err := f.DefaultNamespace() - if err != nil { - return "", err - } - - mapper, typer := f.Object() - r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). - ContinueOnError(). - NamespaceParam(cmdNamespace).DefaultNamespace(). - ResourceTypeOrNameArgs(false, args...). - Flatten(). - Do() - err = r.Err() - if err != nil { - return "", err - } - mapping, err := r.ResourceMapping() - if err != nil { - return "", err - } - client, err := f.RESTClient(mapping) - if err != nil { - return "", err - } - - infos, err := r.Infos() - if err != nil { - return "", err - } - name, namespace := infos[0].Name, infos[0].Namespace - - helper := resource.NewHelper(client, mapping) - _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, []byte(patch)) - return name, err -} - -func forceUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error { +func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error { schema, err := f.Validator() if err != nil { return err @@ -200,7 +143,7 @@ func forceUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s if err != nil { return err } - //Update will create a resource if it doesn't exist already, so ignore not found error + //Replace will create a resource if it doesn't exist already, so ignore not found error ignoreNotFound := true // By default use a reaper to delete all related resources. if cmdutil.GetFlagBool(cmd, "cascade") { @@ -245,7 +188,7 @@ func forceUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s return err } if count == 0 { - return fmt.Errorf("no objects passed to update") + return fmt.Errorf("no objects passed to replace") } return nil } diff --git a/pkg/kubectl/cmd/update_test.go b/pkg/kubectl/cmd/replace_test.go similarity index 95% rename from pkg/kubectl/cmd/update_test.go rename to pkg/kubectl/cmd/replace_test.go index b0221295a7c..f8d9c87aa63 100644 --- a/pkg/kubectl/cmd/update_test.go +++ b/pkg/kubectl/cmd/replace_test.go @@ -25,7 +25,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/client" ) -func TestUpdateObject(t *testing.T) { +func TestReplaceObject(t *testing.T) { _, _, rc := testData() f, tf, codec := NewAPIFactory() @@ -47,7 +47,7 @@ func TestUpdateObject(t *testing.T) { tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdUpdate(f, buf) + cmd := NewCmdReplace(f, buf) cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.yaml") cmd.Run(cmd, []string{}) @@ -66,7 +66,7 @@ func TestUpdateObject(t *testing.T) { } } -func TestUpdateMultipleObject(t *testing.T) { +func TestReplaceMultipleObject(t *testing.T) { _, svc, rc := testData() f, tf, codec := NewAPIFactory() @@ -92,7 +92,7 @@ func TestUpdateMultipleObject(t *testing.T) { tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdUpdate(f, buf) + cmd := NewCmdReplace(f, buf) cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.yaml") cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.yaml") cmd.Run(cmd, []string{}) @@ -111,7 +111,7 @@ func TestUpdateMultipleObject(t *testing.T) { } } -func TestUpdateDirectory(t *testing.T) { +func TestReplaceDirectory(t *testing.T) { _, svc, rc := testData() f, tf, codec := NewAPIFactory() @@ -137,7 +137,7 @@ func TestUpdateDirectory(t *testing.T) { tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdUpdate(f, buf) + cmd := NewCmdReplace(f, buf) cmd.Flags().Set("filename", "../../../examples/guestbook") cmd.Flags().Set("namespace", "test") cmd.Run(cmd, []string{}) @@ -157,7 +157,7 @@ func TestUpdateDirectory(t *testing.T) { } } -func TestForceUpdateObjectNotFound(t *testing.T) { +func TestForceReplaceObjectNotFound(t *testing.T) { _, _, rc := testData() f, tf, codec := NewAPIFactory() @@ -179,7 +179,7 @@ func TestForceUpdateObjectNotFound(t *testing.T) { tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) - cmd := NewCmdUpdate(f, buf) + cmd := NewCmdReplace(f, buf) cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.yaml") cmd.Flags().Set("force", "true") cmd.Flags().Set("cascade", "false") diff --git a/pkg/kubectl/resource/helper.go b/pkg/kubectl/resource/helper.go index 3c95c4e0932..f8bffa08b05 100644 --- a/pkg/kubectl/resource/helper.go +++ b/pkg/kubectl/resource/helper.go @@ -143,27 +143,27 @@ func (m *Helper) Patch(namespace, name string, pt api.PatchType, data []byte) (r Get() } -func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) (runtime.Object, error) { +func (m *Helper) Replace(namespace, name string, overwrite bool, data []byte) (runtime.Object, error) { c := m.RESTClient obj, err := m.Codec.Decode(data) if err != nil { - // We don't know how to handle this object, but update it anyway - return m.updateResource(c, m.Resource, namespace, name, data) + // We don't know how to handle this object, but replace it anyway + return m.replaceResource(c, m.Resource, namespace, name, data) } // Attempt to version the object based on client logic. version, err := m.Versioner.ResourceVersion(obj) if err != nil { // We don't know how to version this object, so send it to the server as is - return m.updateResource(c, m.Resource, namespace, name, data) + return m.replaceResource(c, m.Resource, namespace, name, data) } if version == "" && overwrite { // Retrieve the current version of the object to overwrite the server object serverObj, err := c.Get().Namespace(namespace).Resource(m.Resource).Name(name).Do().Get() if err != nil { // The object does not exist, but we want it to be created - return m.updateResource(c, m.Resource, namespace, name, data) + return m.replaceResource(c, m.Resource, namespace, name, data) } serverVersion, err := m.Versioner.ResourceVersion(serverObj) if err != nil { @@ -179,9 +179,9 @@ func (m *Helper) Update(namespace, name string, overwrite bool, data []byte) (ru data = newData } - return m.updateResource(c, m.Resource, namespace, name, data) + return m.replaceResource(c, m.Resource, namespace, name, data) } -func (m *Helper) updateResource(c RESTClient, resource, namespace, name string, data []byte) (runtime.Object, error) { +func (m *Helper) replaceResource(c RESTClient, resource, namespace, name string, data []byte) (runtime.Object, error) { return c.Put().NamespaceIfScoped(namespace, m.NamespaceScoped).Resource(resource).Name(name).Body(data).Do().Get() } diff --git a/pkg/kubectl/resource/helper_test.go b/pkg/kubectl/resource/helper_test.go index 1c9d1aab96b..9d4e0039609 100644 --- a/pkg/kubectl/resource/helper_test.go +++ b/pkg/kubectl/resource/helper_test.go @@ -363,7 +363,7 @@ func TestHelperList(t *testing.T) { } } -func TestHelperUpdate(t *testing.T) { +func TestHelperReplace(t *testing.T) { expectPut := func(req *http.Request) bool { if req.Method != "PUT" { t.Errorf("unexpected method: %#v", req) @@ -457,7 +457,7 @@ func TestHelperUpdate(t *testing.T) { if test.Object != nil { data = []byte(runtime.EncodeOrDie(testapi.Codec(), test.Object)) } - _, err := modifier.Update("bar", "foo", test.Overwrite, data) + _, err := modifier.Replace("bar", "foo", test.Overwrite, data) if (err != nil) != test.Err { t.Errorf("%d: unexpected error: %t %v", i, test.Err, err) }