Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --force to kubectl update #10358

Merged
merged 1 commit into from
Jun 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions contrib/completions/bash/kubectl
Original file line number Diff line number Diff line change
Expand Up @@ -331,15 +331,19 @@ _kubectl_update()
flags_with_completion=()
flags_completion=()

flags+=("--cascade")
flags+=("--filename=")
flags_with_completion+=("--filename")
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
two_word_flags+=("-f")
flags_with_completion+=("-f")
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
flags+=("--force")
flags+=("--grace-period=")
flags+=("--help")
flags+=("-h")
flags+=("--patch=")
flags+=("--timeout=")

must_have_one_flag=()
must_have_one_flag+=("--filename=")
Expand Down
4 changes: 2 additions & 2 deletions docs/kubectl_delete.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ $ kubectl delete pods --all

```
--all=false: [-all] to select all the specified resources.
--cascade=true: If true, cascade the delete resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.
--cascade=true: 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 a file containing the resource to delete.
--grace-period=-1: Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.
-h, --help=false: help for delete
Expand Down Expand Up @@ -84,6 +84,6 @@ $ kubectl delete pods --all
### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra at 2015-06-03 18:21:01.053120485 +0000 UTC
###### Auto generated by spf13/cobra at 2015-06-26 00:15:55.835198432 +0000 UTC

[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl_delete.md?pixel)]()
9 changes: 8 additions & 1 deletion docs/kubectl_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,21 @@ $ cat pod.json | kubectl update -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
```

### 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.
--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
```

### Options inherited from parent commands
Expand Down Expand Up @@ -66,6 +73,6 @@ kubectl --api-version=v1 update node k8s-node-1 --patch='{"spec":{"unschedulable
### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra at 2015-06-18 19:03:00.935576604 +0000 UTC
###### Auto generated by spf13/cobra at 2015-06-26 00:15:55.835055081 +0000 UTC

[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/kubectl_update.md?pixel)]()
2 changes: 1 addition & 1 deletion docs/man/man1/kubectl-delete.1
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ will be lost along with the rest of the resource.

.PP
\fB\-\-cascade\fP=true
If true, cascade the delete resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.
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=[]
Expand Down
19 changes: 19 additions & 0 deletions docs/man/man1/kubectl-update.1
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,22 @@ 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.

.PP
\fB\-f\fP, \fB\-\-filename\fP=[]
Filename, directory, or URL to file to use to update the resource.

.PP
\fB\-\-force\fP=false
Delete and re\-create the specified resource

.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.

.PP
\fB\-h\fP, \fB\-\-help\fP=false
help for update
Expand All @@ -32,6 +44,10 @@ JSON and YAML formats are accepted.
\fB\-\-patch\fP=""
A JSON document to override the existing resource. The resource is downloaded, patched with the JSON, then updated.

.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


.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
Expand Down Expand Up @@ -145,6 +161,9 @@ $ cat pod.json | kubectl update \-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

.fi
.RE

Expand Down
7 changes: 7 additions & 0 deletions hack/test-cmd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,13 @@ for version in "${kube_api_versions[@]}"; do
# 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'

### Overwriting an existing label is not permitted
# Pre-condition: name is valid-pod
kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
Expand Down
2 changes: 1 addition & 1 deletion pkg/kubectl/cmd/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on.")
cmd.Flags().Bool("all", false, "[-all] to select all the specified resources.")
cmd.Flags().Bool("ignore-not-found", false, "Treat \"resource not found\" as a successful delete.")
cmd.Flags().Bool("cascade", true, "If true, cascade the delete resources managed by this resource (e.g. Pods created by a ReplicationController). Default true.")
cmd.Flags().Bool("cascade", true, "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, "Period of time in seconds given to the resource to terminate gracefully. Ignored if negative.")
cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a delete, zero means determine a timeout from the size of the object")
return cmd
Expand Down
91 changes: 90 additions & 1 deletion pkg/kubectl/cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/golang/glog"
)

const (
Expand All @@ -40,7 +41,10 @@ $ kubectl update -f pod.json
$ cat pod.json | kubectl update -f -

// Partially update a node using strategic merge patch
kubectl --api-version=v1 update node k8s-node-1 --patch='{"spec":{"unschedulable":true}}'`
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`
)

func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
Expand All @@ -60,6 +64,10 @@ func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
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")
return cmd
}

Expand All @@ -74,13 +82,17 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
return err
}

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 {
Expand All @@ -95,6 +107,10 @@ func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
return cmdutil.UsageError(cmd, "Must specify --filename to update")
}

if force {
return forceUpdate(f, out, cmd, args, filenames)
}

mapper, typer := f.Object()
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
Schema(schema).
Expand Down Expand Up @@ -160,3 +176,76 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *cmdutil.Factory, patc
_, 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 {
schema, err := f.Validator()
if err != nil {
return err
}

cmdNamespace, err := f.DefaultNamespace()
if err != nil {
return err
}

mapper, typer := f.Object()
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(filenames...).
ResourceTypeOrNameArgs(false, args...).RequireObject(false).
Flatten().
Do()
err = r.Err()
if err != nil {
return err
}
//Update 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") {
glog.Warningf("\"cascade\" is set, kubectl will delete and re-create all resources managed by this resource (e.g. Pods created by a ReplicationController). Consider using \"kubectl rolling-update\" if you want to update a ReplicationController together with its Pods.")
err = ReapResult(r, f, out, cmdutil.GetFlagBool(cmd, "cascade"), ignoreNotFound, cmdutil.GetFlagDuration(cmd, "timeout"), cmdutil.GetFlagInt(cmd, "grace-period"))
} else {
err = DeleteResult(r, out, ignoreNotFound)
}
if err != nil {
return err
}

r = resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
Schema(schema).
ContinueOnError().
NamespaceParam(cmdNamespace).RequireNamespace().
FilenameParam(filenames...).
Flatten().
Do()
err = r.Err()
if err != nil {
return err
}

count := 0
err = r.Visit(func(info *resource.Info) error {
data, err := info.Mapping.Codec.Encode(info.Object)
if err != nil {
return err
}
obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, data)
if err != nil {
return err
}
count++
info.Refresh(obj, true)
printObjectSpecificMessage(obj, out)
fmt.Fprintf(out, "%s/%s\n", info.Mapping.Resource, info.Name)
return nil
})
if err != nil {
return err
}
if count == 0 {
return fmt.Errorf("no objects passed to update")
}
return nil
}