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

Rolling Updates: Add support for --rollback. #7575

Merged
merged 1 commit into from May 6, 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
1 change: 1 addition & 0 deletions contrib/completions/bash/kubectl
Expand Up @@ -424,6 +424,7 @@ _kubectl_rolling-update()
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--poll-interval=")
flags+=("--rollback")
flags+=("--template=")
two_word_flags+=("-t")
flags+=("--timeout=")
Expand Down
2 changes: 1 addition & 1 deletion docs/design/simple-rolling-update.md
Expand Up @@ -38,7 +38,7 @@ it is assumed that the rollout is nearly completed, and ```foo-next``` is rename
### Aborting a rollout
Abort is assumed to want to reverse a rollout in progress.

```kubectl rolling-update rc foo [foo-v2] --abort```
```kubectl rolling-update rc foo [foo-v2] --rollback```

This is really just semantic sugar for:

Expand Down
3 changes: 2 additions & 1 deletion docs/kubectl_rolling-update.md
Expand Up @@ -45,6 +45,7 @@ $ kubectl rolling-update frontend --image=image:v2
-o, --output="": Output format. One of: json|yaml|template|templatefile.
--output-version="": Output the formatted object with the given version (default api-version).
--poll-interval="3s": Time delay between polling controller status after update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
--rollback=false: If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout
-t, --template="": Template string or path to template file to use when -o=template or -o=templatefile. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview]
--timeout="5m0s": Max time to wait for a controller to update before giving up. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
--update-period="1m0s": Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
Expand Down Expand Up @@ -83,4 +84,4 @@ $ kubectl rolling-update frontend --image=image:v2
### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra at 2015-04-29 15:25:11.031878187 +0000 UTC
###### Auto generated by spf13/cobra at 2015-05-02 00:22:29.503205238 +0000 UTC
4 changes: 4 additions & 0 deletions docs/man/man1/kubectl-rolling-update.1
Expand Up @@ -58,6 +58,10 @@ existing controller and overwrite at least one (common) label in its replicaSele
\fB\-\-poll\-interval\fP="3s"
Time delay between polling controller status after update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

.PP
\fB\-\-rollback\fP=false
If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout

.PP
\fB\-t\fP, \fB\-\-template\fP=""
Template string or path to template file to use when \-o=template or \-o=templatefile. The template format is golang templates [
Expand Down
21 changes: 16 additions & 5 deletions pkg/kubectl/cmd/rollingupdate.go
Expand Up @@ -82,6 +82,7 @@ func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().String("image", "", "Image to upgrade the controller to. Can not be used with --filename/-f")
cmd.Flags().String("deployment-label-key", "deployment", "The key to use to differentiate between two different controllers, default 'deployment'. Only relevant when --image is specified, ignored otherwise")
cmd.Flags().Bool("dry-run", false, "If true, print out the changes that would be made, but don't actually make them.")
cmd.Flags().Bool("rollback", false, "If true, this is a request to abort an existing rollout that is partially rolled out. It effectively reverses current and next and runs a rollout")
cmdutil.AddPrinterFlags(cmd)
return cmd
}
Expand Down Expand Up @@ -171,10 +172,15 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg

if len(newName) > 0 {
newRc, err = client.ReplicationControllers(cmdNamespace).Get(newName)
if err != nil && !apierrors.IsNotFound(err) {
return err
if err != nil {
if !apierrors.IsNotFound(err) {
return err
} else {
newRc = nil
}
} else {
fmt.Fprint(out, "Found existing update in progress (%s), resuming.\n", newName)
}
fmt.Fprint(out, "Found existing update in progress (%s), resuming.\n", newName)
}
if newRc == nil {
// load the old RC into the "new" RC
Expand Down Expand Up @@ -257,15 +263,20 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
if keepOldName {
updateCleanupPolicy = kubectl.RenameRollingUpdateCleanupPolicy
}
err = updater.Update(&kubectl.RollingUpdaterConfig{
config := &kubectl.RollingUpdaterConfig{
Out: out,
OldRc: oldRc,
NewRc: newRc,
UpdatePeriod: period,
Interval: interval,
Timeout: timeout,
CleanupPolicy: updateCleanupPolicy,
})
}
if cmdutil.GetFlagBool(cmd, "rollback") {
kubectl.AbortRollingUpdate(config)
client.ReplicationControllers(config.NewRc.Namespace).Update(config.NewRc)
}
err = updater.Update(config)
if err != nil {
return err
}
Expand Down
20 changes: 19 additions & 1 deletion pkg/kubectl/rolling_updater.go
Expand Up @@ -85,6 +85,24 @@ const (
nextControllerAnnotation = kubectlAnnotationPrefix + "next-controller-id"
)

func AbortRollingUpdate(c *RollingUpdaterConfig) {
// Swap the controllers
tmp := c.OldRc
c.OldRc = c.NewRc
c.NewRc = tmp

if c.NewRc.Annotations == nil {
c.NewRc.Annotations = map[string]string{}
}
c.NewRc.Annotations[sourceIdAnnotation] = fmt.Sprintf("%s:%s", c.OldRc.Name, c.OldRc.UID)
desiredSize, found := c.OldRc.Annotations[desiredReplicasAnnotation]
if found {
fmt.Printf("Found desired replicas.")
c.NewRc.Annotations[desiredReplicasAnnotation] = desiredSize
}
c.CleanupPolicy = DeleteRollingUpdateCleanupPolicy
}

func GetNextControllerAnnotation(rc *api.ReplicationController) (string, bool) {
res, found := rc.Annotations[nextControllerAnnotation]
return res, found
Expand Down Expand Up @@ -237,7 +255,7 @@ func (r *RollingUpdater) getExistingNewRc(sourceId, name string) (rc *api.Replic
source := annotations[sourceIdAnnotation]
_, ok := annotations[desiredReplicasAnnotation]
if source != sourceId || !ok {
err = fmt.Errorf("Missing/unexpected annotations for controller %s: %s", name, annotations)
err = fmt.Errorf("Missing/unexpected annotations for controller %s, expected %s : %s", name, sourceId, annotations)
}
return
}
Expand Down