From 243a8e69ff6141a27fb2e56e1101fb2e70822ab4 Mon Sep 17 00:00:00 2001 From: Arash Deshmeh Date: Sat, 1 Apr 2017 03:07:22 -0400 Subject: [PATCH] added unit tests for package cli/command/secret Signed-off-by: Arash Deshmeh --- cli/command/secret/client_test.go | 44 +++++ cli/command/secret/create.go | 4 +- cli/command/secret/create_test.go | 126 +++++++++++++ cli/command/secret/inspect.go | 4 +- cli/command/secret/inspect_test.go | 149 +++++++++++++++ cli/command/secret/ls.go | 4 +- cli/command/secret/ls_test.go | 172 ++++++++++++++++++ cli/command/secret/remove.go | 4 +- cli/command/secret/remove_test.go | 81 +++++++++ .../testdata/secret-create-with-name.golden | 1 + ...t-inspect-with-format.json-template.golden | 1 + ...inspect-with-format.simple-template.golden | 1 + ...format.multiple-secrets-with-labels.golden | 26 +++ ...nspect-without-format.single-secret.golden | 12 ++ .../secret-list-with-config-format.golden | 2 + .../testdata/secret-list-with-filter.golden | 3 + .../testdata/secret-list-with-format.golden | 2 + .../secret-list-with-quiet-option.golden | 2 + .../secret/testdata/secret-list.golden | 3 + cli/internal/test/builders/secret.go | 61 +++++++ 20 files changed, 694 insertions(+), 8 deletions(-) create mode 100644 cli/command/secret/client_test.go create mode 100644 cli/command/secret/create_test.go create mode 100644 cli/command/secret/inspect_test.go create mode 100644 cli/command/secret/ls_test.go create mode 100644 cli/command/secret/remove_test.go create mode 100644 cli/command/secret/testdata/secret-create-with-name.golden create mode 100644 cli/command/secret/testdata/secret-inspect-with-format.json-template.golden create mode 100644 cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden create mode 100644 cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden create mode 100644 cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden create mode 100644 cli/command/secret/testdata/secret-list-with-config-format.golden create mode 100644 cli/command/secret/testdata/secret-list-with-filter.golden create mode 100644 cli/command/secret/testdata/secret-list-with-format.golden create mode 100644 cli/command/secret/testdata/secret-list-with-quiet-option.golden create mode 100644 cli/command/secret/testdata/secret-list.golden create mode 100644 cli/internal/test/builders/secret.go diff --git a/cli/command/secret/client_test.go b/cli/command/secret/client_test.go new file mode 100644 index 0000000000..bb4b412fc2 --- /dev/null +++ b/cli/command/secret/client_test.go @@ -0,0 +1,44 @@ +package secret + +import ( + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/client" + "golang.org/x/net/context" +) + +type fakeClient struct { + client.Client + secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error) + secretInspectFunc func(string) (swarm.Secret, []byte, error) + secretListFunc func(types.SecretListOptions) ([]swarm.Secret, error) + secretRemoveFunc func(string) error +} + +func (c *fakeClient) SecretCreate(ctx context.Context, spec swarm.SecretSpec) (types.SecretCreateResponse, error) { + if c.secretCreateFunc != nil { + return c.secretCreateFunc(spec) + } + return types.SecretCreateResponse{}, nil +} + +func (c *fakeClient) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) { + if c.secretInspectFunc != nil { + return c.secretInspectFunc(id) + } + return swarm.Secret{}, nil, nil +} + +func (c *fakeClient) SecretList(ctx context.Context, options types.SecretListOptions) ([]swarm.Secret, error) { + if c.secretListFunc != nil { + return c.secretListFunc(options) + } + return []swarm.Secret{}, nil +} + +func (c *fakeClient) SecretRemove(ctx context.Context, name string) error { + if c.secretRemoveFunc != nil { + return c.secretRemoveFunc(name) + } + return nil +} diff --git a/cli/command/secret/create.go b/cli/command/secret/create.go index 11a85a22ca..59b0798178 100644 --- a/cli/command/secret/create.go +++ b/cli/command/secret/create.go @@ -22,7 +22,7 @@ type createOptions struct { labels opts.ListOpts } -func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command { +func newSecretCreateCommand(dockerCli command.Cli) *cobra.Command { createOpts := createOptions{ labels: opts.NewListOpts(opts.ValidateEnv), } @@ -43,7 +43,7 @@ func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command { return cmd } -func runSecretCreate(dockerCli *command.DockerCli, options createOptions) error { +func runSecretCreate(dockerCli command.Cli, options createOptions) error { client := dockerCli.Client() ctx := context.Background() diff --git a/cli/command/secret/create_test.go b/cli/command/secret/create_test.go new file mode 100644 index 0000000000..cbdfd63338 --- /dev/null +++ b/cli/command/secret/create_test.go @@ -0,0 +1,126 @@ +package secret + +import ( + "bytes" + "io/ioutil" + "path/filepath" + "strings" + "testing" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/cli/internal/test" + "github.com/docker/docker/pkg/testutil/assert" + "github.com/docker/docker/pkg/testutil/golden" + "github.com/pkg/errors" +) + +const secretDataFile = "secret-create-with-name.golden" + +func TestSecretCreateErrors(t *testing.T) { + testCases := []struct { + args []string + secretCreateFunc func(swarm.SecretSpec) (types.SecretCreateResponse, error) + expectedError string + }{ + { + args: []string{"too_few"}, + expectedError: "requires exactly 2 argument(s)", + }, + {args: []string{"too", "many", "arguments"}, + expectedError: "requires exactly 2 argument(s)", + }, + { + args: []string{"name", filepath.Join("testdata", secretDataFile)}, + secretCreateFunc: func(secretSpec swarm.SecretSpec) (types.SecretCreateResponse, error) { + return types.SecretCreateResponse{}, errors.Errorf("error creating secret") + }, + expectedError: "error creating secret", + }, + } + for _, tc := range testCases { + buf := new(bytes.Buffer) + cmd := newSecretCreateCommand( + test.NewFakeCli(&fakeClient{ + secretCreateFunc: tc.secretCreateFunc, + }, buf), + ) + cmd.SetArgs(tc.args) + cmd.SetOutput(ioutil.Discard) + assert.Error(t, cmd.Execute(), tc.expectedError) + } +} + +func TestSecretCreateWithName(t *testing.T) { + name := "foo" + buf := new(bytes.Buffer) + var actual []byte + cli := test.NewFakeCli(&fakeClient{ + secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) { + if spec.Name != name { + return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name) + } + + actual = spec.Data + + return types.SecretCreateResponse{ + ID: "ID-" + spec.Name, + }, nil + }, + }, buf) + + cmd := newSecretCreateCommand(cli) + cmd.SetArgs([]string{name, filepath.Join("testdata", secretDataFile)}) + assert.NilError(t, cmd.Execute()) + expected := golden.Get(t, actual, secretDataFile) + assert.Equal(t, string(actual), string(expected)) + assert.Equal(t, strings.TrimSpace(buf.String()), "ID-"+name) +} + +func TestSecretCreateWithLabels(t *testing.T) { + expectedLabels := map[string]string{ + "lbl1": "Label-foo", + "lbl2": "Label-bar", + } + name := "foo" + + buf := new(bytes.Buffer) + cli := test.NewFakeCli(&fakeClient{ + secretCreateFunc: func(spec swarm.SecretSpec) (types.SecretCreateResponse, error) { + if spec.Name != name { + return types.SecretCreateResponse{}, errors.Errorf("expected name %q, got %q", name, spec.Name) + } + + if !compareMap(spec.Labels, expectedLabels) { + return types.SecretCreateResponse{}, errors.Errorf("expected labels %v, got %v", expectedLabels, spec.Labels) + } + + return types.SecretCreateResponse{ + ID: "ID-" + spec.Name, + }, nil + }, + }, buf) + + cmd := newSecretCreateCommand(cli) + cmd.SetArgs([]string{name, filepath.Join("testdata", secretDataFile)}) + cmd.Flags().Set("label", "lbl1=Label-foo") + cmd.Flags().Set("label", "lbl2=Label-bar") + assert.NilError(t, cmd.Execute()) + assert.Equal(t, strings.TrimSpace(buf.String()), "ID-"+name) +} + +func compareMap(actual map[string]string, expected map[string]string) bool { + if len(actual) != len(expected) { + return false + } + for key, value := range actual { + if expectedValue, ok := expected[key]; ok { + if expectedValue != value { + return false + } + } else { + return false + } + } + return true +} diff --git a/cli/command/secret/inspect.go b/cli/command/secret/inspect.go index fb694c5fbe..8b3c3c682e 100644 --- a/cli/command/secret/inspect.go +++ b/cli/command/secret/inspect.go @@ -13,7 +13,7 @@ type inspectOptions struct { format string } -func newSecretInspectCommand(dockerCli *command.DockerCli) *cobra.Command { +func newSecretInspectCommand(dockerCli command.Cli) *cobra.Command { opts := inspectOptions{} cmd := &cobra.Command{ Use: "inspect [OPTIONS] SECRET [SECRET...]", @@ -29,7 +29,7 @@ func newSecretInspectCommand(dockerCli *command.DockerCli) *cobra.Command { return cmd } -func runSecretInspect(dockerCli *command.DockerCli, opts inspectOptions) error { +func runSecretInspect(dockerCli command.Cli, opts inspectOptions) error { client := dockerCli.Client() ctx := context.Background() diff --git a/cli/command/secret/inspect_test.go b/cli/command/secret/inspect_test.go new file mode 100644 index 0000000000..558e23d7c7 --- /dev/null +++ b/cli/command/secret/inspect_test.go @@ -0,0 +1,149 @@ +package secret + +import ( + "bytes" + "fmt" + "io/ioutil" + "testing" + + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/cli/internal/test" + "github.com/pkg/errors" + // Import builders to get the builder function as package function + . "github.com/docker/docker/cli/internal/test/builders" + "github.com/docker/docker/pkg/testutil/assert" + "github.com/docker/docker/pkg/testutil/golden" +) + +func TestSecretInspectErrors(t *testing.T) { + testCases := []struct { + args []string + flags map[string]string + secretInspectFunc func(secretID string) (swarm.Secret, []byte, error) + expectedError string + }{ + { + expectedError: "requires at least 1 argument", + }, + { + args: []string{"foo"}, + secretInspectFunc: func(secretID string) (swarm.Secret, []byte, error) { + return swarm.Secret{}, nil, errors.Errorf("error while inspecting the secret") + }, + expectedError: "error while inspecting the secret", + }, + { + args: []string{"foo"}, + flags: map[string]string{ + "format": "{{invalid format}}", + }, + expectedError: "Template parsing error", + }, + { + args: []string{"foo", "bar"}, + secretInspectFunc: func(secretID string) (swarm.Secret, []byte, error) { + if secretID == "foo" { + return *Secret(SecretName("foo")), nil, nil + } + return swarm.Secret{}, nil, errors.Errorf("error while inspecting the secret") + }, + expectedError: "error while inspecting the secret", + }, + } + for _, tc := range testCases { + buf := new(bytes.Buffer) + cmd := newSecretInspectCommand( + test.NewFakeCli(&fakeClient{ + secretInspectFunc: tc.secretInspectFunc, + }, buf), + ) + cmd.SetArgs(tc.args) + for key, value := range tc.flags { + cmd.Flags().Set(key, value) + } + cmd.SetOutput(ioutil.Discard) + assert.Error(t, cmd.Execute(), tc.expectedError) + } +} + +func TestSecretInspectWithoutFormat(t *testing.T) { + testCases := []struct { + name string + args []string + secretInspectFunc func(secretID string) (swarm.Secret, []byte, error) + }{ + { + name: "single-secret", + args: []string{"foo"}, + secretInspectFunc: func(name string) (swarm.Secret, []byte, error) { + if name != "foo" { + return swarm.Secret{}, nil, errors.Errorf("Invalid name, expected %s, got %s", "foo", name) + } + return *Secret(SecretID("ID-foo"), SecretName("foo")), nil, nil + }, + }, + { + name: "multiple-secrets-with-labels", + args: []string{"foo", "bar"}, + secretInspectFunc: func(name string) (swarm.Secret, []byte, error) { + return *Secret(SecretID("ID-"+name), SecretName(name), SecretLabels(map[string]string{ + "label1": "label-foo", + })), nil, nil + }, + }, + } + for _, tc := range testCases { + buf := new(bytes.Buffer) + cmd := newSecretInspectCommand( + test.NewFakeCli(&fakeClient{ + secretInspectFunc: tc.secretInspectFunc, + }, buf), + ) + cmd.SetArgs(tc.args) + assert.NilError(t, cmd.Execute()) + actual := buf.String() + expected := golden.Get(t, []byte(actual), fmt.Sprintf("secret-inspect-without-format.%s.golden", tc.name)) + assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected)) + } +} + +func TestSecretInspectWithFormat(t *testing.T) { + secretInspectFunc := func(name string) (swarm.Secret, []byte, error) { + return *Secret(SecretName("foo"), SecretLabels(map[string]string{ + "label1": "label-foo", + })), nil, nil + } + testCases := []struct { + name string + format string + args []string + secretInspectFunc func(name string) (swarm.Secret, []byte, error) + }{ + { + name: "simple-template", + format: "{{.Spec.Name}}", + args: []string{"foo"}, + secretInspectFunc: secretInspectFunc, + }, + { + name: "json-template", + format: "{{json .Spec.Labels}}", + args: []string{"foo"}, + secretInspectFunc: secretInspectFunc, + }, + } + for _, tc := range testCases { + buf := new(bytes.Buffer) + cmd := newSecretInspectCommand( + test.NewFakeCli(&fakeClient{ + secretInspectFunc: tc.secretInspectFunc, + }, buf), + ) + cmd.SetArgs(tc.args) + cmd.Flags().Set("format", tc.format) + assert.NilError(t, cmd.Execute()) + actual := buf.String() + expected := golden.Get(t, []byte(actual), fmt.Sprintf("secret-inspect-with-format.%s.golden", tc.name)) + assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected)) + } +} diff --git a/cli/command/secret/ls.go b/cli/command/secret/ls.go index 1d60ff7c4d..384ee26509 100644 --- a/cli/command/secret/ls.go +++ b/cli/command/secret/ls.go @@ -16,7 +16,7 @@ type listOptions struct { filter opts.FilterOpt } -func newSecretListCommand(dockerCli *command.DockerCli) *cobra.Command { +func newSecretListCommand(dockerCli command.Cli) *cobra.Command { opts := listOptions{filter: opts.NewFilterOpt()} cmd := &cobra.Command{ @@ -37,7 +37,7 @@ func newSecretListCommand(dockerCli *command.DockerCli) *cobra.Command { return cmd } -func runSecretList(dockerCli *command.DockerCli, opts listOptions) error { +func runSecretList(dockerCli command.Cli, opts listOptions) error { client := dockerCli.Client() ctx := context.Background() diff --git a/cli/command/secret/ls_test.go b/cli/command/secret/ls_test.go new file mode 100644 index 0000000000..d9a4324b75 --- /dev/null +++ b/cli/command/secret/ls_test.go @@ -0,0 +1,172 @@ +package secret + +import ( + "bytes" + "io/ioutil" + "testing" + "time" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/swarm" + "github.com/docker/docker/cli/config/configfile" + "github.com/docker/docker/cli/internal/test" + "github.com/pkg/errors" + // Import builders to get the builder function as package function + . "github.com/docker/docker/cli/internal/test/builders" + "github.com/docker/docker/pkg/testutil/assert" + "github.com/docker/docker/pkg/testutil/golden" +) + +func TestSecretListErrors(t *testing.T) { + testCases := []struct { + args []string + secretListFunc func(types.SecretListOptions) ([]swarm.Secret, error) + expectedError string + }{ + { + args: []string{"foo"}, + expectedError: "accepts no argument", + }, + { + secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { + return []swarm.Secret{}, errors.Errorf("error listing secrets") + }, + expectedError: "error listing secrets", + }, + } + for _, tc := range testCases { + buf := new(bytes.Buffer) + cmd := newSecretListCommand( + test.NewFakeCli(&fakeClient{ + secretListFunc: tc.secretListFunc, + }, buf), + ) + cmd.SetArgs(tc.args) + cmd.SetOutput(ioutil.Discard) + assert.Error(t, cmd.Execute(), tc.expectedError) + } +} + +func TestSecretList(t *testing.T) { + buf := new(bytes.Buffer) + cli := test.NewFakeCli(&fakeClient{ + secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { + return []swarm.Secret{ + *Secret(SecretID("ID-foo"), + SecretName("foo"), + SecretVersion(swarm.Version{Index: 10}), + SecretCreatedAt(time.Now().Add(-2*time.Hour)), + SecretUpdatedAt(time.Now().Add(-1*time.Hour)), + ), + *Secret(SecretID("ID-bar"), + SecretName("bar"), + SecretVersion(swarm.Version{Index: 11}), + SecretCreatedAt(time.Now().Add(-2*time.Hour)), + SecretUpdatedAt(time.Now().Add(-1*time.Hour)), + ), + }, nil + }, + }, buf) + cli.SetConfigfile(&configfile.ConfigFile{}) + cmd := newSecretListCommand(cli) + cmd.SetOutput(buf) + assert.NilError(t, cmd.Execute()) + actual := buf.String() + expected := golden.Get(t, []byte(actual), "secret-list.golden") + assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected)) +} + +func TestSecretListWithQuietOption(t *testing.T) { + buf := new(bytes.Buffer) + cli := test.NewFakeCli(&fakeClient{ + secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { + return []swarm.Secret{ + *Secret(SecretID("ID-foo"), SecretName("foo")), + *Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{ + "label": "label-bar", + })), + }, nil + }, + }, buf) + cli.SetConfigfile(&configfile.ConfigFile{}) + cmd := newSecretListCommand(cli) + cmd.Flags().Set("quiet", "true") + assert.NilError(t, cmd.Execute()) + actual := buf.String() + expected := golden.Get(t, []byte(actual), "secret-list-with-quiet-option.golden") + assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected)) +} + +func TestSecretListWithConfigFormat(t *testing.T) { + buf := new(bytes.Buffer) + cli := test.NewFakeCli(&fakeClient{ + secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { + return []swarm.Secret{ + *Secret(SecretID("ID-foo"), SecretName("foo")), + *Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{ + "label": "label-bar", + })), + }, nil + }, + }, buf) + cli.SetConfigfile(&configfile.ConfigFile{ + SecretFormat: "{{ .Name }} {{ .Labels }}", + }) + cmd := newSecretListCommand(cli) + assert.NilError(t, cmd.Execute()) + actual := buf.String() + expected := golden.Get(t, []byte(actual), "secret-list-with-config-format.golden") + assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected)) +} + +func TestSecretListWithFormat(t *testing.T) { + buf := new(bytes.Buffer) + cli := test.NewFakeCli(&fakeClient{ + secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { + return []swarm.Secret{ + *Secret(SecretID("ID-foo"), SecretName("foo")), + *Secret(SecretID("ID-bar"), SecretName("bar"), SecretLabels(map[string]string{ + "label": "label-bar", + })), + }, nil + }, + }, buf) + cmd := newSecretListCommand(cli) + cmd.Flags().Set("format", "{{ .Name }} {{ .Labels }}") + assert.NilError(t, cmd.Execute()) + actual := buf.String() + expected := golden.Get(t, []byte(actual), "secret-list-with-format.golden") + assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected)) +} + +func TestSecretListWithFilter(t *testing.T) { + buf := new(bytes.Buffer) + cli := test.NewFakeCli(&fakeClient{ + secretListFunc: func(options types.SecretListOptions) ([]swarm.Secret, error) { + assert.Equal(t, options.Filters.Get("name")[0], "foo") + assert.Equal(t, options.Filters.Get("label")[0], "lbl1=Label-bar") + return []swarm.Secret{ + *Secret(SecretID("ID-foo"), + SecretName("foo"), + SecretVersion(swarm.Version{Index: 10}), + SecretCreatedAt(time.Now().Add(-2*time.Hour)), + SecretUpdatedAt(time.Now().Add(-1*time.Hour)), + ), + *Secret(SecretID("ID-bar"), + SecretName("bar"), + SecretVersion(swarm.Version{Index: 11}), + SecretCreatedAt(time.Now().Add(-2*time.Hour)), + SecretUpdatedAt(time.Now().Add(-1*time.Hour)), + ), + }, nil + }, + }, buf) + cli.SetConfigfile(&configfile.ConfigFile{}) + cmd := newSecretListCommand(cli) + cmd.Flags().Set("filter", "name=foo") + cmd.Flags().Set("filter", "label=lbl1=Label-bar") + assert.NilError(t, cmd.Execute()) + actual := buf.String() + expected := golden.Get(t, []byte(actual), "secret-list-with-filter.golden") + assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected)) +} diff --git a/cli/command/secret/remove.go b/cli/command/secret/remove.go index 9115550d4d..a4b501d176 100644 --- a/cli/command/secret/remove.go +++ b/cli/command/secret/remove.go @@ -15,7 +15,7 @@ type removeOptions struct { names []string } -func newSecretRemoveCommand(dockerCli *command.DockerCli) *cobra.Command { +func newSecretRemoveCommand(dockerCli command.Cli) *cobra.Command { return &cobra.Command{ Use: "rm SECRET [SECRET...]", Aliases: []string{"remove"}, @@ -30,7 +30,7 @@ func newSecretRemoveCommand(dockerCli *command.DockerCli) *cobra.Command { } } -func runSecretRemove(dockerCli *command.DockerCli, opts removeOptions) error { +func runSecretRemove(dockerCli command.Cli, opts removeOptions) error { client := dockerCli.Client() ctx := context.Background() diff --git a/cli/command/secret/remove_test.go b/cli/command/secret/remove_test.go new file mode 100644 index 0000000000..92ca9b9b9d --- /dev/null +++ b/cli/command/secret/remove_test.go @@ -0,0 +1,81 @@ +package secret + +import ( + "bytes" + "io/ioutil" + "strings" + "testing" + + "github.com/docker/docker/cli/internal/test" + "github.com/docker/docker/pkg/testutil/assert" + "github.com/pkg/errors" +) + +func TestSecretRemoveErrors(t *testing.T) { + testCases := []struct { + args []string + secretRemoveFunc func(string) error + expectedError string + }{ + { + args: []string{}, + expectedError: "requires at least 1 argument(s).", + }, + { + args: []string{"foo"}, + secretRemoveFunc: func(name string) error { + return errors.Errorf("error removing secret") + }, + expectedError: "error removing secret", + }, + } + for _, tc := range testCases { + buf := new(bytes.Buffer) + cmd := newSecretRemoveCommand( + test.NewFakeCli(&fakeClient{ + secretRemoveFunc: tc.secretRemoveFunc, + }, buf), + ) + cmd.SetArgs(tc.args) + cmd.SetOutput(ioutil.Discard) + assert.Error(t, cmd.Execute(), tc.expectedError) + } +} + +func TestSecretRemoveWithName(t *testing.T) { + names := []string{"foo", "bar"} + buf := new(bytes.Buffer) + var removedSecrets []string + cli := test.NewFakeCli(&fakeClient{ + secretRemoveFunc: func(name string) error { + removedSecrets = append(removedSecrets, name) + return nil + }, + }, buf) + cmd := newSecretRemoveCommand(cli) + cmd.SetArgs(names) + assert.NilError(t, cmd.Execute()) + assert.EqualStringSlice(t, strings.Split(strings.TrimSpace(buf.String()), "\n"), names) + assert.EqualStringSlice(t, removedSecrets, names) +} + +func TestSecretRemoveContinueAfterError(t *testing.T) { + names := []string{"foo", "bar"} + buf := new(bytes.Buffer) + var removedSecrets []string + + cli := test.NewFakeCli(&fakeClient{ + secretRemoveFunc: func(name string) error { + removedSecrets = append(removedSecrets, name) + if name == "foo" { + return errors.Errorf("error removing secret: %s", name) + } + return nil + }, + }, buf) + + cmd := newSecretRemoveCommand(cli) + cmd.SetArgs(names) + assert.Error(t, cmd.Execute(), "error removing secret: foo") + assert.EqualStringSlice(t, removedSecrets, names) +} diff --git a/cli/command/secret/testdata/secret-create-with-name.golden b/cli/command/secret/testdata/secret-create-with-name.golden new file mode 100644 index 0000000000..788642a93a --- /dev/null +++ b/cli/command/secret/testdata/secret-create-with-name.golden @@ -0,0 +1 @@ +secret_foo_bar diff --git a/cli/command/secret/testdata/secret-inspect-with-format.json-template.golden b/cli/command/secret/testdata/secret-inspect-with-format.json-template.golden new file mode 100644 index 0000000000..aab678f85d --- /dev/null +++ b/cli/command/secret/testdata/secret-inspect-with-format.json-template.golden @@ -0,0 +1 @@ +{"label1":"label-foo"} diff --git a/cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden b/cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden new file mode 100644 index 0000000000..257cc5642c --- /dev/null +++ b/cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden @@ -0,0 +1 @@ +foo diff --git a/cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden b/cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden new file mode 100644 index 0000000000..6887c185f1 --- /dev/null +++ b/cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden @@ -0,0 +1,26 @@ +[ + { + "ID": "ID-foo", + "Version": {}, + "CreatedAt": "0001-01-01T00:00:00Z", + "UpdatedAt": "0001-01-01T00:00:00Z", + "Spec": { + "Name": "foo", + "Labels": { + "label1": "label-foo" + } + } + }, + { + "ID": "ID-bar", + "Version": {}, + "CreatedAt": "0001-01-01T00:00:00Z", + "UpdatedAt": "0001-01-01T00:00:00Z", + "Spec": { + "Name": "bar", + "Labels": { + "label1": "label-foo" + } + } + } +] diff --git a/cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden b/cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden new file mode 100644 index 0000000000..ea42ec6f4f --- /dev/null +++ b/cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden @@ -0,0 +1,12 @@ +[ + { + "ID": "ID-foo", + "Version": {}, + "CreatedAt": "0001-01-01T00:00:00Z", + "UpdatedAt": "0001-01-01T00:00:00Z", + "Spec": { + "Name": "foo", + "Labels": null + } + } +] diff --git a/cli/command/secret/testdata/secret-list-with-config-format.golden b/cli/command/secret/testdata/secret-list-with-config-format.golden new file mode 100644 index 0000000000..9a47538804 --- /dev/null +++ b/cli/command/secret/testdata/secret-list-with-config-format.golden @@ -0,0 +1,2 @@ +foo +bar label=label-bar diff --git a/cli/command/secret/testdata/secret-list-with-filter.golden b/cli/command/secret/testdata/secret-list-with-filter.golden new file mode 100644 index 0000000000..29983de8e9 --- /dev/null +++ b/cli/command/secret/testdata/secret-list-with-filter.golden @@ -0,0 +1,3 @@ +ID NAME CREATED UPDATED +ID-foo foo 2 hours ago About an hour ago +ID-bar bar 2 hours ago About an hour ago diff --git a/cli/command/secret/testdata/secret-list-with-format.golden b/cli/command/secret/testdata/secret-list-with-format.golden new file mode 100644 index 0000000000..9a47538804 --- /dev/null +++ b/cli/command/secret/testdata/secret-list-with-format.golden @@ -0,0 +1,2 @@ +foo +bar label=label-bar diff --git a/cli/command/secret/testdata/secret-list-with-quiet-option.golden b/cli/command/secret/testdata/secret-list-with-quiet-option.golden new file mode 100644 index 0000000000..83fb6e8979 --- /dev/null +++ b/cli/command/secret/testdata/secret-list-with-quiet-option.golden @@ -0,0 +1,2 @@ +ID-foo +ID-bar diff --git a/cli/command/secret/testdata/secret-list.golden b/cli/command/secret/testdata/secret-list.golden new file mode 100644 index 0000000000..29983de8e9 --- /dev/null +++ b/cli/command/secret/testdata/secret-list.golden @@ -0,0 +1,3 @@ +ID NAME CREATED UPDATED +ID-foo foo 2 hours ago About an hour ago +ID-bar bar 2 hours ago About an hour ago diff --git a/cli/internal/test/builders/secret.go b/cli/internal/test/builders/secret.go new file mode 100644 index 0000000000..9e0f910e93 --- /dev/null +++ b/cli/internal/test/builders/secret.go @@ -0,0 +1,61 @@ +package builders + +import ( + "time" + + "github.com/docker/docker/api/types/swarm" +) + +// Secret creates a secret with default values. +// Any number of secret builder functions can be passed to augment it. +func Secret(builders ...func(secret *swarm.Secret)) *swarm.Secret { + secret := &swarm.Secret{} + + for _, builder := range builders { + builder(secret) + } + + return secret +} + +// SecretLabels sets the secret's labels +func SecretLabels(labels map[string]string) func(secret *swarm.Secret) { + return func(secret *swarm.Secret) { + secret.Spec.Labels = labels + } +} + +// SecretName sets the secret's name +func SecretName(name string) func(secret *swarm.Secret) { + return func(secret *swarm.Secret) { + secret.Spec.Name = name + } +} + +// SecretID sets the secret's ID +func SecretID(ID string) func(secret *swarm.Secret) { + return func(secret *swarm.Secret) { + secret.ID = ID + } +} + +// SecretVersion sets the version for the secret +func SecretVersion(v swarm.Version) func(*swarm.Secret) { + return func(secret *swarm.Secret) { + secret.Version = v + } +} + +// SecretCreatedAt sets the creation time for the secret +func SecretCreatedAt(t time.Time) func(*swarm.Secret) { + return func(secret *swarm.Secret) { + secret.CreatedAt = t + } +} + +// SecretUpdatedAt sets the update time for the secret +func SecretUpdatedAt(t time.Time) func(*swarm.Secret) { + return func(secret *swarm.Secret) { + secret.UpdatedAt = t + } +}