added unit tests for package cli/command/secret
Signed-off-by: Arash Deshmeh <adeshmeh@ca.ibm.com>
This commit is contained in:
parent
f6b7dc9837
commit
243a8e69ff
20 changed files with 694 additions and 8 deletions
44
cli/command/secret/client_test.go
Normal file
44
cli/command/secret/client_test.go
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -22,7 +22,7 @@ type createOptions struct {
|
||||||
labels opts.ListOpts
|
labels opts.ListOpts
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
|
func newSecretCreateCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
createOpts := createOptions{
|
createOpts := createOptions{
|
||||||
labels: opts.NewListOpts(opts.ValidateEnv),
|
labels: opts.NewListOpts(opts.ValidateEnv),
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ func newSecretCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSecretCreate(dockerCli *command.DockerCli, options createOptions) error {
|
func runSecretCreate(dockerCli command.Cli, options createOptions) error {
|
||||||
client := dockerCli.Client()
|
client := dockerCli.Client()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
|
126
cli/command/secret/create_test.go
Normal file
126
cli/command/secret/create_test.go
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ type inspectOptions struct {
|
||||||
format string
|
format string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSecretInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
|
func newSecretInspectCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
opts := inspectOptions{}
|
opts := inspectOptions{}
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "inspect [OPTIONS] SECRET [SECRET...]",
|
Use: "inspect [OPTIONS] SECRET [SECRET...]",
|
||||||
|
@ -29,7 +29,7 @@ func newSecretInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSecretInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
|
func runSecretInspect(dockerCli command.Cli, opts inspectOptions) error {
|
||||||
client := dockerCli.Client()
|
client := dockerCli.Client()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
|
149
cli/command/secret/inspect_test.go
Normal file
149
cli/command/secret/inspect_test.go
Normal file
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ type listOptions struct {
|
||||||
filter opts.FilterOpt
|
filter opts.FilterOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSecretListCommand(dockerCli *command.DockerCli) *cobra.Command {
|
func newSecretListCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
opts := listOptions{filter: opts.NewFilterOpt()}
|
opts := listOptions{filter: opts.NewFilterOpt()}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
@ -37,7 +37,7 @@ func newSecretListCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func runSecretList(dockerCli *command.DockerCli, opts listOptions) error {
|
func runSecretList(dockerCli command.Cli, opts listOptions) error {
|
||||||
client := dockerCli.Client()
|
client := dockerCli.Client()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
|
172
cli/command/secret/ls_test.go
Normal file
172
cli/command/secret/ls_test.go
Normal file
|
@ -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))
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ type removeOptions struct {
|
||||||
names []string
|
names []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSecretRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
|
func newSecretRemoveCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "rm SECRET [SECRET...]",
|
Use: "rm SECRET [SECRET...]",
|
||||||
Aliases: []string{"remove"},
|
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()
|
client := dockerCli.Client()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
|
81
cli/command/secret/remove_test.go
Normal file
81
cli/command/secret/remove_test.go
Normal file
|
@ -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)
|
||||||
|
}
|
1
cli/command/secret/testdata/secret-create-with-name.golden
vendored
Normal file
1
cli/command/secret/testdata/secret-create-with-name.golden
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
secret_foo_bar
|
1
cli/command/secret/testdata/secret-inspect-with-format.json-template.golden
vendored
Normal file
1
cli/command/secret/testdata/secret-inspect-with-format.json-template.golden
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"label1":"label-foo"}
|
1
cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden
vendored
Normal file
1
cli/command/secret/testdata/secret-inspect-with-format.simple-template.golden
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
foo
|
26
cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden
vendored
Normal file
26
cli/command/secret/testdata/secret-inspect-without-format.multiple-secrets-with-labels.golden
vendored
Normal file
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
12
cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden
vendored
Normal file
12
cli/command/secret/testdata/secret-inspect-without-format.single-secret.golden
vendored
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
2
cli/command/secret/testdata/secret-list-with-config-format.golden
vendored
Normal file
2
cli/command/secret/testdata/secret-list-with-config-format.golden
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
foo
|
||||||
|
bar label=label-bar
|
3
cli/command/secret/testdata/secret-list-with-filter.golden
vendored
Normal file
3
cli/command/secret/testdata/secret-list-with-filter.golden
vendored
Normal file
|
@ -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
|
2
cli/command/secret/testdata/secret-list-with-format.golden
vendored
Normal file
2
cli/command/secret/testdata/secret-list-with-format.golden
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
foo
|
||||||
|
bar label=label-bar
|
2
cli/command/secret/testdata/secret-list-with-quiet-option.golden
vendored
Normal file
2
cli/command/secret/testdata/secret-list-with-quiet-option.golden
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ID-foo
|
||||||
|
ID-bar
|
3
cli/command/secret/testdata/secret-list.golden
vendored
Normal file
3
cli/command/secret/testdata/secret-list.golden
vendored
Normal file
|
@ -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
|
61
cli/internal/test/builders/secret.go
Normal file
61
cli/internal/test/builders/secret.go
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue