8000 Add 'docker service rollback' subcommand by redpanda · Pull Request #205 · docker/cli · GitHub
[go: up one dir, main page]

Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add 'docker service rollback' subcommand
Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Implement runRollback to not use runUpdate

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Add version tag and add flag quiet to suppress progress output

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Removed flags from warnDetachDefault

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Used command.Cli interface

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Add detach flag on rollback command

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Create a fakeClient for service commands

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Added unit test for rollback command

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Used command.Cli interface instead of *command.DockerCli in service commands

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Revert "Removed flags from warnDetachDefault"

This reverts commit 3e4f601.

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Fixed test.NewFakeCli instanciation

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Removed unused receiver

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Replaced cli by dockerCli

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Revert "Removed unused receiver"

This reverts commit 604ef7c.

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>

Fixed last typo

Signed-off-by: Jimmy Leger <jimmy.leger@gmail.com>
  • Loading branch information
redpanda committed Aug 16, 2017
commit 11d471d6601617d0507e27dfa228563b7b9e0654
33 changes: 27 additions & 6 deletions cli/command/service/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,49 @@ import (
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/client"
"golang.org/x/net/context"
// Import builders to get the builder function as package function
. "github.com/docker/cli/cli/internal/test/builders"
)

type fakeClient struct {
client.Client
serviceListFunc func(context.Context, types.ServiceListOptions) ([]swarm.Service, error)
serviceInspectWithRawFunc func(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error)
serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error)
serviceListFunc func(context.Context, types.ServiceListOptions) ([]swarm.Service, error)
}

func (f *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
if f.serviceListFunc != nil {
return f.serviceListFunc(ctx, options)
}
func (f *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
return nil, nil
}

func (f *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
return nil, nil
}

func (f *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
func (f *fakeClient) ServiceInspectWithRaw(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
if f.serviceInspectWithRawFunc != nil {
return f.serviceInspectWithRawFunc(ctx, serviceID, options)
}

return *Service(ServiceID(serviceID)), []byte{}, nil
}

func (f *fakeClient) ServiceList(ctx context.Context, options types.ServiceListOptions) ([]swarm.Service, error) {
if f.serviceListFunc != nil {
return f.serviceListFunc(ctx, options)
}

return nil, nil
}

func (f *fakeClient) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
if f.serviceUpdateFunc != nil {
return f.serviceUpdateFunc(ctx, serviceID, version, service, options)
}

return types.ServiceUpdateResponse{}, nil
}

func newService(id string, name string) swarm.Service {
return swarm.Service{
ID: id,
Expand Down
1 change: 1 addition & 0 deletions cli/command/service/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func NewServiceCommand(dockerCli *command.DockerCli) *cobra.Command {
newScaleCommand(dockerCli),
newUpdateCommand(dockerCli),
newLogsCommand(dockerCli),
newRollbackCommand(dockerCli),
)
return cmd
}
4 changes: 2 additions & 2 deletions cli/command/service/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"golang.org/x/net/context"
)

func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
func newCreateCommand(dockerCli command.Cli) *cobra.Command {
opts := newServiceOptions()

cmd := &cobra.Command{
Expand Down Expand Up @@ -62,7 +62,7 @@ func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}

func runCreate(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts *serviceOptions) error {
func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions) error {
apiClient := dockerCli.Client()
createOpts := types.ServiceCreateOptions{}

Expand Down
2 changes: 1 addition & 1 deletion cli/command/service/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

// waitOnService waits for the service to converge. It outputs a progress bar,
// if appropriate based on the CLI flags.
func waitOnService(ctx context.Context, dockerCli *command.DockerCli, serviceID string, quiet bool) error {
func waitOnService(ctx context.Context, dockerCli command.Cli, serviceID string, quiet bool) error {
errChan := make(chan error, 1)
pipeReader, pipeWriter := io.Pipe()

Expand Down
4 changes: 2 additions & 2 deletions cli/command/service/inspect.go
< 685C td class="blob-code blob-code-addition js-file-line"> func newInspectCommand(dockerCli command.Cli) *cobra.Command {
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type inspectOptions struct {
pretty bool
}

func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
var opts inspectOptions

cmd := &cobra.Command{
Expand All @@ -43,7 +43,7 @@ func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}

func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
func runInspect(dockerCli command.Cli, opts inspectOptions) error {
client := dockerCli.Client()
ctx := context.Background()

Expand Down
4 changes: 2 additions & 2 deletions cli/command/service/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"golang.org/x/net/context"
)

func newRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
func newRemoveCommand(dockerCli command.Cli) *cobra.Command {

cmd := &cobra.Command{
Use: "rm SERVICE [SERVICE...]",
Expand All @@ -27,7 +27,7 @@ func newRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
return cmd
}

func runRemove(dockerCli *command.DockerCli, sids []string) error {
func runRemove(dockerCli command.Cli, sids []string) error {
client := dockerCli.Client()

ctx := context.Background()
Expand Down
65 changes: 65 additions & 0 deletions cli/command/service/rollback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package service

import (
"context"
"fmt"

"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/docker/api/types"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func newRollbackCommand(dockerCli command.Cli) *cobra.Command {
options := newServiceOptions()

cmd := &cobra.Command{
Use: "rollback [OPTIONS] SERVICE",
Short: "Revert changes to a service's configuration",
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
return runRollback(dockerCli, cmd.Flags(), options, args[0])
},
Tags: map[string]string{"version": "1.31"},
}

flags := cmd.Flags()
flags.BoolVarP(&options.quiet, flagQuiet, "q", false, "Suppress progress output")
addDetachFlag(flags, &options.detach)

return cmd
}

func runRollback(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error {
apiClient := dockerCli.Client()
ctx := context.Background()

service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
if err != nil {
return err
}

spec := &service.Spec
updateOpts := types.ServiceUpdateOptions{
Rollback: "previous",
}

response, err := apiClient.ServiceUpdate(ctx, service.ID, service.Version, *spec, updateOpts)
if err != nil {
return err
}

for _, warning := range response.Warnings {
fmt.Fprintln(dockerCli.Err(), warning)
}

fmt.Fprintf(dockerCli.Out(), "%s\n", serviceID)

if options.detach {
warnDetachDefault(dockerCli.Err(), apiClient.ClientVersion(), flags, "rolled back")
return nil
}

return waitOnService(ctx, dockerCli, serviceID, options.quiet)
}
104 changes: 104 additions & 0 deletions cli/command/service/rollback_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package service

import (
"fmt"
"io/ioutil"
"strings"
"testing"

"github.com/docker/cli/cli/internal/test"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/pkg/testutil"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)

func TestRollback(t *testing.T) {
testCases := []struct {
name string
args []string
serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error)
expectedDockerCliErr string
}{
{
name: "rollback-service",
args: []string{"service-id"},
},
{
name: "rollback-service-with-warnings",
args: []string{"service-id"},
serviceUpdateFunc: func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
response := types.ServiceUpdateResponse{}

response.Warnings = []string{
"- warning 1",
"- warning 2",
}

return response, nil
},
expectedDockerCliErr: "- warning 1\n- warning 2",
},
}

for _, tc := range testCases {
cli := test.NewFakeCli(&fakeClient{
serviceUpdateFunc: tc.serviceUpdateFunc,
})
cmd := newRollbackCommand(cli)
cmd.SetArgs(tc.args)
cmd.Flags().Set("quiet", "true")
cmd.SetOutput(ioutil.Discard)
assert.NoError(t, cmd.Execute())
assert.Equal(t, strings.TrimSpace(cli.ErrBuffer().String()), tc.expectedDockerCliErr)
}
}

func TestRollbackWithErrors(t *testing.T) {
testCases := []struct {
name string
args []string
serviceInspectWithRawFunc func(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error)
serviceUpdateFunc func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error)
expectedError string
}{
{
name: "not-enough-args",
expectedError: "requires exactly 1 argument",
},
{
name: "too-many-args",
args: []string{"service-id-1", "service-id-2"},
expectedError: "requires exactly 1 argument",
},
{
name: "service-does-not-exists",
args: []string{"service-id"},
serviceInspectWithRawFunc: func(ctx context.Context, serviceID string, options types.ServiceInspectOptions) (swarm.Service, []byte, error) {
return swarm.Service{}, []byte{}, fmt.Errorf("no such services: %s", serviceID)
},
expectedError: "no such services: service-id",
},
{
name: "service-update-failed",
args: []string{"service-id"},
serviceUpdateFunc: func(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
return types.ServiceUpdateResponse{}, fmt.Errorf("no such services: %s", serviceID)
},
expectedError: "no such services: service-id",
},
}

for _, tc := range testCases {
cmd := newRollbackCommand(
test.NewFakeCli(&fakeClient{
serviceInspectWithRawFunc: tc.serviceInspectWithRawFunc,
serviceUpdateFunc: tc.serviceUpdateFunc,
}))
cmd.SetArgs(tc.args)
cmd.Flags().Set("quiet", "true")
cmd.SetOutput(ioutil.Discard)
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
}
}
6 changes: 3 additions & 3 deletions cli/command/service/scale.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type scaleOptions struct {
detach bool
}

func newScaleCommand(dockerCli *command.DockerCli) *cobra.Command {
func newScaleCommand(dockerCli command.Cli) *cobra.Command {
options := &scaleOptions{}

cmd := &cobra.Command{
Expand Down Expand Up @@ -54,7 +54,7 @@ func scaleArgs(cmd *cobra.Command, args []string) error {
return nil
}

func runScale(dockerCli *command.DockerCli, flags *pflag.FlagSet, options *scaleOptions, args []string) error {
func runScale(dockerCli command.Cli, flags *pflag.FlagSet, options *scaleOptions, args []string) error {
var errs []string
var serviceIDs []string
ctx := context.Background()
Expand Down Expand Up @@ -96,7 +96,7 @@ func runScale(dockerCli *command.DockerCli, flags *pflag.FlagSet, options *scale
return errors.Errorf(strings.Join(errs, "\n"))
}

func runServiceScale(ctx context.Context, dockerCli *command.DockerCli, serviceID string, scale uint64) error {
func runServiceScale(ctx context.Context, dockerCli command.Cli, serviceID string, scale uint64) error {
client := dockerCli.Client()

service, _, err := client.ServiceInspectWithRaw(ctx, serviceID, types.ServiceInspectOptions{})
Expand Down
4 changes: 2 additions & 2 deletions cli/command/service/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"golang.org/x/net/context"
)

func newUpdateCommand(dockerCli *command.DockerCli) *cobra.Command {
func newUpdateCommand(dockerCli command.Cli) *cobra.Command {
options := newServiceOptions()

cmd := &cobra.Command{
Expand Down Expand Up @@ -103,7 +103,7 @@ func newListOptsVar() *opts.ListOpts {
}

// nolint: gocyclo
func runUpdate(dockerCli *command.DockerCli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error {
func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error {
apiClient := dockerCli.Client()
ctx := context.Background()

Expand Down
3 changes: 2 additions & 1 deletion docs/reference/commandline/service_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -877,9 +877,10 @@ x3ti0erg11rjpg64m75kej2mz-hosttempl
* [service inspect](service_inspect.md)
* [service logs](service_logs.md)
* [service ls](service_ls.md)
* [service ps](service_ps.md)
* [service rm](service_rm.md)
* [service rollback](service_rollback.md)
* [service scale](service_scale.md)
* [service ps](service_ps.md)
* [service update](service_update.md)

<style>table tr > td:first-child { white-space: nowrap;}</style>
3 changes: 2 additions & 1 deletion docs/reference/commandline/service_inspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ $ d D37C ocker service inspect --format='{{.Spec.Mode.Replicated.Replicas}}' redis
* [service create](service_create.md)
* [service logs](service_logs.md)
* [service ls](service_ls.md)
* [service ps](service_ps.md)
* [service rm](service_rm.md)
* [service rollback](service_rollback.md)
* [service scale](service_scale.md)
* [service ps](service_ps.md)
* [service update](service_update.md)
3 changes: 2 additions & 1 deletion docs/reference/commandline/service_logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ fraction of a second no more than nine digits long. You can combine the
* [service create](service_create.md)
* [service inspect](service_inspect.md)
* [service ls](service_ls.md)
* [service ps](service_ps.md)
* [service rm](service_rm.md)
* [service rollback](service_rollback.md)
* [service scale](service_scale.md)
* [service ps](service_ps.md)
* [service update](service_update.md)
3 changes: 2 additions & 1 deletion docs/reference/commandline/service_ls.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ fm6uf97exkul: global 5/5
* [service create](service_create.md)
* [service inspect](service_inspect.md)
* [service logs](service_logs.md)
* [service ps](service_ps.md)
* [service rm](service_rm.md)
* [service rollback](service_rollback.md)
* [service scale](service_scale.md)
* [service ps](service_ps.md)
* [service update](service_update.md)
1 change: 1 addition & 0 deletions docs/reference/commandline/service_ps.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,5 +190,6 @@ top.3: busybox
* [service logs](service_logs.md)
* [service ls](service_ls.md)
* [service rm](service_rm.md)
* [service rollback](service_rollback.md)
* [service scale](service_scale.md)
* [service update](service_update.md)
Loading
0