Skip to content

Commit

Permalink
Implement server-side rollback, for daemon versions that support this
Browse files Browse the repository at this point in the history
Server-side rollback can take advantage of the rollback-specific update
parameters, instead of being treated as a normal update that happens to
go back to a previous version of the spec.

Signed-off-by: Aaron Lehmann <[email protected]>
  • Loading branch information
aaronlehmann committed Mar 4, 2017
1 parent 8de01fb commit 78c204e
Showing 1 changed file with 38 additions and 5 deletions.
43 changes: 38 additions & 5 deletions command/service/update.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package service

import (
"errors"
"fmt"
"sort"
"strings"
Expand All @@ -10,6 +11,7 @@ import (
"github.com/docker/docker/api/types/container"
mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/client"
Expand Down Expand Up @@ -95,7 +97,6 @@ func newListOptsVar() *opts.ListOpts {
func runUpdate(dockerCli *command.DockerCli, flags *pflag.FlagSet, serviceID string) error {
apiClient := dockerCli.Client()
ctx := context.Background()
updateOpts := types.ServiceUpdateOptions{}

service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID)
if err != nil {
Expand All @@ -107,12 +108,44 @@ func runUpdate(dockerCli *command.DockerCli, flags *pflag.FlagSet, serviceID str
return err
}

// There are two ways to do user-requested rollback. The old way is
// client-side, but with a sufficiently recent daemon we prefer
// server-side, because it will honor the rollback parameters.
var (
clientSideRollback bool
serverSideRollback bool
)

spec := &service.Spec
if rollback {
spec = service.PreviousSpec
if spec == nil {
return fmt.Errorf("service does not have a previous specification to roll back to")
// Rollback can't be combined with other flags.
otherFlagsPassed := false
flags.VisitAll(func(f *pflag.Flag) {
if f.Name == "rollback" {
return
}
if flags.Changed(f.Name) {
otherFlagsPassed = true
}
})
if otherFlagsPassed {
return errors.New("other flags may not be combined with --rollback")
}

if versions.LessThan(dockerCli.Client().ClientVersion(), "1.27") {
clientSideRollback = true
spec = service.PreviousSpec
if spec == nil {
return fmt.Errorf("service does not have a previous specification to roll back to")
}
} else {
serverSideRollback = true
}
}

updateOpts := types.ServiceUpdateOptions{}
if serverSideRollback {
updateOpts.Rollback = "previous"
}

err = updateService(flags, spec)
Expand Down Expand Up @@ -147,7 +180,7 @@ func runUpdate(dockerCli *command.DockerCli, flags *pflag.FlagSet, serviceID str
return err
}
updateOpts.EncodedRegistryAuth = encodedAuth
} else if rollback {
} else if clientSideRollback {
updateOpts.RegistryAuthFrom = types.RegistryAuthFromPreviousSpec
} else {
updateOpts.RegistryAuthFrom = types.RegistryAuthFromSpec
Expand Down

0 comments on commit 78c204e

Please sign in to comment.