Merge pull request #19946 from janetkuo/kubectl-rollout-status

Automatic merge from submit-queue

Add `kubectl rollout status`

## Pull Request Guidelines

1. Please read our [contributor guidelines](https://github.com/kubernetes/kubernetes/blob/master/CONTRIBUTING.md).
1. See our [developer guide](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/development.md).
1. Follow the instructions for [labeling and writing a release note for this PR](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/pull-requests.md#release-notes) in the block below.

```release-note
Implement `kubectl rollout status` that can be used to watch a deployment's rollout status
```

Addresses #17168; depends on #19882 (the "Add kubectl rollout" commit).
See [proposal](https://github.com/kubernetes/kubernetes/blob/master/docs/proposals/deploy.md#deployment-version). 

cc @bgrant0607 @nikhiljindal @ironcladlou @kargakis @kubernetes/sig-config @kubernetes/kubectl  @madhusudancs

<!-- Reviewable:start -->
---
This change is [<img src="http://reviewable.k8s.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](http://reviewable.k8s.io/reviews/kubernetes/kubernetes/19946)
<!-- Reviewable:end -->
pull/6/head
k8s-merge-robot 2016-05-12 06:28:49 -07:00
commit 0c2641d4ea
17 changed files with 514 additions and 8 deletions

View File

@ -48,6 +48,7 @@ docs/man/man1/kubectl-rolling-update.1
docs/man/man1/kubectl-rollout-history.1
docs/man/man1/kubectl-rollout-pause.1
docs/man/man1/kubectl-rollout-resume.1
docs/man/man1/kubectl-rollout-status.1
docs/man/man1/kubectl-rollout-undo.1
docs/man/man1/kubectl-rollout.1
docs/man/man1/kubectl-run.1
@ -102,6 +103,7 @@ docs/user-guide/kubectl/kubectl_rollout.md
docs/user-guide/kubectl/kubectl_rollout_history.md
docs/user-guide/kubectl/kubectl_rollout_pause.md
docs/user-guide/kubectl/kubectl_rollout_resume.md
docs/user-guide/kubectl/kubectl_rollout_status.md
docs/user-guide/kubectl/kubectl_rollout_undo.md
docs/user-guide/kubectl/kubectl_run.md
docs/user-guide/kubectl/kubectl_scale.md

View File

@ -2603,6 +2603,57 @@ _kubectl_rollout_undo()
noun_aliases=()
}
_kubectl_rollout_status()
{
last_command="kubectl_rollout_status"
commands=()
flags=()
two_word_flags=()
flags_with_completion=()
flags_completion=()
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+=("--recursive")
flags+=("-R")
flags+=("--alsologtostderr")
flags+=("--api-version=")
flags+=("--as=")
flags+=("--certificate-authority=")
flags+=("--client-certificate=")
flags+=("--client-key=")
flags+=("--cluster=")
flags+=("--context=")
flags+=("--insecure-skip-tls-verify")
flags+=("--kubeconfig=")
flags+=("--log-backtrace-at=")
flags+=("--log-dir=")
flags+=("--log-flush-frequency=")
flags+=("--logtostderr")
flags+=("--match-server-version")
flags+=("--namespace=")
flags_with_completion+=("--namespace")
flags_completion+=("__kubectl_get_namespaces")
flags+=("--password=")
flags+=("--server=")
two_word_flags+=("-s")
flags+=("--stderrthreshold=")
flags+=("--token=")
flags+=("--user=")
flags+=("--username=")
flags+=("--v=")
flags+=("--vmodule=")
must_have_one_flag=()
must_have_one_noun=()
noun_aliases=()
}
_kubectl_rollout()
{
last_command="kubectl_rollout"
@ -2611,6 +2662,7 @@ _kubectl_rollout()
commands+=("pause")
commands+=("resume")
commands+=("undo")
commands+=("status")
flags=()
two_word_flags=()

View File

@ -0,0 +1,146 @@
.TH "KUBERNETES" "1" " kubernetes User Manuals" "Eric Paris" "Jan 2015" ""
.SH NAME
.PP
kubectl rollout status \- Watch rollout status until it's done
.SH SYNOPSIS
.PP
\fBkubectl rollout status\fP [OPTIONS]
.SH DESCRIPTION
.PP
Watch the status of current rollout, until it's done.
.SH OPTIONS
.PP
\fB\-f\fP, \fB\-\-filename\fP=[]
Filename, directory, or URL to a file identifying the resource to get from a server.
.PP
\fB\-R\fP, \fB\-\-recursive\fP=false
If true, process directory recursively.
.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
\fB\-\-alsologtostderr\fP=false
log to standard error as well as files
.PP
\fB\-\-api\-version\fP=""
DEPRECATED: The API version to use when talking to the server
.PP
\fB\-\-as\fP=""
Username to impersonate for the operation.
.PP
\fB\-\-certificate\-authority\fP=""
Path to a cert. file for the certificate authority.
.PP
\fB\-\-client\-certificate\fP=""
Path to a client certificate file for TLS.
.PP
\fB\-\-client\-key\fP=""
Path to a client key file for TLS.
.PP
\fB\-\-cluster\fP=""
The name of the kubeconfig cluster to use
.PP
\fB\-\-context\fP=""
The name of the kubeconfig context to use
.PP
\fB\-\-insecure\-skip\-tls\-verify\fP=false
If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
.PP
\fB\-\-kubeconfig\fP=""
Path to the kubeconfig file to use for CLI requests.
.PP
\fB\-\-log\-backtrace\-at\fP=:0
when logging hits line file:N, emit a stack trace
.PP
\fB\-\-log\-dir\fP=""
If non\-empty, write log files in this directory
.PP
\fB\-\-log\-flush\-frequency\fP=5s
Maximum number of seconds between log flushes
.PP
\fB\-\-logtostderr\fP=true
log to standard error instead of files
.PP
\fB\-\-match\-server\-version\fP=false
Require server version to match client version
.PP
\fB\-\-namespace\fP=""
If present, the namespace scope for this CLI request.
.PP
\fB\-\-password\fP=""
Password for basic authentication to the API server.
.PP
\fB\-s\fP, \fB\-\-server\fP=""
The address and port of the Kubernetes API server
.PP
\fB\-\-stderrthreshold\fP=2
logs at or above this threshold go to stderr
.PP
\fB\-\-token\fP=""
Bearer token for authentication to the API server.
.PP
\fB\-\-user\fP=""
The name of the kubeconfig user to use
.PP
\fB\-\-username\fP=""
Username for basic authentication to the API server.
.PP
\fB\-\-v\fP=0
log level for V logs
.PP
\fB\-\-vmodule\fP=
comma\-separated list of pattern=N settings for file\-filtered logging
.SH EXAMPLE
.PP
.RS
.nf
# Watch the rollout status of a deployment
kubectl rollout status deployment/nginx
.fi
.RE
.SH SEE ALSO
.PP
\fBkubectl\-rollout(1)\fP,
.SH HISTORY
.PP
January 2015, Originally compiled by Eric Paris (eparis at redhat dot com) based on the kubernetes source material, but hopefully they have been automatically generated since!

View File

@ -128,7 +128,7 @@ kubectl rollout undo deployment/abc
.SH SEE ALSO
.PP
\fBkubectl(1)\fP, \fBkubectl\-rollout\-history(1)\fP, \fBkubectl\-rollout\-pause(1)\fP, \fBkubectl\-rollout\-resume(1)\fP, \fBkubectl\-rollout\-undo(1)\fP,
\fBkubectl(1)\fP, \fBkubectl\-rollout\-history(1)\fP, \fBkubectl\-rollout\-pause(1)\fP, \fBkubectl\-rollout\-resume(1)\fP, \fBkubectl\-rollout\-undo(1)\fP, \fBkubectl\-rollout\-status(1)\fP,
.SH HISTORY

View File

@ -119,7 +119,7 @@ kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=va
* [kubectl create](kubectl_create.md) - Create a resource by filename or stdin
###### Auto generated by spf13/cobra on 29-Apr-2016
###### Auto generated by spf13/cobra on 6-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_configmap.md?pixel)]()

View File

@ -103,7 +103,7 @@ kubectl create serviceaccount NAME [--dry-run]
* [kubectl create](kubectl_create.md) - Create a resource by filename or stdin
###### Auto generated by spf13/cobra on 5-Apr-2016
###### Auto generated by spf13/cobra on 6-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_serviceaccount.md?pixel)]()

View File

@ -86,9 +86,10 @@ kubectl rollout undo deployment/abc
* [kubectl rollout history](kubectl_rollout_history.md) - view rollout history
* [kubectl rollout pause](kubectl_rollout_pause.md) - Mark the provided resource as paused
* [kubectl rollout resume](kubectl_rollout_resume.md) - Resume a paused resource
* [kubectl rollout status](kubectl_rollout_status.md) - Watch rollout status until it's done
* [kubectl rollout undo](kubectl_rollout_undo.md) - undoes a previous rollout
###### Auto generated by spf13/cobra on 5-Apr-2016
###### Auto generated by spf13/cobra on 10-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_rollout.md?pixel)]()

View File

@ -95,7 +95,7 @@ kubectl rollout history deployment/abc --revision=3
* [kubectl rollout](kubectl_rollout.md) - rollout manages a deployment
###### Auto generated by spf13/cobra on 30-Mar-2016
###### Auto generated by spf13/cobra on 6-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_rollout_history.md?pixel)]()

View File

@ -97,7 +97,7 @@ kubectl rollout pause deployment/nginx
* [kubectl rollout](kubectl_rollout.md) - rollout manages a deployment
###### Auto generated by spf13/cobra on 30-Mar-2016
###### Auto generated by spf13/cobra on 6-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_rollout_pause.md?pixel)]()

View File

@ -95,7 +95,7 @@ kubectl rollout resume deployment/nginx
* [kubectl rollout](kubectl_rollout.md) - rollout manages a deployment
###### Auto generated by spf13/cobra on 30-Mar-2016
###### Auto generated by spf13/cobra on 6-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_rollout_resume.md?pixel)]()

View File

@ -0,0 +1,93 @@
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
## kubectl rollout status
Watch rollout status until it's done
### Synopsis
Watch the status of current rollout, until it's done.
```
kubectl rollout status (TYPE NAME | TYPE/NAME) [flags]
```
### Examples
```
# Watch the rollout status of a deployment
kubectl rollout status deployment/nginx
```
### Options
```
-f, --filename=[]: Filename, directory, or URL to a file identifying the resource to get from a server.
-R, --recursive[=false]: If true, process directory recursively.
```
### Options inherited from parent commands
```
--alsologtostderr[=false]: log to standard error as well as files
--as="": Username to impersonate for the operation.
--certificate-authority="": Path to a cert. file for the certificate authority.
--client-certificate="": Path to a client certificate file for TLS.
--client-key="": Path to a client key file for TLS.
--cluster="": The name of the kubeconfig cluster to use
--context="": The name of the kubeconfig context to use
--insecure-skip-tls-verify[=false]: If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.
--kubeconfig="": Path to the kubeconfig file to use for CLI requests.
--log-backtrace-at=:0: when logging hits line file:N, emit a stack trace
--log-dir="": If non-empty, write log files in this directory
--log-flush-frequency=5s: Maximum number of seconds between log flushes
--logtostderr[=true]: log to standard error instead of files
--match-server-version[=false]: Require server version to match client version
--namespace="": If present, the namespace scope for this CLI request.
--password="": Password for basic authentication to the API server.
-s, --server="": The address and port of the Kubernetes API server
--stderrthreshold=2: logs at or above this threshold go to stderr
--token="": Bearer token for authentication to the API server.
--user="": The name of the kubeconfig user to use
--username="": Username for basic authentication to the API server.
--v=0: log level for V logs
--vmodule=: comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kubectl rollout](kubectl_rollout.md) - rollout manages a deployment
###### Auto generated by spf13/cobra on 10-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_rollout_status.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -95,7 +95,7 @@ kubectl rollout undo deployment/abc --to-revision=3
* [kubectl rollout](kubectl_rollout.md) - rollout manages a deployment
###### Auto generated by spf13/cobra on 30-Mar-2016
###### Auto generated by spf13/cobra on 6-May-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_rollout_undo.md?pixel)]()

View File

@ -72,3 +72,4 @@ see_also:
- pause
- resume
- undo
- status

View File

@ -49,5 +49,7 @@ func NewCmdRollout(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.AddCommand(NewCmdRolloutResume(f, out))
cmd.AddCommand(NewCmdRolloutUndo(f, out))
cmd.AddCommand(NewCmdRolloutStatus(f, out))
return cmd
}

View File

@ -0,0 +1,142 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rollout
import (
"fmt"
"io"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/watch"
"github.com/spf13/cobra"
)
// StatusOptions 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()
type StatusOptions struct {
Filenames []string
Recursive bool
}
const (
status_long = `Watch the status of current rollout, until it's done.`
status_example = `# Watch the rollout status of a deployment
kubectl rollout status deployment/nginx`
)
func NewCmdRolloutStatus(f *cmdutil.Factory, out io.Writer) *cobra.Command {
options := &StatusOptions{}
cmd := &cobra.Command{
Use: "status (TYPE NAME | TYPE/NAME) [flags]",
Short: "Watch rollout status until it's done",
Long: status_long,
Example: status_example,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(RunStatus(f, cmd, out, args, options))
},
}
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddRecursiveFlag(cmd, &options.Recursive)
return cmd
}
func RunStatus(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *StatusOptions) error {
if len(args) == 0 && len(options.Filenames) == 0 {
return cmdutil.UsageError(cmd, "Required resource not specified.")
}
mapper, typer := f.Object(false)
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil {
return err
}
r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options.Recursive, options.Filenames...).
ResourceTypeOrNameArgs(true, args...).
SingleResourceType().
Latest().
Do()
err = r.Err()
if err != nil {
return err
}
infos, err := r.Infos()
if err != nil {
return err
}
if len(infos) != 1 {
return fmt.Errorf("rollout status is only supported on individual resources and resource collections - %d resources were found", len(infos))
}
info := infos[0]
mapping := info.ResourceMapping()
obj, err := r.Object()
if err != nil {
return err
}
rv, err := mapping.MetadataAccessor.ResourceVersion(obj)
if err != nil {
return err
}
statusViewer, err := f.StatusViewer(mapping)
if err != nil {
return err
}
// check if deployment's has finished the rollout
status, done, err := statusViewer.Status(cmdNamespace, info.Name)
if err != nil {
return err
}
fmt.Fprintf(out, "%s", status)
if done {
return nil
}
// watch for changes to the deployment
w, err := r.Watch(rv)
if err != nil {
return err
}
// if the rollout isn't done yet, keep watching deployment status
kubectl.WatchLoop(w, func(e watch.Event) error {
// print deployment's status
status, done, err := statusViewer.Status(cmdNamespace, info.Name)
if err != nil {
return err
}
fmt.Fprintf(out, "%s", status)
// Quit waiting if the rollout is done
if done {
w.Stop()
}
return nil
})
return nil
}

View File

@ -103,6 +103,8 @@ type Factory struct {
HistoryViewer func(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error)
// Returns a Rollbacker for changing the rollback version of the specified RESTMapping type or an error
Rollbacker func(mapping *meta.RESTMapping) (kubectl.Rollbacker, error)
// Returns a StatusViewer for printing rollout status.
StatusViewer func(mapping *meta.RESTMapping) (kubectl.StatusViewer, error)
// MapBasedSelectorForObject returns the map-based selector associated with the provided object. If a
// new set-based selector is provided, an error is returned if the selector cannot be converted to a
// map-based selector
@ -562,6 +564,14 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
}
return kubectl.RollbackerFor(mapping.GroupVersionKind.GroupKind(), client)
},
StatusViewer: func(mapping *meta.RESTMapping) (kubectl.StatusViewer, error) {
mappingVersion := mapping.GroupVersionKind.GroupVersion()
client, err := clients.ClientForVersion(&mappingVersion)
if err != nil {
return nil, err
}
return kubectl.StatusViewerFor(mapping.GroupVersionKind.GroupKind(), client)
},
Validator: func(validate bool, cacheDir string) (validation.Schema, error) {
if validate {
client, err := clients.ClientForVersion(nil)

View File

@ -0,0 +1,57 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubectl
import (
"fmt"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apis/extensions"
client "k8s.io/kubernetes/pkg/client/unversioned"
)
// StatusViewer provides an interface for resources that provides rollout status.
type StatusViewer interface {
Status(namespace, name string) (string, bool, error)
}
func StatusViewerFor(kind unversioned.GroupKind, c client.Interface) (StatusViewer, error) {
switch kind {
case extensions.Kind("Deployment"):
return &DeploymentStatusViewer{c.Extensions()}, nil
}
return nil, fmt.Errorf("no status viewer has been implemented for %v", kind)
}
type DeploymentStatusViewer struct {
c client.ExtensionsInterface
}
// Status returns a message describing deployment status, and a bool value indicating if the status is considered done
func (s *DeploymentStatusViewer) Status(namespace, name string) (string, bool, error) {
deployment, err := s.c.Deployments(namespace).Get(name)
if err != nil {
return "", false, err
}
if deployment.Generation <= deployment.Status.ObservedGeneration {
if deployment.Status.UpdatedReplicas == deployment.Spec.Replicas {
return fmt.Sprintf("deployment %s successfully rolled out\n", name), true, nil
}
return fmt.Sprintf("Waiting for rollout to finish: %d out of %d new replicas have been updated...\n", deployment.Status.UpdatedReplicas, deployment.Spec.Replicas), false, nil
}
return fmt.Sprintf("Waiting for deployment spec update to be observed...\n"), false, nil
}