Commit c9e33e19 authored by Brendan Burns's avatar Brendan Burns

Add support for --rollback.

parent b2c0ea37
...@@ -424,6 +424,7 @@ _kubectl_rolling-update() ...@@ -424,6 +424,7 @@ _kubectl_rolling-update()
two_word_flags+=("-o") two_word_flags+=("-o")
flags+=("--output-version=") flags+=("--output-version=")
flags+=("--poll-interval=") flags+=("--poll-interval=")
flags+=("--rollback")
flags+=("--template=") flags+=("--template=")
two_word_flags+=("-t") two_word_flags+=("-t")
flags+=("--timeout=") flags+=("--timeout=")
......
...@@ -38,7 +38,7 @@ it is assumed that the rollout is nearly completed, and ```foo-next``` is rename ...@@ -38,7 +38,7 @@ it is assumed that the rollout is nearly completed, and ```foo-next``` is rename
### Aborting a rollout ### Aborting a rollout
Abort is assumed to want to reverse a rollout in progress. 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: This is really just semantic sugar for:
......
...@@ -45,6 +45,7 @@ $ kubectl rolling-update frontend --image=image:v2 ...@@ -45,6 +45,7 @@ $ kubectl rolling-update frontend --image=image:v2
-o, --output="": Output format. One of: json|yaml|template|templatefile. -o, --output="": Output format. One of: json|yaml|template|templatefile.
--output-version="": Output the formatted object with the given version (default api-version). --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". --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] -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". --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". --update-period="1m0s": Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
...@@ -83,4 +84,4 @@ $ kubectl rolling-update frontend --image=image:v2 ...@@ -83,4 +84,4 @@ $ kubectl rolling-update frontend --image=image:v2
### SEE ALSO ### SEE ALSO
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager * [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
...@@ -59,6 +59,10 @@ existing controller and overwrite at least one (common) label in its replicaSele ...@@ -59,6 +59,10 @@ existing controller and overwrite at least one (common) label in its replicaSele
Time delay between polling controller status after update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". Time delay between polling controller status after update. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
.PP .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="" \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 [ Template string or path to template file to use when \-o=template or \-o=templatefile. The template format is golang templates [
\[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]] \[la]http://golang.org/pkg/text/template/#pkg-overview\[ra]]
......
...@@ -82,6 +82,7 @@ func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -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("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().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("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) cmdutil.AddPrinterFlags(cmd)
return cmd return cmd
} }
...@@ -171,11 +172,16 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg ...@@ -171,11 +172,16 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
if len(newName) > 0 { if len(newName) > 0 {
newRc, err = client.ReplicationControllers(cmdNamespace).Get(newName) newRc, err = client.ReplicationControllers(cmdNamespace).Get(newName)
if err != nil && !apierrors.IsNotFound(err) { if err != nil {
if !apierrors.IsNotFound(err) {
return 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 { if newRc == nil {
// load the old RC into the "new" RC // load the old RC into the "new" RC
if newRc, err = client.ReplicationControllers(cmdNamespace).Get(oldName); err != nil { if newRc, err = client.ReplicationControllers(cmdNamespace).Get(oldName); err != nil {
...@@ -257,7 +263,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg ...@@ -257,7 +263,7 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
if keepOldName { if keepOldName {
updateCleanupPolicy = kubectl.RenameRollingUpdateCleanupPolicy updateCleanupPolicy = kubectl.RenameRollingUpdateCleanupPolicy
} }
err = updater.Update(&kubectl.RollingUpdaterConfig{ config := &kubectl.RollingUpdaterConfig{
Out: out, Out: out,
OldRc: oldRc, OldRc: oldRc,
NewRc: newRc, NewRc: newRc,
...@@ -265,7 +271,12 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg ...@@ -265,7 +271,12 @@ func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, arg
Interval: interval, Interval: interval,
Timeout: timeout, Timeout: timeout,
CleanupPolicy: updateCleanupPolicy, 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 { if err != nil {
return err return err
} }
......
...@@ -85,6 +85,24 @@ const ( ...@@ -85,6 +85,24 @@ const (
nextControllerAnnotation = kubectlAnnotationPrefix + "next-controller-id" 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) { func GetNextControllerAnnotation(rc *api.ReplicationController) (string, bool) {
res, found := rc.Annotations[nextControllerAnnotation] res, found := rc.Annotations[nextControllerAnnotation]
return res, found return res, found
...@@ -237,7 +255,7 @@ func (r *RollingUpdater) getExistingNewRc(sourceId, name string) (rc *api.Replic ...@@ -237,7 +255,7 @@ func (r *RollingUpdater) getExistingNewRc(sourceId, name string) (rc *api.Replic
source := annotations[sourceIdAnnotation] source := annotations[sourceIdAnnotation]
_, ok := annotations[desiredReplicasAnnotation] _, ok := annotations[desiredReplicasAnnotation]
if source != sourceId || !ok { 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 return
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment