mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 23:15:14 +00:00
Add command "kubectl replace". "kubectl update" is still supported as an alias.
"kubectl replace --patch" is NOT supported. It's moved to "kubectl patch" as a separate command in another commit.
This commit is contained in:
parent
ad12c98e6d
commit
9b3d42c090
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
|
||||
[]()
|
||||
|
@ -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
|
||||
|
||||
[]()
|
||||
[]()
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -528,7 +520,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
|
||||
@ -711,16 +703,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}}" '<no value>'
|
||||
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}}" '<no value>'
|
||||
|
||||
###########
|
||||
# Nodes #
|
||||
###########
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -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")
|
@ -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()
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user