mirror of https://github.com/docker/cli.git
Merge pull request #214 from adshmh/add-unit-tests-to-stack-package
add unit tests to stack package
This commit is contained in:
commit
d5d0ec56c1
|
@ -103,11 +103,11 @@ func TestNodePs(t *testing.T) {
|
|||
},
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{
|
||||
*Task(TaskID("taskID1"), ServiceID("failure"),
|
||||
*Task(TaskID("taskID1"), TaskServiceID("failure"),
|
||||
WithStatus(Timestamp(time.Now().Add(-2*time.Hour)), StatusErr("a task error"))),
|
||||
*Task(TaskID("taskID2"), ServiceID("failure"),
|
||||
*Task(TaskID("taskID2"), TaskServiceID("failure"),
|
||||
WithStatus(Timestamp(time.Now().Add(-3*time.Hour)), StatusErr("a task error"))),
|
||||
*Task(TaskID("taskID3"), ServiceID("failure"),
|
||||
*Task(TaskID("taskID3"), TaskServiceID("failure"),
|
||||
WithStatus(Timestamp(time.Now().Add(-4*time.Hour)), StatusErr("a task error"))),
|
||||
}, nil
|
||||
},
|
||||
|
|
|
@ -25,14 +25,17 @@ type fakeClient struct {
|
|||
removedSecrets []string
|
||||
removedConfigs []string
|
||||
|
||||
serviceListFunc func(options types.ServiceListOptions) ([]swarm.Service, error)
|
||||
networkListFunc func(options types.NetworkListOptions) ([]types.NetworkResource, error)
|
||||
secretListFunc func(options types.SecretListOptions) ([]swarm.Secret, error)
|
||||
configListFunc func(options types.ConfigListOptions) ([]swarm.Config, error)
|
||||
serviceRemoveFunc func(serviceID string) error
|
||||
networkRemoveFunc func(networkID string) error
|
||||
secretRemoveFunc func(secretID string) error
|
||||
configRemoveFunc func(configID string) error
|
||||
serviceListFunc func(options types.ServiceListOptions) ([]swarm.Service, error)
|
||||
networkListFunc func(options types.NetworkListOptions) ([]types.NetworkResource, error)
|
||||
secretListFunc func(options types.SecretListOptions) ([]swarm.Secret, error)
|
||||
configListFunc func(options types.ConfigListOptions) ([]swarm.Config, error)
|
||||
nodeListFunc func(options types.NodeListOptions) ([]swarm.Node, error)
|
||||
taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error)
|
||||
nodeInspectWithRaw func(ref string) (swarm.Node, []byte, error)
|
||||
serviceRemoveFunc func(serviceID string) error
|
||||
networkRemoveFunc func(networkID string) error
|
||||
secretRemoveFunc func(secretID string) error
|
||||
configRemoveFunc func(configID string) error
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error) {
|
||||
|
@ -102,6 +105,27 @@ func (cli *fakeClient) ConfigList(ctx context.Context, options types.ConfigListO
|
|||
return configsList, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) TaskList(ctx context.Context, options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
if cli.taskListFunc != nil {
|
||||
return cli.taskListFunc(options)
|
||||
}
|
||||
return []swarm.Task{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeList(ctx context.Context, options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
if cli.nodeListFunc != nil {
|
||||
return cli.nodeListFunc(options)
|
||||
}
|
||||
return []swarm.Node{}, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) NodeInspectWithRaw(ctx context.Context, ref string) (swarm.Node, []byte, error) {
|
||||
if cli.nodeInspectWithRaw != nil {
|
||||
return cli.nodeInspectWithRaw(ref)
|
||||
}
|
||||
return swarm.Node{}, nil, nil
|
||||
}
|
||||
|
||||
func (cli *fakeClient) ServiceRemove(ctx context.Context, serviceID string) error {
|
||||
if cli.serviceRemoveFunc != nil {
|
||||
return cli.serviceRemoveFunc(serviceID)
|
||||
|
|
|
@ -18,7 +18,7 @@ type listOptions struct {
|
|||
format string
|
||||
}
|
||||
|
||||
func newListCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||
func newListCommand(dockerCli command.Cli) *cobra.Command {
|
||||
opts := listOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
@ -36,7 +36,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()
|
||||
ctx := context.Background()
|
||||
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/internal/test"
|
||||
// Import builders to get the builder function as package function
|
||||
. "github.com/docker/cli/cli/internal/test/builders"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/docker/docker/pkg/testutil/golden"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestListErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
flags map[string]string
|
||||
serviceListFunc func(options types.ServiceListOptions) ([]swarm.Service, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
args: []string{"foo"},
|
||||
expectedError: "accepts no argument",
|
||||
},
|
||||
{
|
||||
flags: map[string]string{
|
||||
"format": "{{invalid format}}",
|
||||
},
|
||||
expectedError: "Template parsing error",
|
||||
},
|
||||
{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{}, errors.Errorf("error getting services")
|
||||
},
|
||||
expectedError: "error getting services",
|
||||
},
|
||||
{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*Service()}, nil
|
||||
},
|
||||
expectedError: "cannot get label",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
cmd := newListCommand(test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: tc.serviceListFunc,
|
||||
}, &bytes.Buffer{}))
|
||||
cmd.SetArgs(tc.args)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListWithFormat(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := newListCommand(test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": "service-name-foo",
|
||||
}),
|
||||
)}, nil
|
||||
},
|
||||
}, buf))
|
||||
cmd.Flags().Set("format", "{{ .Name }}")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-list-with-format.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestListWithoutFormat(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := newListCommand(test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": "service-name-foo",
|
||||
}),
|
||||
)}, nil
|
||||
},
|
||||
}, buf))
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-list-without-format.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestListOrder(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := newListCommand(test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": "service-name-foo",
|
||||
}),
|
||||
),
|
||||
*Service(
|
||||
ServiceLabels(map[string]string{
|
||||
"com.docker.stack.namespace": "service-name-bar",
|
||||
}),
|
||||
),
|
||||
}, nil
|
||||
},
|
||||
}, buf))
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-list-sort.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLoadBundlefileErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
namespace string
|
||||
path string
|
||||
expectedError error
|
||||
}{
|
||||
{
|
||||
namespace: "namespace_foo",
|
||||
expectedError: fmt.Errorf("Bundle %s.dab not found", "namespace_foo"),
|
||||
},
|
||||
{
|
||||
namespace: "namespace_foo",
|
||||
path: "invalid_path",
|
||||
expectedError: fmt.Errorf("Bundle %s not found", "invalid_path"),
|
||||
},
|
||||
{
|
||||
namespace: "namespace_foo",
|
||||
path: filepath.Join("testdata", "bundlefile_with_invalid_syntax"),
|
||||
expectedError: fmt.Errorf("Error reading"),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
_, err := loadBundlefile(&bytes.Buffer{}, tc.namespace, tc.path)
|
||||
assert.Error(t, err, tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadBundlefile(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
namespace := ""
|
||||
path := filepath.Join("testdata", "bundlefile_with_two_services.dab")
|
||||
bundleFile, err := loadBundlefile(buf, namespace, path)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(bundleFile.Services), 2)
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/internal/test"
|
||||
// Import builders to get the builder function as package function
|
||||
. "github.com/docker/cli/cli/internal/test/builders"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/docker/docker/pkg/testutil/golden"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStackPsErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error)
|
||||
expectedError string
|
||||
}{
|
||||
|
||||
{
|
||||
args: []string{},
|
||||
expectedError: "requires exactly 1 argument",
|
||||
},
|
||||
{
|
||||
args: []string{"foo", "bar"},
|
||||
expectedError: "requires exactly 1 argument",
|
||||
},
|
||||
{
|
||||
args: []string{"foo"},
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return nil, errors.Errorf("error getting tasks")
|
||||
},
|
||||
expectedError: "error getting tasks",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
cmd := newPsCommand(test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: tc.taskListFunc,
|
||||
}, &bytes.Buffer{}))
|
||||
cmd.SetArgs(tc.args)
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStackPsEmptyStack(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := newPsCommand(test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{}, nil
|
||||
},
|
||||
}, buf))
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.NoError(t, cmd.Execute())
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, buf.String(), "Nothing found in stack: foo")
|
||||
}
|
||||
|
||||
func TestStackPsWithQuietOption(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*Task(TaskID("id-foo"))}, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
cmd.Flags().Set("quiet", "true")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-ps-with-quiet-option.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
|
||||
}
|
||||
|
||||
func TestStackPsWithNoTruncOption(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*Task(TaskID("xn4cypcov06f2w8gsbaf2lst3"))}, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
cmd.Flags().Set("no-trunc", "true")
|
||||
cmd.Flags().Set("format", "{{ .ID }}")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-ps-with-no-trunc-option.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestStackPsWithNoResolveOption(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*Task(
|
||||
TaskNodeID("id-node-foo"),
|
||||
)}, nil
|
||||
},
|
||||
nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) {
|
||||
return *Node(NodeName("node-name-bar")), nil, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
cmd.Flags().Set("no-resolve", "true")
|
||||
cmd.Flags().Set("format", "{{ .Node }}")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-ps-with-no-resolve-option.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestStackPsWithFormat(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*Task(TaskServiceID("service-id-foo"))}, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
cmd.Flags().Set("format", "{{ .Name }}")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-ps-with-format.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestStackPsWithConfigFormat(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*Task(TaskServiceID("service-id-foo"))}, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{
|
||||
TasksFormat: "{{ .Name }}",
|
||||
})
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-ps-with-config-format.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestStackPsWithoutFormat(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return []swarm.Task{*Task(
|
||||
TaskID("id-foo"),
|
||||
TaskServiceID("service-id-foo"),
|
||||
TaskNodeID("id-node"),
|
||||
WithTaskSpec(TaskImage("myimage:mytag")),
|
||||
TaskDesiredState(swarm.TaskStateReady),
|
||||
WithStatus(TaskState(swarm.TaskStateFailed), Timestamp(time.Now().Add(-2*time.Hour))),
|
||||
)}, nil
|
||||
},
|
||||
nodeInspectWithRaw: func(ref string) (swarm.Node, []byte, error) {
|
||||
return *Node(NodeName("node-name-bar")), nil, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newPsCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-ps-without-format.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
|
@ -87,7 +87,7 @@ func TestSkipEmptyStack(t *testing.T) {
|
|||
assert.Equal(t, allConfigIDs, cli.removedConfigs)
|
||||
}
|
||||
|
||||
func TestContinueAfterError(t *testing.T) {
|
||||
func TestRemoveContinueAfterError(t *testing.T) {
|
||||
allServices := []string{objectName("foo", "service1"), objectName("bar", "service1")}
|
||||
allServiceIDs := buildObjectIDs(allServices)
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ type servicesOptions struct {
|
|||
namespace string
|
||||
}
|
||||
|
||||
func newServicesCommand(dockerCli *command.DockerCli) *cobra.Command {
|
||||
func newServicesCommand(dockerCli command.Cli) *cobra.Command {
|
||||
options := servicesOptions{filter: opts.NewFilterOpt()}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
@ -41,7 +41,7 @@ func newServicesCommand(dockerCli *command.DockerCli) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func runServices(dockerCli *command.DockerCli, options servicesOptions) error {
|
||||
func runServices(dockerCli command.Cli, options servicesOptions) error {
|
||||
ctx := context.Background()
|
||||
client := dockerCli.Client()
|
||||
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/config/configfile"
|
||||
"github.com/docker/cli/cli/internal/test"
|
||||
// Import builders to get the builder function as package function
|
||||
. "github.com/docker/cli/cli/internal/test/builders"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"github.com/docker/docker/pkg/testutil"
|
||||
"github.com/docker/docker/pkg/testutil/golden"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStackServicesErrors(t *testing.T) {
|
||||
testCases := []struct {
|
||||
args []string
|
||||
flags map[string]string
|
||||
serviceListFunc func(options types.ServiceListOptions) ([]swarm.Service, error)
|
||||
nodeListFunc func(options types.NodeListOptions) ([]swarm.Node, error)
|
||||
taskListFunc func(options types.TaskListOptions) ([]swarm.Task, error)
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
args: []string{"foo"},
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return nil, errors.Errorf("error getting services")
|
||||
},
|
||||
expectedError: "error getting services",
|
||||
},
|
||||
{
|
||||
args: []string{"foo"},
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*Service()}, nil
|
||||
},
|
||||
nodeListFunc: func(options types.NodeListOptions) ([]swarm.Node, error) {
|
||||
return nil, errors.Errorf("error getting nodes")
|
||||
},
|
||||
expectedError: "error getting nodes",
|
||||
},
|
||||
{
|
||||
args: []string{"foo"},
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*Service()}, nil
|
||||
},
|
||||
taskListFunc: func(options types.TaskListOptions) ([]swarm.Task, error) {
|
||||
return nil, errors.Errorf("error getting tasks")
|
||||
},
|
||||
expectedError: "error getting tasks",
|
||||
},
|
||||
{
|
||||
args: []string{"foo"},
|
||||
flags: map[string]string{
|
||||
"format": "{{invalid format}}",
|
||||
},
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*Service()}, nil
|
||||
},
|
||||
expectedError: "Template parsing error",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: tc.serviceListFunc,
|
||||
nodeListFunc: tc.nodeListFunc,
|
||||
taskListFunc: tc.taskListFunc,
|
||||
}, &bytes.Buffer{})
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newServicesCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
}
|
||||
cmd.SetOutput(ioutil.Discard)
|
||||
testutil.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStackServicesEmptyServiceList(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := newServicesCommand(
|
||||
test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{}, nil
|
||||
},
|
||||
}, buf),
|
||||
)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.NoError(t, cmd.Execute())
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, buf.String(), "Nothing found in stack: foo")
|
||||
}
|
||||
|
||||
func TestStackServicesWithQuietOption(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*Service(ServiceID("id-foo"))}, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newServicesCommand(cli)
|
||||
cmd.Flags().Set("quiet", "true")
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-services-with-quiet-option.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestStackServicesWithFormat(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{
|
||||
*Service(ServiceName("service-name-foo")),
|
||||
}, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newServicesCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
cmd.Flags().Set("format", "{{ .Name }}")
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-services-with-format.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestStackServicesWithConfigFormat(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{
|
||||
*Service(ServiceName("service-name-foo")),
|
||||
}, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{
|
||||
ServicesFormat: "{{ .Name }}",
|
||||
})
|
||||
cmd := newServicesCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-services-with-config-format.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
||||
|
||||
func TestStackServicesWithoutFormat(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
cli := test.NewFakeCli(&fakeClient{
|
||||
serviceListFunc: func(options types.ServiceListOptions) ([]swarm.Service, error) {
|
||||
return []swarm.Service{*Service(
|
||||
ServiceName("name-foo"),
|
||||
ServiceID("id-foo"),
|
||||
ReplicatedService(2),
|
||||
ServiceImage("busybox:latest"),
|
||||
ServicePort(swarm.PortConfig{
|
||||
PublishMode: swarm.PortConfigPublishModeIngress,
|
||||
PublishedPort: 0,
|
||||
TargetPort: 3232,
|
||||
Protocol: swarm.PortConfigProtocolTCP,
|
||||
}),
|
||||
)}, nil
|
||||
},
|
||||
}, buf)
|
||||
cli.SetConfigfile(&configfile.ConfigFile{})
|
||||
cmd := newServicesCommand(cli)
|
||||
cmd.SetArgs([]string{"foo"})
|
||||
assert.NoError(t, cmd.Execute())
|
||||
actual := buf.String()
|
||||
expected := golden.Get(t, []byte(actual), "stack-services-without-format.golden")
|
||||
testutil.EqualNormalizedString(t, testutil.RemoveSpace, actual, string(expected))
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"Services": {
|
||||
"visualizer": {
|
||||
"Image": "busybox@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f",
|
||||
"Networks": [
|
||||
"webnet"
|
||||
],
|
||||
"Ports": [
|
||||
{
|
||||
"Port": 8080,
|
||||
"Protocol": "tcp"
|
||||
}
|
||||
]
|
||||
},
|
||||
"web": {
|
||||
"Image": "busybox@sha256:32f093055929dbc23dec4d03e09dfe971f5973a9ca5cf059cbfb644c206aa83f",
|
||||
"Networks": [
|
||||
"webnet"
|
||||
],
|
||||
"Ports": [
|
||||
{
|
||||
"Port": 80,
|
||||
"Protocol": "tcp"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"Version": "0.1"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
NAME SERVICES
|
||||
service-name-bar 1
|
||||
service-name-foo 1
|
|
@ -0,0 +1 @@
|
|||
service-name-foo
|
|
@ -0,0 +1,2 @@
|
|||
NAME SERVICES
|
||||
service-name-foo 1
|
|
@ -0,0 +1 @@
|
|||
service-id-foo.1
|
|
@ -0,0 +1 @@
|
|||
service-id-foo.1
|
|
@ -0,0 +1 @@
|
|||
id-node-foo
|
|
@ -0,0 +1 @@
|
|||
xn4cypcov06f2w8gsbaf2lst3
|
|
@ -0,0 +1 @@
|
|||
id-foo
|
|
@ -0,0 +1,2 @@
|
|||
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
|
||||
id-foo service-id-foo.1 myimage:mytag node-name-bar Ready Failed 2 hours ago
|
|
@ -0,0 +1 @@
|
|||
service-name-foo
|
|
@ -0,0 +1 @@
|
|||
service-name-foo
|
|
@ -0,0 +1 @@
|
|||
id-foo
|
|
@ -0,0 +1,2 @@
|
|||
ID NAME MODE REPLICAS IMAGE PORTS
|
||||
id-foo name-foo replicated 0/2 busybox:latest *:0->3232/tcp
|
|
@ -14,6 +14,7 @@ func Service(builders ...func(*swarm.Service)) *swarm.Service {
|
|||
Annotations: swarm.Annotations{
|
||||
Name: "defaultServiceName",
|
||||
},
|
||||
EndpointSpec: &swarm.EndpointSpec{},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -24,9 +25,44 @@ func Service(builders ...func(*swarm.Service)) *swarm.Service {
|
|||
return service
|
||||
}
|
||||
|
||||
// ServiceID sets the service ID
|
||||
func ServiceID(ID string) func(*swarm.Service) {
|
||||
return func(service *swarm.Service) {
|
||||
service.ID = ID
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceName sets the service name
|
||||
func ServiceName(name string) func(*swarm.Service) {
|
||||
return func(service *swarm.Service) {
|
||||
service.Spec.Annotations.Name = name
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceLabels sets the service's labels
|
||||
func ServiceLabels(labels map[string]string) func(*swarm.Service) {
|
||||
return func(service *swarm.Service) {
|
||||
service.Spec.Annotations.Labels = labels
|
||||
}
|
||||
}
|
||||
|
||||
// ReplicatedService sets the number of replicas for the service
|
||||
func ReplicatedService(replicas uint64) func(*swarm.Service) {
|
||||
return func(service *swarm.Service) {
|
||||
service.Spec.Mode = swarm.ServiceMode{Replicated: &swarm.ReplicatedService{Replicas: &replicas}}
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceImage sets the service's image
|
||||
func ServiceImage(image string) func(*swarm.Service) {
|
||||
return func(service *swarm.Service) {
|
||||
service.Spec.TaskTemplate = swarm.TaskSpec{ContainerSpec: swarm.ContainerSpec{Image: image}}
|
||||
}
|
||||
}
|
||||
|
||||
// ServicePort sets the service's port
|
||||
func ServicePort(port swarm.PortConfig) func(*swarm.Service) {
|
||||
return func(service *swarm.Service) {
|
||||
service.Spec.EndpointSpec.Ports = append(service.Spec.EndpointSpec.Ports, port)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,13 +42,34 @@ func TaskID(id string) func(*swarm.Task) {
|
|||
}
|
||||
}
|
||||
|
||||
// ServiceID sets the task service's ID
|
||||
func ServiceID(id string) func(*swarm.Task) {
|
||||
// TaskName sets the task name
|
||||
func TaskName(name string) func(*swarm.Task) {
|
||||
return func(task *swarm.Task) {
|
||||
task.Annotations.Name = name
|
||||
}
|
||||
}
|
||||
|
||||
// TaskServiceID sets the task service's ID
|
||||
func TaskServiceID(id string) func(*swarm.Task) {
|
||||
return func(task *swarm.Task) {
|
||||
task.ServiceID = id
|
||||
}
|
||||
}
|
||||
|
||||
// TaskNodeID sets the task's node id
|
||||
func TaskNodeID(id string) func(*swarm.Task) {
|
||||
return func(task *swarm.Task) {
|
||||
task.NodeID = id
|
||||
}
|
||||
}
|
||||
|
||||
// TaskDesiredState sets the task's desired state
|
||||
func TaskDesiredState(state swarm.TaskState) func(*swarm.Task) {
|
||||
return func(task *swarm.Task) {
|
||||
task.DesiredState = state
|
||||
}
|
||||
}
|
||||
|
||||
// WithStatus sets the task status
|
||||
func WithStatus(statusBuilders ...func(*swarm.TaskStatus)) func(*swarm.Task) {
|
||||
return func(task *swarm.Task) {
|
||||
|
@ -86,6 +107,13 @@ func StatusErr(err string) func(*swarm.TaskStatus) {
|
|||
}
|
||||
}
|
||||
|
||||
// TaskState sets the task's current state
|
||||
func TaskState(state swarm.TaskState) func(*swarm.TaskStatus) {
|
||||
return func(taskStatus *swarm.TaskStatus) {
|
||||
taskStatus.State = state
|
||||
}
|
||||
}
|
||||
|
||||
// PortStatus sets the tasks port config status
|
||||
// FIXME(vdemeester) should be a sub builder 👼
|
||||
func PortStatus(portConfigs []swarm.PortConfig) func(*swarm.TaskStatus) {
|
||||
|
@ -94,6 +122,13 @@ func PortStatus(portConfigs []swarm.PortConfig) func(*swarm.TaskStatus) {
|
|||
}
|
||||
}
|
||||
|
||||
// WithTaskSpec sets the task spec
|
||||
func WithTaskSpec(specBuilders ...func(*swarm.TaskSpec)) func(*swarm.Task) {
|
||||
return func(task *swarm.Task) {
|
||||
task.Spec = *TaskSpec(specBuilders...)
|
||||
}
|
||||
}
|
||||
|
||||
// TaskSpec creates a task spec with default values .
|
||||
// Any number of taskSpec function builder can be pass to augment it.
|
||||
func TaskSpec(specBuilders ...func(*swarm.TaskSpec)) *swarm.TaskSpec {
|
||||
|
@ -109,3 +144,10 @@ func TaskSpec(specBuilders ...func(*swarm.TaskSpec)) *swarm.TaskSpec {
|
|||
|
||||
return taskSpec
|
||||
}
|
||||
|
||||
// TaskImage sets the task's image
|
||||
func TaskImage(image string) func(*swarm.TaskSpec) {
|
||||
return func(taskSpec *swarm.TaskSpec) {
|
||||
taskSpec.ContainerSpec.Image = image
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue