mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Add unit tests to cli/command/volume package
Signed-off-by: Vincent Demeester <vincent@sbr.pm>
This commit is contained in:
		
							parent
							
								
									40532143c2
								
							
						
					
					
						commit
						6da111b3bb
					
				
					 30 changed files with 815 additions and 39 deletions
				
			
		| 
						 | 
				
			
			@ -38,6 +38,7 @@ type Cli interface {
 | 
			
		|||
	Out() *OutStream
 | 
			
		||||
	Err() io.Writer
 | 
			
		||||
	In() *InStream
 | 
			
		||||
	ConfigFile() *configfile.ConfigFile
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DockerCli is an instance the docker command line client.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										53
									
								
								cli/command/volume/client_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								cli/command/volume/client_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
package volume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	volumetypes "github.com/docker/docker/api/types/volume"
 | 
			
		||||
	"github.com/docker/docker/client"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type fakeClient struct {
 | 
			
		||||
	client.Client
 | 
			
		||||
	volumeCreateFunc  func(volumetypes.VolumesCreateBody) (types.Volume, error)
 | 
			
		||||
	volumeInspectFunc func(volumeID string) (types.Volume, error)
 | 
			
		||||
	volumeListFunc    func(filter filters.Args) (volumetypes.VolumesListOKBody, error)
 | 
			
		||||
	volumeRemoveFunc  func(volumeID string, force bool) error
 | 
			
		||||
	volumePruneFunc   func(filter filters.Args) (types.VolumesPruneReport, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *fakeClient) VolumeCreate(ctx context.Context, options volumetypes.VolumesCreateBody) (types.Volume, error) {
 | 
			
		||||
	if c.volumeCreateFunc != nil {
 | 
			
		||||
		return c.volumeCreateFunc(options)
 | 
			
		||||
	}
 | 
			
		||||
	return types.Volume{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *fakeClient) VolumeInspect(ctx context.Context, volumeID string) (types.Volume, error) {
 | 
			
		||||
	if c.volumeInspectFunc != nil {
 | 
			
		||||
		return c.volumeInspectFunc(volumeID)
 | 
			
		||||
	}
 | 
			
		||||
	return types.Volume{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *fakeClient) VolumeList(ctx context.Context, filter filters.Args) (volumetypes.VolumesListOKBody, error) {
 | 
			
		||||
	if c.volumeListFunc != nil {
 | 
			
		||||
		return c.volumeListFunc(filter)
 | 
			
		||||
	}
 | 
			
		||||
	return volumetypes.VolumesListOKBody{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *fakeClient) VolumesPrune(ctx context.Context, filter filters.Args) (types.VolumesPruneReport, error) {
 | 
			
		||||
	if c.volumePruneFunc != nil {
 | 
			
		||||
		return c.volumePruneFunc(filter)
 | 
			
		||||
	}
 | 
			
		||||
	return types.VolumesPruneReport{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *fakeClient) VolumeRemove(ctx context.Context, volumeID string, force bool) error {
 | 
			
		||||
	if c.volumeRemoveFunc != nil {
 | 
			
		||||
		return c.volumeRemoveFunc(volumeID, force)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,9 @@
 | 
			
		|||
package volume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cli"
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewVolumeCommand returns a cobra command for `volume` subcommands
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ type createOptions struct {
 | 
			
		|||
	labels     opts.ListOpts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		||||
func newCreateCommand(dockerCli command.Cli) *cobra.Command {
 | 
			
		||||
	opts := createOptions{
 | 
			
		||||
		driverOpts: *opts.NewMapOpts(nil, nil),
 | 
			
		||||
		labels:     opts.NewListOpts(opts.ValidateEnv),
 | 
			
		||||
| 
						 | 
				
			
			@ -32,8 +32,7 @@ func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		|||
		RunE: func(cmd *cobra.Command, args []string) error {
 | 
			
		||||
			if len(args) == 1 {
 | 
			
		||||
				if opts.name != "" {
 | 
			
		||||
					fmt.Fprint(dockerCli.Err(), "Conflicting options: either specify --name or provide positional arg, not both\n")
 | 
			
		||||
					return cli.StatusError{StatusCode: 1}
 | 
			
		||||
					return fmt.Errorf("Conflicting options: either specify --name or provide positional arg, not both\n")
 | 
			
		||||
				}
 | 
			
		||||
				opts.name = args[0]
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +49,7 @@ func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		|||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func runCreate(dockerCli *command.DockerCli, opts createOptions) error {
 | 
			
		||||
func runCreate(dockerCli command.Cli, opts createOptions) error {
 | 
			
		||||
	client := dockerCli.Client()
 | 
			
		||||
 | 
			
		||||
	volReq := volumetypes.VolumesCreateBody{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										142
									
								
								cli/command/volume/create_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								cli/command/volume/create_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,142 @@
 | 
			
		|||
package volume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	volumetypes "github.com/docker/docker/api/types/volume"
 | 
			
		||||
	"github.com/docker/docker/cli/internal/test"
 | 
			
		||||
	"github.com/docker/docker/pkg/testutil/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestVolumeCreateErrors(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		args             []string
 | 
			
		||||
		flags            map[string]string
 | 
			
		||||
		volumeCreateFunc func(volumetypes.VolumesCreateBody) (types.Volume, error)
 | 
			
		||||
		expectedError    string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			args: []string{"volumeName"},
 | 
			
		||||
			flags: map[string]string{
 | 
			
		||||
				"name": "volumeName",
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "Conflicting options: either specify --name or provide positional arg, not both",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			args:          []string{"too", "many"},
 | 
			
		||||
			expectedError: "requires at most 1 argument(s)",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			volumeCreateFunc: func(createBody volumetypes.VolumesCreateBody) (types.Volume, error) {
 | 
			
		||||
				return types.Volume{}, fmt.Errorf("error creating volume")
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "error creating volume",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cmd := newCreateCommand(
 | 
			
		||||
			test.NewFakeCli(&fakeClient{
 | 
			
		||||
				volumeCreateFunc: tc.volumeCreateFunc,
 | 
			
		||||
			}, 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 TestVolumeCreateWithName(t *testing.T) {
 | 
			
		||||
	name := "foo"
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	cli := test.NewFakeCli(&fakeClient{
 | 
			
		||||
		volumeCreateFunc: func(body volumetypes.VolumesCreateBody) (types.Volume, error) {
 | 
			
		||||
			if body.Name != name {
 | 
			
		||||
				return types.Volume{}, fmt.Errorf("expected name %q, got %q", name, body.Name)
 | 
			
		||||
			}
 | 
			
		||||
			return types.Volume{
 | 
			
		||||
				Name: body.Name,
 | 
			
		||||
			}, nil
 | 
			
		||||
		},
 | 
			
		||||
	}, buf)
 | 
			
		||||
 | 
			
		||||
	// Test by flags
 | 
			
		||||
	cmd := newCreateCommand(cli)
 | 
			
		||||
	cmd.Flags().Set("name", name)
 | 
			
		||||
	assert.NilError(t, cmd.Execute())
 | 
			
		||||
	assert.Equal(t, strings.TrimSpace(buf.String()), name)
 | 
			
		||||
 | 
			
		||||
	// Then by args
 | 
			
		||||
	buf.Reset()
 | 
			
		||||
	cmd = newCreateCommand(cli)
 | 
			
		||||
	cmd.SetArgs([]string{name})
 | 
			
		||||
	assert.NilError(t, cmd.Execute())
 | 
			
		||||
	assert.Equal(t, strings.TrimSpace(buf.String()), name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVolumeCreateWithFlags(t *testing.T) {
 | 
			
		||||
	expectedDriver := "foo"
 | 
			
		||||
	expectedOpts := map[string]string{
 | 
			
		||||
		"bar": "1",
 | 
			
		||||
		"baz": "baz",
 | 
			
		||||
	}
 | 
			
		||||
	expectedLabels := map[string]string{
 | 
			
		||||
		"lbl1": "v1",
 | 
			
		||||
		"lbl2": "v2",
 | 
			
		||||
	}
 | 
			
		||||
	name := "banana"
 | 
			
		||||
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	cli := test.NewFakeCli(&fakeClient{
 | 
			
		||||
		volumeCreateFunc: func(body volumetypes.VolumesCreateBody) (types.Volume, error) {
 | 
			
		||||
			if body.Name != "" {
 | 
			
		||||
				return types.Volume{}, fmt.Errorf("expected empty name, got %q", body.Name)
 | 
			
		||||
			}
 | 
			
		||||
			if body.Driver != expectedDriver {
 | 
			
		||||
				return types.Volume{}, fmt.Errorf("expected driver %q, got %q", expectedDriver, body.Driver)
 | 
			
		||||
			}
 | 
			
		||||
			if !compareMap(body.DriverOpts, expectedOpts) {
 | 
			
		||||
				return types.Volume{}, fmt.Errorf("expected drivers opts %v, got %v", expectedOpts, body.DriverOpts)
 | 
			
		||||
			}
 | 
			
		||||
			if !compareMap(body.Labels, expectedLabels) {
 | 
			
		||||
				return types.Volume{}, fmt.Errorf("expected labels %v, got %v", expectedLabels, body.Labels)
 | 
			
		||||
			}
 | 
			
		||||
			return types.Volume{
 | 
			
		||||
				Name: name,
 | 
			
		||||
			}, nil
 | 
			
		||||
		},
 | 
			
		||||
	}, buf)
 | 
			
		||||
 | 
			
		||||
	cmd := newCreateCommand(cli)
 | 
			
		||||
	cmd.Flags().Set("driver", "foo")
 | 
			
		||||
	cmd.Flags().Set("opt", "bar=1")
 | 
			
		||||
	cmd.Flags().Set("opt", "baz=baz")
 | 
			
		||||
	cmd.Flags().Set("label", "lbl1=v1")
 | 
			
		||||
	cmd.Flags().Set("label", "lbl2=v2")
 | 
			
		||||
	assert.NilError(t, cmd.Execute())
 | 
			
		||||
	assert.Equal(t, strings.TrimSpace(buf.String()), 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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,12 +1,11 @@
 | 
			
		|||
package volume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cli"
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	"github.com/docker/docker/cli/command/inspect"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type inspectOptions struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +13,7 @@ type inspectOptions struct {
 | 
			
		|||
	names  []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newInspectCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		||||
func newInspectCommand(dockerCli command.Cli) *cobra.Command {
 | 
			
		||||
	var opts inspectOptions
 | 
			
		||||
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +31,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()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										150
									
								
								cli/command/volume/inspect_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								cli/command/volume/inspect_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,150 @@
 | 
			
		|||
package volume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/cli/internal/test"
 | 
			
		||||
	// 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 TestVolumeInspectErrors(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		args              []string
 | 
			
		||||
		flags             map[string]string
 | 
			
		||||
		volumeInspectFunc func(volumeID string) (types.Volume, error)
 | 
			
		||||
		expectedError     string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			expectedError: "requires at least 1 argument",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			args: []string{"foo"},
 | 
			
		||||
			volumeInspectFunc: func(volumeID string) (types.Volume, error) {
 | 
			
		||||
				return types.Volume{}, fmt.Errorf("error while inspecting the volume")
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "error while inspecting the volume",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			args: []string{"foo"},
 | 
			
		||||
			flags: map[string]string{
 | 
			
		||||
				"format": "{{invalid format}}",
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "Template parsing error",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			args: []string{"foo", "bar"},
 | 
			
		||||
			volumeInspectFunc: func(volumeID string) (types.Volume, error) {
 | 
			
		||||
				if volumeID == "foo" {
 | 
			
		||||
					return types.Volume{
 | 
			
		||||
						Name: "foo",
 | 
			
		||||
					}, nil
 | 
			
		||||
				}
 | 
			
		||||
				return types.Volume{}, fmt.Errorf("error while inspecting the volume")
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "error while inspecting the volume",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cmd := newInspectCommand(
 | 
			
		||||
			test.NewFakeCli(&fakeClient{
 | 
			
		||||
				volumeInspectFunc: tc.volumeInspectFunc,
 | 
			
		||||
			}, 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 TestVolumeInspectWithoutFormat(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		name              string
 | 
			
		||||
		args              []string
 | 
			
		||||
		volumeInspectFunc func(volumeID string) (types.Volume, error)
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "single-volume",
 | 
			
		||||
			args: []string{"foo"},
 | 
			
		||||
			volumeInspectFunc: func(volumeID string) (types.Volume, error) {
 | 
			
		||||
				if volumeID != "foo" {
 | 
			
		||||
					return types.Volume{}, fmt.Errorf("Invalid volumeID, expected %s, got %s", "foo", volumeID)
 | 
			
		||||
				}
 | 
			
		||||
				return *Volume(), nil
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "multiple-volume-with-labels",
 | 
			
		||||
			args: []string{"foo", "bar"},
 | 
			
		||||
			volumeInspectFunc: func(volumeID string) (types.Volume, error) {
 | 
			
		||||
				return *Volume(VolumeName(volumeID), VolumeLabels(map[string]string{
 | 
			
		||||
					"foo": "bar",
 | 
			
		||||
				})), nil
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cmd := newInspectCommand(
 | 
			
		||||
			test.NewFakeCli(&fakeClient{
 | 
			
		||||
				volumeInspectFunc: tc.volumeInspectFunc,
 | 
			
		||||
			}, buf),
 | 
			
		||||
		)
 | 
			
		||||
		cmd.SetArgs(tc.args)
 | 
			
		||||
		assert.NilError(t, cmd.Execute())
 | 
			
		||||
		actual := buf.String()
 | 
			
		||||
		expected := golden.Get(t, []byte(actual), fmt.Sprintf("volume-inspect-without-format.%s.golden", tc.name))
 | 
			
		||||
		assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVolumeInspectWithFormat(t *testing.T) {
 | 
			
		||||
	volumeInspectFunc := func(volumeID string) (types.Volume, error) {
 | 
			
		||||
		return *Volume(VolumeLabels(map[string]string{
 | 
			
		||||
			"foo": "bar",
 | 
			
		||||
		})), nil
 | 
			
		||||
	}
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		name              string
 | 
			
		||||
		format            string
 | 
			
		||||
		args              []string
 | 
			
		||||
		volumeInspectFunc func(volumeID string) (types.Volume, error)
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:              "simple-template",
 | 
			
		||||
			format:            "{{.Name}}",
 | 
			
		||||
			args:              []string{"foo"},
 | 
			
		||||
			volumeInspectFunc: volumeInspectFunc,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:              "json-template",
 | 
			
		||||
			format:            "{{json .Labels}}",
 | 
			
		||||
			args:              []string{"foo"},
 | 
			
		||||
			volumeInspectFunc: volumeInspectFunc,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cmd := newInspectCommand(
 | 
			
		||||
			test.NewFakeCli(&fakeClient{
 | 
			
		||||
				volumeInspectFunc: tc.volumeInspectFunc,
 | 
			
		||||
			}, 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("volume-inspect-with-format.%s.golden", tc.name))
 | 
			
		||||
		assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,14 +3,13 @@ package volume
 | 
			
		|||
import (
 | 
			
		||||
	"sort"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/cli"
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	"github.com/docker/docker/cli/command/formatter"
 | 
			
		||||
	"github.com/docker/docker/opts"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type byVolumeName []*types.Volume
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +26,7 @@ type listOptions struct {
 | 
			
		|||
	filter opts.FilterOpt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		||||
func newListCommand(dockerCli command.Cli) *cobra.Command {
 | 
			
		||||
	opts := listOptions{filter: opts.NewFilterOpt()}
 | 
			
		||||
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +47,7 @@ func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		|||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func runList(dockerCli *command.DockerCli, opts listOptions) error {
 | 
			
		||||
func runList(dockerCli command.Cli, opts listOptions) error {
 | 
			
		||||
	client := dockerCli.Client()
 | 
			
		||||
	volumes, err := client.VolumeList(context.Background(), opts.filter.Value())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										124
									
								
								cli/command/volume/list_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								cli/command/volume/list_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,124 @@
 | 
			
		|||
package volume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	volumetypes "github.com/docker/docker/api/types/volume"
 | 
			
		||||
	"github.com/docker/docker/cli/config/configfile"
 | 
			
		||||
	"github.com/docker/docker/cli/internal/test"
 | 
			
		||||
	// 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 TestVolumeListErrors(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		args           []string
 | 
			
		||||
		flags          map[string]string
 | 
			
		||||
		volumeListFunc func(filter filters.Args) (volumetypes.VolumesListOKBody, error)
 | 
			
		||||
		expectedError  string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			args:          []string{"foo"},
 | 
			
		||||
			expectedError: "accepts no argument",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			volumeListFunc: func(filter filters.Args) (volumetypes.VolumesListOKBody, error) {
 | 
			
		||||
				return volumetypes.VolumesListOKBody{}, fmt.Errorf("error listing volumes")
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "error listing volumes",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cmd := newListCommand(
 | 
			
		||||
			test.NewFakeCli(&fakeClient{
 | 
			
		||||
				volumeListFunc: tc.volumeListFunc,
 | 
			
		||||
			}, 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 TestVolumeListWithoutFormat(t *testing.T) {
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	cli := test.NewFakeCli(&fakeClient{
 | 
			
		||||
		volumeListFunc: func(filter filters.Args) (volumetypes.VolumesListOKBody, error) {
 | 
			
		||||
			return volumetypes.VolumesListOKBody{
 | 
			
		||||
				Volumes: []*types.Volume{
 | 
			
		||||
					Volume(),
 | 
			
		||||
					Volume(VolumeName("foo"), VolumeDriver("bar")),
 | 
			
		||||
					Volume(VolumeName("baz"), VolumeLabels(map[string]string{
 | 
			
		||||
						"foo": "bar",
 | 
			
		||||
					})),
 | 
			
		||||
				},
 | 
			
		||||
			}, nil
 | 
			
		||||
		},
 | 
			
		||||
	}, buf)
 | 
			
		||||
	cli.SetConfigfile(&configfile.ConfigFile{})
 | 
			
		||||
	cmd := newListCommand(cli)
 | 
			
		||||
	assert.NilError(t, cmd.Execute())
 | 
			
		||||
	actual := buf.String()
 | 
			
		||||
	expected := golden.Get(t, []byte(actual), "volume-list-without-format.golden")
 | 
			
		||||
	assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVolumeListWithConfigFormat(t *testing.T) {
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	cli := test.NewFakeCli(&fakeClient{
 | 
			
		||||
		volumeListFunc: func(filter filters.Args) (volumetypes.VolumesListOKBody, error) {
 | 
			
		||||
			return volumetypes.VolumesListOKBody{
 | 
			
		||||
				Volumes: []*types.Volume{
 | 
			
		||||
					Volume(),
 | 
			
		||||
					Volume(VolumeName("foo"), VolumeDriver("bar")),
 | 
			
		||||
					Volume(VolumeName("baz"), VolumeLabels(map[string]string{
 | 
			
		||||
						"foo": "bar",
 | 
			
		||||
					})),
 | 
			
		||||
				},
 | 
			
		||||
			}, nil
 | 
			
		||||
		},
 | 
			
		||||
	}, buf)
 | 
			
		||||
	cli.SetConfigfile(&configfile.ConfigFile{
 | 
			
		||||
		VolumesFormat: "{{ .Name }} {{ .Driver }} {{ .Labels }}",
 | 
			
		||||
	})
 | 
			
		||||
	cmd := newListCommand(cli)
 | 
			
		||||
	assert.NilError(t, cmd.Execute())
 | 
			
		||||
	actual := buf.String()
 | 
			
		||||
	expected := golden.Get(t, []byte(actual), "volume-list-with-config-format.golden")
 | 
			
		||||
	assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVolumeListWithFormat(t *testing.T) {
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	cli := test.NewFakeCli(&fakeClient{
 | 
			
		||||
		volumeListFunc: func(filter filters.Args) (volumetypes.VolumesListOKBody, error) {
 | 
			
		||||
			return volumetypes.VolumesListOKBody{
 | 
			
		||||
				Volumes: []*types.Volume{
 | 
			
		||||
					Volume(),
 | 
			
		||||
					Volume(VolumeName("foo"), VolumeDriver("bar")),
 | 
			
		||||
					Volume(VolumeName("baz"), VolumeLabels(map[string]string{
 | 
			
		||||
						"foo": "bar",
 | 
			
		||||
					})),
 | 
			
		||||
				},
 | 
			
		||||
			}, nil
 | 
			
		||||
		},
 | 
			
		||||
	}, buf)
 | 
			
		||||
	cli.SetConfigfile(&configfile.ConfigFile{})
 | 
			
		||||
	cmd := newListCommand(cli)
 | 
			
		||||
	cmd.Flags().Set("format", "{{ .Name }} {{ .Driver }} {{ .Labels }}")
 | 
			
		||||
	assert.NilError(t, cmd.Execute())
 | 
			
		||||
	actual := buf.String()
 | 
			
		||||
	expected := golden.Get(t, []byte(actual), "volume-list-with-format.golden")
 | 
			
		||||
	assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -3,13 +3,12 @@ package volume
 | 
			
		|||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/cli"
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	units "github.com/docker/go-units"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type pruneOptions struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -17,7 +16,7 @@ type pruneOptions struct {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// NewPruneCommand returns a new cobra prune command for volumes
 | 
			
		||||
func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		||||
func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
 | 
			
		||||
	var opts pruneOptions
 | 
			
		||||
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +46,7 @@ func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		|||
const warning = `WARNING! This will remove all volumes not used by at least one container.
 | 
			
		||||
Are you sure you want to continue?`
 | 
			
		||||
 | 
			
		||||
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
 | 
			
		||||
func runPrune(dockerCli command.Cli, opts pruneOptions) (spaceReclaimed uint64, output string, err error) {
 | 
			
		||||
	if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										132
									
								
								cli/command/volume/prune_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								cli/command/volume/prune_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,132 @@
 | 
			
		|||
package volume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/filters"
 | 
			
		||||
	"github.com/docker/docker/cli/internal/test"
 | 
			
		||||
	"github.com/docker/docker/pkg/testutil/assert"
 | 
			
		||||
	"github.com/docker/docker/pkg/testutil/golden"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestVolumePruneErrors(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		args            []string
 | 
			
		||||
		flags           map[string]string
 | 
			
		||||
		volumePruneFunc func(args filters.Args) (types.VolumesPruneReport, error)
 | 
			
		||||
		expectedError   string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			args:          []string{"foo"},
 | 
			
		||||
			expectedError: "accepts no argument",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			flags: map[string]string{
 | 
			
		||||
				"force": "true",
 | 
			
		||||
			},
 | 
			
		||||
			volumePruneFunc: func(args filters.Args) (types.VolumesPruneReport, error) {
 | 
			
		||||
				return types.VolumesPruneReport{}, fmt.Errorf("error pruning volumes")
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "error pruning volumes",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		cmd := NewPruneCommand(
 | 
			
		||||
			test.NewFakeCli(&fakeClient{
 | 
			
		||||
				volumePruneFunc: tc.volumePruneFunc,
 | 
			
		||||
			}, ioutil.Discard),
 | 
			
		||||
		)
 | 
			
		||||
		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 TestVolumePruneForce(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		name            string
 | 
			
		||||
		volumePruneFunc func(args filters.Args) (types.VolumesPruneReport, error)
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "empty",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name:            "deletedVolumes",
 | 
			
		||||
			volumePruneFunc: simplePruneFunc,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cmd := NewPruneCommand(
 | 
			
		||||
			test.NewFakeCli(&fakeClient{
 | 
			
		||||
				volumePruneFunc: tc.volumePruneFunc,
 | 
			
		||||
			}, buf),
 | 
			
		||||
		)
 | 
			
		||||
		cmd.Flags().Set("force", "true")
 | 
			
		||||
		assert.NilError(t, cmd.Execute())
 | 
			
		||||
		actual := buf.String()
 | 
			
		||||
		expected := golden.Get(t, []byte(actual), fmt.Sprintf("volume-prune.%s.golden", tc.name))
 | 
			
		||||
		assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func TestVolumePrunePromptYes(t *testing.T) {
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		// FIXME(vdemeester) make it work..
 | 
			
		||||
		t.Skip("skipping this test on Windows")
 | 
			
		||||
	}
 | 
			
		||||
	for _, input := range []string{"y", "Y"} {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cli := test.NewFakeCli(&fakeClient{
 | 
			
		||||
			volumePruneFunc: simplePruneFunc,
 | 
			
		||||
		}, buf)
 | 
			
		||||
 | 
			
		||||
		cli.SetIn(ioutil.NopCloser(strings.NewReader(input)))
 | 
			
		||||
		cmd := NewPruneCommand(
 | 
			
		||||
			cli,
 | 
			
		||||
		)
 | 
			
		||||
		assert.NilError(t, cmd.Execute())
 | 
			
		||||
		actual := buf.String()
 | 
			
		||||
		expected := golden.Get(t, []byte(actual), "volume-prune-yes.golden")
 | 
			
		||||
		assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVolumePrunePromptNo(t *testing.T) {
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		// FIXME(vdemeester) make it work..
 | 
			
		||||
		t.Skip("skipping this test on Windows")
 | 
			
		||||
	}
 | 
			
		||||
	for _, input := range []string{"n", "N", "no", "anything", "really"} {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cli := test.NewFakeCli(&fakeClient{
 | 
			
		||||
			volumePruneFunc: simplePruneFunc,
 | 
			
		||||
		}, buf)
 | 
			
		||||
 | 
			
		||||
		cli.SetIn(ioutil.NopCloser(strings.NewReader(input)))
 | 
			
		||||
		cmd := NewPruneCommand(
 | 
			
		||||
			cli,
 | 
			
		||||
		)
 | 
			
		||||
		assert.NilError(t, cmd.Execute())
 | 
			
		||||
		actual := buf.String()
 | 
			
		||||
		expected := golden.Get(t, []byte(actual), "volume-prune-no.golden")
 | 
			
		||||
		assert.EqualNormalizedString(t, assert.RemoveSpace, actual, string(expected))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func simplePruneFunc(args filters.Args) (types.VolumesPruneReport, error) {
 | 
			
		||||
	return types.VolumesPruneReport{
 | 
			
		||||
		VolumesDeleted: []string{
 | 
			
		||||
			"foo", "bar", "baz",
 | 
			
		||||
		},
 | 
			
		||||
		SpaceReclaimed: 2000,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2,12 +2,12 @@ package volume
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cli"
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type removeOptions struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +16,7 @@ type removeOptions struct {
 | 
			
		|||
	volumes []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		||||
func newRemoveCommand(dockerCli command.Cli) *cobra.Command {
 | 
			
		||||
	var opts removeOptions
 | 
			
		||||
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
| 
						 | 
				
			
			@ -38,22 +38,22 @@ func newRemoveCommand(dockerCli *command.DockerCli) *cobra.Command {
 | 
			
		|||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func runRemove(dockerCli *command.DockerCli, opts *removeOptions) error {
 | 
			
		||||
func runRemove(dockerCli command.Cli, opts *removeOptions) error {
 | 
			
		||||
	client := dockerCli.Client()
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
	status := 0
 | 
			
		||||
 | 
			
		||||
	var errs []string
 | 
			
		||||
 | 
			
		||||
	for _, name := range opts.volumes {
 | 
			
		||||
		if err := client.VolumeRemove(ctx, name, opts.force); err != nil {
 | 
			
		||||
			fmt.Fprintf(dockerCli.Err(), "%s\n", err)
 | 
			
		||||
			status = 1
 | 
			
		||||
			errs = append(errs, err.Error())
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Fprintf(dockerCli.Out(), "%s\n", name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if status != 0 {
 | 
			
		||||
		return cli.StatusError{StatusCode: status}
 | 
			
		||||
	if len(errs) > 0 {
 | 
			
		||||
		return fmt.Errorf("%s", strings.Join(errs, "\n"))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										47
									
								
								cli/command/volume/remove_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								cli/command/volume/remove_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
package volume
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cli/internal/test"
 | 
			
		||||
	"github.com/docker/docker/pkg/testutil/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestVolumeRemoveErrors(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		args             []string
 | 
			
		||||
		volumeRemoveFunc func(volumeID string, force bool) error
 | 
			
		||||
		expectedError    string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			expectedError: "requires at least 1 argument",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			args: []string{"nodeID"},
 | 
			
		||||
			volumeRemoveFunc: func(volumeID string, force bool) error {
 | 
			
		||||
				return fmt.Errorf("error removing the volume")
 | 
			
		||||
			},
 | 
			
		||||
			expectedError: "error removing the volume",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, tc := range testCases {
 | 
			
		||||
		buf := new(bytes.Buffer)
 | 
			
		||||
		cmd := newRemoveCommand(
 | 
			
		||||
			test.NewFakeCli(&fakeClient{
 | 
			
		||||
				volumeRemoveFunc: tc.volumeRemoveFunc,
 | 
			
		||||
			}, buf))
 | 
			
		||||
		cmd.SetArgs(tc.args)
 | 
			
		||||
		cmd.SetOutput(ioutil.Discard)
 | 
			
		||||
		assert.Error(t, cmd.Execute(), tc.expectedError)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNodeRemoveMultiple(t *testing.T) {
 | 
			
		||||
	buf := new(bytes.Buffer)
 | 
			
		||||
	cmd := newRemoveCommand(test.NewFakeCli(&fakeClient{}, buf))
 | 
			
		||||
	cmd.SetArgs([]string{"volume1", "volume2"})
 | 
			
		||||
	assert.NilError(t, cmd.Execute())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								cli/command/volume/testdata/volume-inspect-with-format.json-template.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								cli/command/volume/testdata/volume-inspect-with-format.json-template.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
{"foo":"bar"}
 | 
			
		||||
							
								
								
									
										1
									
								
								cli/command/volume/testdata/volume-inspect-with-format.simple-template.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								cli/command/volume/testdata/volume-inspect-with-format.simple-template.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
volume
 | 
			
		||||
							
								
								
									
										22
									
								
								cli/command/volume/testdata/volume-inspect-without-format.multiple-volume-with-labels.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								cli/command/volume/testdata/volume-inspect-without-format.multiple-volume-with-labels.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
[
 | 
			
		||||
    {
 | 
			
		||||
        "Driver": "local",
 | 
			
		||||
        "Labels": {
 | 
			
		||||
            "foo": "bar"
 | 
			
		||||
        },
 | 
			
		||||
        "Mountpoint": "/data/volume",
 | 
			
		||||
        "Name": "foo",
 | 
			
		||||
        "Options": null,
 | 
			
		||||
        "Scope": "local"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "Driver": "local",
 | 
			
		||||
        "Labels": {
 | 
			
		||||
            "foo": "bar"
 | 
			
		||||
        },
 | 
			
		||||
        "Mountpoint": "/data/volume",
 | 
			
		||||
        "Name": "bar",
 | 
			
		||||
        "Options": null,
 | 
			
		||||
        "Scope": "local"
 | 
			
		||||
    }
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										10
									
								
								cli/command/volume/testdata/volume-inspect-without-format.single-volume.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								cli/command/volume/testdata/volume-inspect-without-format.single-volume.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
[
 | 
			
		||||
    {
 | 
			
		||||
        "Driver": "local",
 | 
			
		||||
        "Labels": null,
 | 
			
		||||
        "Mountpoint": "/data/volume",
 | 
			
		||||
        "Name": "volume",
 | 
			
		||||
        "Options": null,
 | 
			
		||||
        "Scope": "local"
 | 
			
		||||
    }
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										3
									
								
								cli/command/volume/testdata/volume-list-with-config-format.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								cli/command/volume/testdata/volume-list-with-config-format.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
baz local foo=bar
 | 
			
		||||
foo bar 
 | 
			
		||||
volume local 
 | 
			
		||||
							
								
								
									
										3
									
								
								cli/command/volume/testdata/volume-list-with-format.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								cli/command/volume/testdata/volume-list-with-format.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
baz local foo=bar
 | 
			
		||||
foo bar 
 | 
			
		||||
volume local 
 | 
			
		||||
							
								
								
									
										4
									
								
								cli/command/volume/testdata/volume-list-without-format.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								cli/command/volume/testdata/volume-list-without-format.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
DRIVER              VOLUME NAME
 | 
			
		||||
local               baz
 | 
			
		||||
bar                 foo
 | 
			
		||||
local               volume
 | 
			
		||||
							
								
								
									
										2
									
								
								cli/command/volume/testdata/volume-prune-no.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								cli/command/volume/testdata/volume-prune-no.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
WARNING! This will remove all volumes not used by at least one container.
 | 
			
		||||
Are you sure you want to continue? [y/N] Total reclaimed space: 0B
 | 
			
		||||
							
								
								
									
										7
									
								
								cli/command/volume/testdata/volume-prune-yes.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								cli/command/volume/testdata/volume-prune-yes.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
WARNING! This will remove all volumes not used by at least one container.
 | 
			
		||||
Are you sure you want to continue? [y/N] Deleted Volumes:
 | 
			
		||||
foo
 | 
			
		||||
bar
 | 
			
		||||
baz
 | 
			
		||||
 | 
			
		||||
Total reclaimed space: 2kB
 | 
			
		||||
							
								
								
									
										6
									
								
								cli/command/volume/testdata/volume-prune.deletedVolumes.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								cli/command/volume/testdata/volume-prune.deletedVolumes.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,6 @@
 | 
			
		|||
Deleted Volumes:
 | 
			
		||||
foo
 | 
			
		||||
bar
 | 
			
		||||
baz
 | 
			
		||||
 | 
			
		||||
Total reclaimed space: 2kB
 | 
			
		||||
							
								
								
									
										1
									
								
								cli/command/volume/testdata/volume-prune.empty.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								cli/command/volume/testdata/volume-prune.empty.golden
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
Total reclaimed space: 0B
 | 
			
		||||
							
								
								
									
										3
									
								
								cli/internal/test/builders/doc.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								cli/internal/test/builders/doc.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
// Package builders helps you create struct for your unit test while keeping them expressive.
 | 
			
		||||
//
 | 
			
		||||
package builders
 | 
			
		||||
| 
						 | 
				
			
			@ -8,6 +8,9 @@ import (
 | 
			
		|||
 | 
			
		||||
// Node creates a node with default values.
 | 
			
		||||
// Any number of node function builder can be pass to augment it.
 | 
			
		||||
//
 | 
			
		||||
//	n1 := Node() // Returns a default node
 | 
			
		||||
//	n2 := Node(NodeID("foo"), NodeHostname("bar"), Leader())
 | 
			
		||||
func Node(builders ...func(*swarm.Node)) *swarm.Node {
 | 
			
		||||
	t1 := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
 | 
			
		||||
	node := &swarm.Node{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										43
									
								
								cli/internal/test/builders/volume.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								cli/internal/test/builders/volume.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
package builders
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Volume creates a volume with default values.
 | 
			
		||||
// Any number of volume function builder can be pass to augment it.
 | 
			
		||||
func Volume(builders ...func(volume *types.Volume)) *types.Volume {
 | 
			
		||||
	volume := &types.Volume{
 | 
			
		||||
		Name:       "volume",
 | 
			
		||||
		Driver:     "local",
 | 
			
		||||
		Mountpoint: "/data/volume",
 | 
			
		||||
		Scope:      "local",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, builder := range builders {
 | 
			
		||||
		builder(volume)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return volume
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VolumeLabels sets the volume labels
 | 
			
		||||
func VolumeLabels(labels map[string]string) func(volume *types.Volume) {
 | 
			
		||||
	return func(volume *types.Volume) {
 | 
			
		||||
		volume.Labels = labels
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VolumeName sets the volume labels
 | 
			
		||||
func VolumeName(name string) func(volume *types.Volume) {
 | 
			
		||||
	return func(volume *types.Volume) {
 | 
			
		||||
		volume.Name = name
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VolumeDriver sets the volume driver
 | 
			
		||||
func VolumeDriver(name string) func(volume *types.Volume) {
 | 
			
		||||
	return func(volume *types.Volume) {
 | 
			
		||||
		volume.Driver = name
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,20 +1,22 @@
 | 
			
		|||
// Package test is a test-only package that can be used by other cli package to write unit test
 | 
			
		||||
package test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/cli/command"
 | 
			
		||||
	"github.com/docker/docker/cli/config/configfile"
 | 
			
		||||
	"github.com/docker/docker/client"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// FakeCli emulates the default DockerCli
 | 
			
		||||
type FakeCli struct {
 | 
			
		||||
	command.DockerCli
 | 
			
		||||
	client     client.APIClient
 | 
			
		||||
	configfile *configfile.ConfigFile
 | 
			
		||||
	out        io.Writer
 | 
			
		||||
	err        io.Writer
 | 
			
		||||
	in         io.ReadCloser
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -23,6 +25,7 @@ func NewFakeCli(client client.APIClient, out io.Writer) *FakeCli {
 | 
			
		|||
	return &FakeCli{
 | 
			
		||||
		client: client,
 | 
			
		||||
		out:    out,
 | 
			
		||||
		err:    ioutil.Discard,
 | 
			
		||||
		in:     ioutil.NopCloser(strings.NewReader("")),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -32,17 +35,37 @@ func (c *FakeCli) SetIn(in io.ReadCloser) {
 | 
			
		|||
	c.in = in
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetErr sets the standard error stream th cli should write on
 | 
			
		||||
func (c *FakeCli) SetErr(err io.Writer) {
 | 
			
		||||
	c.err = err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetConfigfile sets the "fake" config file
 | 
			
		||||
func (c *FakeCli) SetConfigfile(configfile *configfile.ConfigFile) {
 | 
			
		||||
	c.configfile = configfile
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Client returns a docker API client
 | 
			
		||||
func (c *FakeCli) Client() client.APIClient {
 | 
			
		||||
	return c.client
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Out returns the output stream the cli should write on
 | 
			
		||||
// Out returns the output stream (stdout) the cli should write on
 | 
			
		||||
func (c *FakeCli) Out() *command.OutStream {
 | 
			
		||||
	return command.NewOutStream(c.out)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// In returns thi input stream the cli will use
 | 
			
		||||
// Err returns the output stream (stderr) the cli should write on
 | 
			
		||||
func (c *FakeCli) Err() io.Writer {
 | 
			
		||||
	return c.err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// In returns the input stream the cli will use
 | 
			
		||||
func (c *FakeCli) In() *command.InStream {
 | 
			
		||||
	return command.NewInStream(c.in)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ConfigFile returns the cli configfile object (to get client configuration)
 | 
			
		||||
func (c *FakeCli) ConfigFile() *configfile.ConfigFile {
 | 
			
		||||
	return c.configfile
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										5
									
								
								cli/internal/test/doc.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								cli/internal/test/doc.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
// Package test is a test-only package that can be used by other cli package to write unit test.
 | 
			
		||||
//
 | 
			
		||||
// It as an internal package and cannot be used outside of github.com/docker/docker/cli package.
 | 
			
		||||
//
 | 
			
		||||
package test
 | 
			
		||||
| 
						 | 
				
			
			@ -292,11 +292,6 @@ func (s *DockerExternalVolumeSuite) TestVolumeCLICreateOptionConflict(c *check.C
 | 
			
		|||
	out, _ = dockerCmd(c, "volume", "inspect", "--format={{ .Driver }}", "test")
 | 
			
		||||
	_, _, err = dockerCmdWithError("volume", "create", "test", "--driver", strings.TrimSpace(out))
 | 
			
		||||
	c.Assert(err, check.IsNil)
 | 
			
		||||
 | 
			
		||||
	// make sure hidden --name option conflicts with positional arg name
 | 
			
		||||
	out, _, err = dockerCmdWithError("volume", "create", "--name", "test2", "test2")
 | 
			
		||||
	c.Assert(err, check.NotNil)
 | 
			
		||||
	c.Assert(strings.TrimSpace(out), checker.Equals, "Conflicting options: either specify --name or provide positional arg, not both")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *DockerExternalVolumeSuite) TestExternalVolumeDriverNamed(c *check.C) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue