Add support for --rollback.

pull/6/head
Brendan Burns 2015-04-30 10:28:36 -07:00
parent b2c0ea37b4
commit c9e33e197d
6 changed files with 43 additions and 8 deletions

View File

@ -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=")

View File

@ -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:

View File

@ -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
### 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

View File

@ -58,6 +58,10 @@ existing controller and overwrite at least one (common) label in its replicaSele
\fB\-\-poll\-interval\fP="3s" \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". 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 .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 [

View File

@ -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,10 +172,15 @@ 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 {
return err 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 { if newRc == nil {
// load the old RC into the "new" RC // load the old RC into the "new" RC
@ -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
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
} }

View File

@ -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
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
} }