mirror of https://github.com/docker/cli.git
remove obsolete mutli-orchestrator support
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
1d48749c1c
commit
193ede9b12
|
@ -60,7 +60,6 @@ type Cli interface {
|
||||||
ContentTrustEnabled() bool
|
ContentTrustEnabled() bool
|
||||||
ContextStore() store.Store
|
ContextStore() store.Store
|
||||||
CurrentContext() string
|
CurrentContext() string
|
||||||
StackOrchestrator(flagValue string) (Orchestrator, error)
|
|
||||||
DockerEndpoint() docker.Endpoint
|
DockerEndpoint() docker.Endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,25 +366,6 @@ func (cli *DockerCli) CurrentContext() string {
|
||||||
return cli.currentContext
|
return cli.currentContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// StackOrchestrator resolves which stack orchestrator is in use
|
|
||||||
func (cli *DockerCli) StackOrchestrator(flagValue string) (Orchestrator, error) {
|
|
||||||
currentContext := cli.CurrentContext()
|
|
||||||
ctxRaw, err := cli.ContextStore().GetMetadata(currentContext)
|
|
||||||
if store.IsErrContextDoesNotExist(err) {
|
|
||||||
// case where the currentContext has been removed (CLI behavior is to fallback to using DOCKER_HOST based resolution)
|
|
||||||
return GetStackOrchestrator(flagValue, "", cli.ConfigFile().StackOrchestrator, cli.Err())
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
ctxMeta, err := GetDockerContext(ctxRaw)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
ctxOrchestrator := string(ctxMeta.StackOrchestrator)
|
|
||||||
return GetStackOrchestrator(flagValue, ctxOrchestrator, cli.ConfigFile().StackOrchestrator, cli.Err())
|
|
||||||
}
|
|
||||||
|
|
||||||
// DockerEndpoint returns the current docker endpoint
|
// DockerEndpoint returns the current docker endpoint
|
||||||
func (cli *DockerCli) DockerEndpoint() docker.Endpoint {
|
func (cli *DockerCli) DockerEndpoint() docker.Endpoint {
|
||||||
return cli.dockerEndpoint
|
return cli.dockerEndpoint
|
||||||
|
|
|
@ -9,9 +9,8 @@ import (
|
||||||
|
|
||||||
// DockerContext is a typed representation of what we put in Context metadata
|
// DockerContext is a typed representation of what we put in Context metadata
|
||||||
type DockerContext struct {
|
type DockerContext struct {
|
||||||
Description string
|
Description string
|
||||||
StackOrchestrator Orchestrator
|
AdditionalFields map[string]interface{}
|
||||||
AdditionalFields map[string]interface{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements custom JSON marshalling
|
// MarshalJSON implements custom JSON marshalling
|
||||||
|
@ -20,9 +19,6 @@ func (dc DockerContext) MarshalJSON() ([]byte, error) {
|
||||||
if dc.Description != "" {
|
if dc.Description != "" {
|
||||||
s["Description"] = dc.Description
|
s["Description"] = dc.Description
|
||||||
}
|
}
|
||||||
if dc.StackOrchestrator != "" {
|
|
||||||
s["StackOrchestrator"] = dc.StackOrchestrator
|
|
||||||
}
|
|
||||||
if dc.AdditionalFields != nil {
|
if dc.AdditionalFields != nil {
|
||||||
for k, v := range dc.AdditionalFields {
|
for k, v := range dc.AdditionalFields {
|
||||||
s[k] = v
|
s[k] = v
|
||||||
|
@ -41,8 +37,6 @@ func (dc *DockerContext) UnmarshalJSON(payload []byte) error {
|
||||||
switch k {
|
switch k {
|
||||||
case "Description":
|
case "Description":
|
||||||
dc.Description = v.(string)
|
dc.Description = v.(string)
|
||||||
case "StackOrchestrator":
|
|
||||||
dc.StackOrchestrator = Orchestrator(v.(string))
|
|
||||||
default:
|
default:
|
||||||
if dc.AdditionalFields == nil {
|
if dc.AdditionalFields == nil {
|
||||||
dc.AdditionalFields = make(map[string]interface{})
|
dc.AdditionalFields = make(map[string]interface{})
|
||||||
|
|
|
@ -3,7 +3,6 @@ package context
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
|
@ -59,10 +58,12 @@ func newCreateCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
"default-stack-orchestrator", "",
|
"default-stack-orchestrator", "",
|
||||||
"Default orchestrator for stack operations to use with this context (swarm|kubernetes|all)")
|
"Default orchestrator for stack operations to use with this context (swarm|kubernetes|all)")
|
||||||
flags.SetAnnotation("default-stack-orchestrator", "deprecated", nil)
|
flags.SetAnnotation("default-stack-orchestrator", "deprecated", nil)
|
||||||
|
flags.MarkDeprecated("default-stack-orchestrator", "option will be ignored")
|
||||||
flags.StringToStringVar(&opts.Docker, "docker", nil, "set the docker endpoint")
|
flags.StringToStringVar(&opts.Docker, "docker", nil, "set the docker endpoint")
|
||||||
flags.StringToStringVar(&opts.Kubernetes, "kubernetes", nil, "set the kubernetes endpoint")
|
flags.StringToStringVar(&opts.Kubernetes, "kubernetes", nil, "set the kubernetes endpoint")
|
||||||
flags.SetAnnotation("kubernetes", "kubernetes", nil)
|
flags.SetAnnotation("kubernetes", "kubernetes", nil)
|
||||||
flags.SetAnnotation("kubernetes", "deprecated", nil)
|
flags.SetAnnotation("kubernetes", "deprecated", nil)
|
||||||
|
flags.MarkDeprecated("kubernetes", "option will be ignored")
|
||||||
flags.StringVar(&opts.From, "from", "", "create context from a named context")
|
flags.StringVar(&opts.From, "from", "", "create context from a named context")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -70,20 +71,17 @@ func newCreateCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
// RunCreate creates a Docker context
|
// RunCreate creates a Docker context
|
||||||
func RunCreate(cli command.Cli, o *CreateOptions) error {
|
func RunCreate(cli command.Cli, o *CreateOptions) error {
|
||||||
s := cli.ContextStore()
|
s := cli.ContextStore()
|
||||||
if err := checkContextNameForCreation(s, o.Name); err != nil {
|
err := checkContextNameForCreation(s, o.Name)
|
||||||
return err
|
|
||||||
}
|
|
||||||
stackOrchestrator, err := command.NormalizeOrchestrator(o.DefaultStackOrchestrator)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "unable to parse default-stack-orchestrator")
|
return err
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case o.From == "" && o.Docker == nil && o.Kubernetes == nil:
|
case o.From == "" && o.Docker == nil && o.Kubernetes == nil:
|
||||||
err = createFromExistingContext(s, cli.CurrentContext(), stackOrchestrator, o)
|
err = createFromExistingContext(s, cli.CurrentContext(), o)
|
||||||
case o.From != "":
|
case o.From != "":
|
||||||
err = createFromExistingContext(s, o.From, stackOrchestrator, o)
|
err = createFromExistingContext(s, o.From, o)
|
||||||
default:
|
default:
|
||||||
err = createNewContext(o, stackOrchestrator, cli, s)
|
err = createNewContext(o, cli, s)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Fprintln(cli.Out(), o.Name)
|
fmt.Fprintln(cli.Out(), o.Name)
|
||||||
|
@ -92,11 +90,11 @@ func RunCreate(cli command.Cli, o *CreateOptions) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNewContext(o *CreateOptions, stackOrchestrator command.Orchestrator, cli command.Cli, s store.Writer) error {
|
func createNewContext(o *CreateOptions, cli command.Cli, s store.Writer) error {
|
||||||
if o.Docker == nil {
|
if o.Docker == nil {
|
||||||
return errors.New("docker endpoint configuration is required")
|
return errors.New("docker endpoint configuration is required")
|
||||||
}
|
}
|
||||||
contextMetadata := newContextMetadata(stackOrchestrator, o)
|
contextMetadata := newContextMetadata(o)
|
||||||
contextTLSData := store.ContextTLSData{
|
contextTLSData := store.ContextTLSData{
|
||||||
Endpoints: make(map[string]store.EndpointTLSData),
|
Endpoints: make(map[string]store.EndpointTLSData),
|
||||||
}
|
}
|
||||||
|
@ -108,10 +106,7 @@ func createNewContext(o *CreateOptions, stackOrchestrator command.Orchestrator,
|
||||||
if dockerTLS != nil {
|
if dockerTLS != nil {
|
||||||
contextTLSData.Endpoints[docker.DockerEndpoint] = *dockerTLS
|
contextTLSData.Endpoints[docker.DockerEndpoint] = *dockerTLS
|
||||||
}
|
}
|
||||||
if len(o.Kubernetes) != 0 {
|
if err := validateEndpoints(contextMetadata); err != nil {
|
||||||
logrus.Warn("kubernetes orchestrator is deprecated")
|
|
||||||
}
|
|
||||||
if err := validateEndpointsAndOrchestrator(contextMetadata); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.CreateOrUpdate(contextMetadata); err != nil {
|
if err := s.CreateOrUpdate(contextMetadata); err != nil {
|
||||||
|
@ -136,26 +131,24 @@ func checkContextNameForCreation(s store.Reader, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFromExistingContext(s store.ReaderWriter, fromContextName string, stackOrchestrator command.Orchestrator, o *CreateOptions) error {
|
func createFromExistingContext(s store.ReaderWriter, fromContextName string, o *CreateOptions) error {
|
||||||
if len(o.Docker) != 0 || len(o.Kubernetes) != 0 {
|
if len(o.Docker) != 0 || len(o.Kubernetes) != 0 {
|
||||||
return errors.New("cannot use --docker or --kubernetes flags when --from is set")
|
return errors.New("cannot use --docker or --kubernetes flags when --from is set")
|
||||||
}
|
}
|
||||||
reader := store.Export(fromContextName, &descriptionAndOrchestratorStoreDecorator{
|
reader := store.Export(fromContextName, &descriptionDecorator{
|
||||||
Reader: s,
|
Reader: s,
|
||||||
description: o.Description,
|
description: o.Description,
|
||||||
orchestrator: stackOrchestrator,
|
|
||||||
})
|
})
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
return store.Import(o.Name, s, reader)
|
return store.Import(o.Name, s, reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
type descriptionAndOrchestratorStoreDecorator struct {
|
type descriptionDecorator struct {
|
||||||
store.Reader
|
store.Reader
|
||||||
description string
|
description string
|
||||||
orchestrator command.Orchestrator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *descriptionAndOrchestratorStoreDecorator) GetMetadata(name string) (store.Metadata, error) {
|
func (d *descriptionDecorator) GetMetadata(name string) (store.Metadata, error) {
|
||||||
c, err := d.Reader.GetMetadata(name)
|
c, err := d.Reader.GetMetadata(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c, err
|
return c, err
|
||||||
|
@ -167,19 +160,15 @@ func (d *descriptionAndOrchestratorStoreDecorator) GetMetadata(name string) (sto
|
||||||
if d.description != "" {
|
if d.description != "" {
|
||||||
typedContext.Description = d.description
|
typedContext.Description = d.description
|
||||||
}
|
}
|
||||||
if d.orchestrator != command.Orchestrator("") {
|
|
||||||
typedContext.StackOrchestrator = d.orchestrator
|
|
||||||
}
|
|
||||||
c.Metadata = typedContext
|
c.Metadata = typedContext
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContextMetadata(stackOrchestrator command.Orchestrator, o *CreateOptions) store.Metadata {
|
func newContextMetadata(o *CreateOptions) store.Metadata {
|
||||||
return store.Metadata{
|
return store.Metadata{
|
||||||
Endpoints: make(map[string]interface{}),
|
Endpoints: make(map[string]interface{}),
|
||||||
Metadata: command.DockerContext{
|
Metadata: command.DockerContext{
|
||||||
Description: o.Description,
|
Description: o.Description,
|
||||||
StackOrchestrator: stackOrchestrator,
|
|
||||||
},
|
},
|
||||||
Name: o.Name,
|
Name: o.Name,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/docker/cli/cli/context/store"
|
"github.com/docker/cli/cli/context/store"
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
"gotest.tools/v3/assert"
|
"gotest.tools/v3/assert"
|
||||||
"gotest.tools/v3/env"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeFakeCli(t *testing.T, opts ...func(*test.FakeCli)) (*test.FakeCli, func()) {
|
func makeFakeCli(t *testing.T, opts ...func(*test.FakeCli)) (*test.FakeCli, func()) {
|
||||||
|
@ -33,8 +32,7 @@ func makeFakeCli(t *testing.T, opts ...func(*test.FakeCli)) (*test.FakeCli, func
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Metadata: command.DockerContext{
|
Metadata: command.DockerContext{
|
||||||
Description: "",
|
Description: "",
|
||||||
StackOrchestrator: command.OrchestratorSwarm,
|
|
||||||
},
|
},
|
||||||
Name: command.DefaultContextName,
|
Name: command.DefaultContextName,
|
||||||
},
|
},
|
||||||
|
@ -59,7 +57,7 @@ func withCliConfig(configFile *configfile.ConfigFile) func(*test.FakeCli) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateInvalids(t *testing.T) {
|
func TestCreate(t *testing.T) {
|
||||||
cli, cleanup := makeFakeCli(t)
|
cli, cleanup := makeFakeCli(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
assert.NilError(t, cli.ContextStore().CreateOrUpdate(store.Metadata{Name: "existing-context"}))
|
assert.NilError(t, cli.ContextStore().CreateOrUpdate(store.Metadata{Name: "existing-context"}))
|
||||||
|
@ -102,7 +100,7 @@ func TestCreateInvalids(t *testing.T) {
|
||||||
Name: "invalid-orchestrator",
|
Name: "invalid-orchestrator",
|
||||||
DefaultStackOrchestrator: "invalid",
|
DefaultStackOrchestrator: "invalid",
|
||||||
},
|
},
|
||||||
expecterErr: `specified orchestrator "invalid" is invalid, please use either kubernetes, swarm or all`,
|
expecterErr: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
options: CreateOptions{
|
options: CreateOptions{
|
||||||
|
@ -158,37 +156,25 @@ func TestCreateOrchestratorEmpty(t *testing.T) {
|
||||||
|
|
||||||
func TestCreateFromContext(t *testing.T) {
|
func TestCreateFromContext(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
description string
|
description string
|
||||||
orchestrator string
|
expectedDescription string
|
||||||
expectedDescription string
|
docker map[string]string
|
||||||
docker map[string]string
|
kubernetes map[string]string
|
||||||
kubernetes map[string]string
|
|
||||||
expectedOrchestrator command.Orchestrator
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no-override",
|
name: "no-override",
|
||||||
expectedDescription: "original description",
|
expectedDescription: "original description",
|
||||||
expectedOrchestrator: command.OrchestratorSwarm,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "override-description",
|
name: "override-description",
|
||||||
description: "new description",
|
description: "new description",
|
||||||
expectedDescription: "new description",
|
expectedDescription: "new description",
|
||||||
expectedOrchestrator: command.OrchestratorSwarm,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "override-orchestrator",
|
|
||||||
orchestrator: "kubernetes",
|
|
||||||
expectedDescription: "original description",
|
|
||||||
expectedOrchestrator: command.OrchestratorKubernetes,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cli, cleanup := makeFakeCli(t)
|
cli, cleanup := makeFakeCli(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
revert := env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig")
|
|
||||||
defer revert()
|
|
||||||
cli.ResetOutputBuffers()
|
cli.ResetOutputBuffers()
|
||||||
assert.NilError(t, RunCreate(cli, &CreateOptions{
|
assert.NilError(t, RunCreate(cli, &CreateOptions{
|
||||||
Name: "original",
|
Name: "original",
|
||||||
|
@ -196,10 +182,6 @@ func TestCreateFromContext(t *testing.T) {
|
||||||
Docker: map[string]string{
|
Docker: map[string]string{
|
||||||
keyHost: "tcp://42.42.42.42:2375",
|
keyHost: "tcp://42.42.42.42:2375",
|
||||||
},
|
},
|
||||||
Kubernetes: map[string]string{
|
|
||||||
keyFrom: "default",
|
|
||||||
},
|
|
||||||
DefaultStackOrchestrator: "swarm",
|
|
||||||
}))
|
}))
|
||||||
assertContextCreateLogging(t, cli, "original")
|
assertContextCreateLogging(t, cli, "original")
|
||||||
|
|
||||||
|
@ -210,10 +192,6 @@ func TestCreateFromContext(t *testing.T) {
|
||||||
Docker: map[string]string{
|
Docker: map[string]string{
|
||||||
keyHost: "tcp://24.24.24.24:2375",
|
keyHost: "tcp://24.24.24.24:2375",
|
||||||
},
|
},
|
||||||
Kubernetes: map[string]string{
|
|
||||||
keyFrom: "default",
|
|
||||||
},
|
|
||||||
DefaultStackOrchestrator: "swarm",
|
|
||||||
}))
|
}))
|
||||||
assertContextCreateLogging(t, cli, "dummy")
|
assertContextCreateLogging(t, cli, "dummy")
|
||||||
|
|
||||||
|
@ -224,12 +202,10 @@ func TestCreateFromContext(t *testing.T) {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
cli.ResetOutputBuffers()
|
cli.ResetOutputBuffers()
|
||||||
err := RunCreate(cli, &CreateOptions{
|
err := RunCreate(cli, &CreateOptions{
|
||||||
From: "original",
|
From: "original",
|
||||||
Name: c.name,
|
Name: c.name,
|
||||||
Description: c.description,
|
Description: c.description,
|
||||||
DefaultStackOrchestrator: c.orchestrator,
|
Docker: c.docker,
|
||||||
Docker: c.docker,
|
|
||||||
Kubernetes: c.kubernetes,
|
|
||||||
})
|
})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assertContextCreateLogging(t, cli, c.name)
|
assertContextCreateLogging(t, cli, c.name)
|
||||||
|
@ -240,7 +216,6 @@ func TestCreateFromContext(t *testing.T) {
|
||||||
dockerEndpoint, err := docker.EndpointFromContext(newContext)
|
dockerEndpoint, err := docker.EndpointFromContext(newContext)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, newContextTyped.Description, c.expectedDescription)
|
assert.Equal(t, newContextTyped.Description, c.expectedDescription)
|
||||||
assert.Equal(t, newContextTyped.StackOrchestrator, c.expectedOrchestrator)
|
|
||||||
assert.Equal(t, dockerEndpoint.Host, "tcp://42.42.42.42:2375")
|
assert.Equal(t, dockerEndpoint.Host, "tcp://42.42.42.42:2375")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -248,29 +223,24 @@ func TestCreateFromContext(t *testing.T) {
|
||||||
|
|
||||||
func TestCreateFromCurrent(t *testing.T) {
|
func TestCreateFromCurrent(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
description string
|
description string
|
||||||
orchestrator string
|
orchestrator string
|
||||||
expectedDescription string
|
expectedDescription string
|
||||||
expectedOrchestrator command.Orchestrator
|
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no-override",
|
name: "no-override",
|
||||||
expectedDescription: "original description",
|
expectedDescription: "original description",
|
||||||
expectedOrchestrator: command.OrchestratorSwarm,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "override-description",
|
name: "override-description",
|
||||||
description: "new description",
|
description: "new description",
|
||||||
expectedDescription: "new description",
|
expectedDescription: "new description",
|
||||||
expectedOrchestrator: command.OrchestratorSwarm,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cli, cleanup := makeFakeCli(t)
|
cli, cleanup := makeFakeCli(t)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
revert := env.Patch(t, "KUBECONFIG", "./testdata/test-kubeconfig")
|
|
||||||
defer revert()
|
|
||||||
cli.ResetOutputBuffers()
|
cli.ResetOutputBuffers()
|
||||||
assert.NilError(t, RunCreate(cli, &CreateOptions{
|
assert.NilError(t, RunCreate(cli, &CreateOptions{
|
||||||
Name: "original",
|
Name: "original",
|
||||||
|
@ -278,10 +248,6 @@ func TestCreateFromCurrent(t *testing.T) {
|
||||||
Docker: map[string]string{
|
Docker: map[string]string{
|
||||||
keyHost: "tcp://42.42.42.42:2375",
|
keyHost: "tcp://42.42.42.42:2375",
|
||||||
},
|
},
|
||||||
Kubernetes: map[string]string{
|
|
||||||
keyFrom: "default",
|
|
||||||
},
|
|
||||||
DefaultStackOrchestrator: "swarm",
|
|
||||||
}))
|
}))
|
||||||
assertContextCreateLogging(t, cli, "original")
|
assertContextCreateLogging(t, cli, "original")
|
||||||
|
|
||||||
|
@ -292,9 +258,8 @@ func TestCreateFromCurrent(t *testing.T) {
|
||||||
t.Run(c.name, func(t *testing.T) {
|
t.Run(c.name, func(t *testing.T) {
|
||||||
cli.ResetOutputBuffers()
|
cli.ResetOutputBuffers()
|
||||||
err := RunCreate(cli, &CreateOptions{
|
err := RunCreate(cli, &CreateOptions{
|
||||||
Name: c.name,
|
Name: c.name,
|
||||||
Description: c.description,
|
Description: c.description,
|
||||||
DefaultStackOrchestrator: c.orchestrator,
|
|
||||||
})
|
})
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assertContextCreateLogging(t, cli, c.name)
|
assertContextCreateLogging(t, cli, c.name)
|
||||||
|
@ -305,7 +270,6 @@ func TestCreateFromCurrent(t *testing.T) {
|
||||||
dockerEndpoint, err := docker.EndpointFromContext(newContext)
|
dockerEndpoint, err := docker.EndpointFromContext(newContext)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, newContextTyped.Description, c.expectedDescription)
|
assert.Equal(t, newContextTyped.Description, c.expectedDescription)
|
||||||
assert.Equal(t, newContextTyped.StackOrchestrator, c.expectedOrchestrator)
|
|
||||||
assert.Equal(t, dockerEndpoint.Host, "tcp://42.42.42.42:2375")
|
assert.Equal(t, dockerEndpoint.Host, "tcp://42.42.42.42:2375")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,11 +59,10 @@ func runList(dockerCli command.Cli, opts *listOptions) error {
|
||||||
meta.Description = "Current DOCKER_HOST based configuration"
|
meta.Description = "Current DOCKER_HOST based configuration"
|
||||||
}
|
}
|
||||||
desc := formatter.ClientContext{
|
desc := formatter.ClientContext{
|
||||||
Name: rawMeta.Name,
|
Name: rawMeta.Name,
|
||||||
Current: rawMeta.Name == curContext,
|
Current: rawMeta.Name == curContext,
|
||||||
Description: meta.Description,
|
Description: meta.Description,
|
||||||
StackOrchestrator: string(meta.StackOrchestrator),
|
DockerEndpoint: dockerEndpoint.Host,
|
||||||
DockerEndpoint: dockerEndpoint.Host,
|
|
||||||
}
|
}
|
||||||
contexts = append(contexts, &desc)
|
contexts = append(contexts, &desc)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
{
|
{
|
||||||
"Name": "current",
|
"Name": "current",
|
||||||
"Metadata": {
|
"Metadata": {
|
||||||
"Description": "description of current",
|
"Description": "description of current"
|
||||||
"StackOrchestrator": "all"
|
|
||||||
},
|
},
|
||||||
"Endpoints": {
|
"Endpoints": {
|
||||||
"docker": {
|
"docker": {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
NAME DESCRIPTION DOCKER ENDPOINT ORCHESTRATOR
|
NAME DESCRIPTION DOCKER ENDPOINT
|
||||||
current * description of current https://someswarmserver.example.com all
|
current * description of current https://someswarmserver.example.com
|
||||||
default Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
|
default Current DOCKER_HOST based configuration unix:///var/run/docker.sock
|
||||||
other description of other https://someswarmserver.example.com all
|
other description of other https://someswarmserver.example.com
|
||||||
unset description of unset https://someswarmserver.example.com
|
unset description of unset https://someswarmserver.example.com
|
||||||
|
|
|
@ -3,7 +3,6 @@ package context
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
|
@ -58,10 +57,12 @@ func newUpdateCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
"default-stack-orchestrator", "",
|
"default-stack-orchestrator", "",
|
||||||
"Default orchestrator for stack operations to use with this context (swarm|kubernetes|all)")
|
"Default orchestrator for stack operations to use with this context (swarm|kubernetes|all)")
|
||||||
flags.SetAnnotation("default-stack-orchestrator", "deprecated", nil)
|
flags.SetAnnotation("default-stack-orchestrator", "deprecated", nil)
|
||||||
|
flags.MarkDeprecated("default-stack-orchestrator", "option will be ignored")
|
||||||
flags.StringToStringVar(&opts.Docker, "docker", nil, "set the docker endpoint")
|
flags.StringToStringVar(&opts.Docker, "docker", nil, "set the docker endpoint")
|
||||||
flags.StringToStringVar(&opts.Kubernetes, "kubernetes", nil, "set the kubernetes endpoint")
|
flags.StringToStringVar(&opts.Kubernetes, "kubernetes", nil, "set the kubernetes endpoint")
|
||||||
flags.SetAnnotation("kubernetes", "kubernetes", nil)
|
flags.SetAnnotation("kubernetes", "kubernetes", nil)
|
||||||
flags.SetAnnotation("kubernetes", "deprecated", nil)
|
flags.SetAnnotation("kubernetes", "deprecated", nil)
|
||||||
|
flags.MarkDeprecated("kubernetes", "option will be ignored")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,13 +80,6 @@ func RunUpdate(cli command.Cli, o *UpdateOptions) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if o.DefaultStackOrchestrator != "" {
|
|
||||||
stackOrchestrator, err := command.NormalizeOrchestrator(o.DefaultStackOrchestrator)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "unable to parse default-stack-orchestrator")
|
|
||||||
}
|
|
||||||
dockerContext.StackOrchestrator = stackOrchestrator
|
|
||||||
}
|
|
||||||
if o.Description != "" {
|
if o.Description != "" {
|
||||||
dockerContext.Description = o.Description
|
dockerContext.Description = o.Description
|
||||||
}
|
}
|
||||||
|
@ -102,10 +96,7 @@ func RunUpdate(cli command.Cli, o *UpdateOptions) error {
|
||||||
c.Endpoints[docker.DockerEndpoint] = dockerEP
|
c.Endpoints[docker.DockerEndpoint] = dockerEP
|
||||||
tlsDataToReset[docker.DockerEndpoint] = dockerTLS
|
tlsDataToReset[docker.DockerEndpoint] = dockerTLS
|
||||||
}
|
}
|
||||||
if len(o.Kubernetes) != 0 {
|
if err := validateEndpoints(c); err != nil {
|
||||||
logrus.Warn("kubernetes orchestrator is deprecated")
|
|
||||||
}
|
|
||||||
if err := validateEndpointsAndOrchestrator(c); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.CreateOrUpdate(c); err != nil {
|
if err := s.CreateOrUpdate(c); err != nil {
|
||||||
|
@ -122,7 +113,7 @@ func RunUpdate(cli command.Cli, o *UpdateOptions) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateEndpointsAndOrchestrator(c store.Metadata) error {
|
func validateEndpoints(c store.Metadata) error {
|
||||||
_, err := command.GetDockerContext(c)
|
_, err := command.GetDockerContext(c)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ func TestUpdateDescriptionOnly(t *testing.T) {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
dc, err := command.GetDockerContext(c)
|
dc, err := command.GetDockerContext(c)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, dc.StackOrchestrator, command.OrchestratorSwarm)
|
|
||||||
assert.Equal(t, dc.Description, "description")
|
assert.Equal(t, dc.Description, "description")
|
||||||
|
|
||||||
assert.Equal(t, "test\n", cli.OutBuffer().String())
|
assert.Equal(t, "test\n", cli.OutBuffer().String())
|
||||||
|
@ -49,7 +48,6 @@ func TestUpdateDockerOnly(t *testing.T) {
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
dc, err := command.GetDockerContext(c)
|
dc, err := command.GetDockerContext(c)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, dc.StackOrchestrator, command.OrchestratorSwarm)
|
|
||||||
assert.Equal(t, dc.Description, "description of test")
|
assert.Equal(t, dc.Description, "description of test")
|
||||||
assert.Check(t, cmp.Contains(c.Endpoints, docker.DockerEndpoint))
|
assert.Check(t, cmp.Contains(c.Endpoints, docker.DockerEndpoint))
|
||||||
assert.Equal(t, c.Endpoints[docker.DockerEndpoint].(docker.EndpointMeta).Host, "tcp://some-host")
|
assert.Equal(t, c.Endpoints[docker.DockerEndpoint].(docker.EndpointMeta).Host, "tcp://some-host")
|
||||||
|
|
|
@ -9,19 +9,17 @@ import (
|
||||||
|
|
||||||
func TestDockerContextMetadataKeepAdditionalFields(t *testing.T) {
|
func TestDockerContextMetadataKeepAdditionalFields(t *testing.T) {
|
||||||
c := DockerContext{
|
c := DockerContext{
|
||||||
Description: "test",
|
Description: "test",
|
||||||
StackOrchestrator: OrchestratorSwarm,
|
|
||||||
AdditionalFields: map[string]interface{}{
|
AdditionalFields: map[string]interface{}{
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
jsonBytes, err := json.Marshal(c)
|
jsonBytes, err := json.Marshal(c)
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, `{"Description":"test","StackOrchestrator":"swarm","foo":"bar"}`, string(jsonBytes))
|
assert.Equal(t, `{"Description":"test","foo":"bar"}`, string(jsonBytes))
|
||||||
|
|
||||||
var c2 DockerContext
|
var c2 DockerContext
|
||||||
assert.NilError(t, json.Unmarshal(jsonBytes, &c2))
|
assert.NilError(t, json.Unmarshal(jsonBytes, &c2))
|
||||||
assert.Equal(t, c2.AdditionalFields["foo"], "bar")
|
assert.Equal(t, c2.AdditionalFields["foo"], "bar")
|
||||||
assert.Equal(t, c2.StackOrchestrator, OrchestratorSwarm)
|
|
||||||
assert.Equal(t, c2.Description, "test")
|
assert.Equal(t, c2.Description, "test")
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,23 +41,18 @@ type EndpointDefaultResolver interface {
|
||||||
// the lack of a default (e.g. because the config file which
|
// the lack of a default (e.g. because the config file which
|
||||||
// would contain it is missing). If there is no default then
|
// would contain it is missing). If there is no default then
|
||||||
// returns nil, nil, nil.
|
// returns nil, nil, nil.
|
||||||
ResolveDefault(Orchestrator) (interface{}, *store.EndpointTLSData, error)
|
ResolveDefault() (interface{}, *store.EndpointTLSData, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveDefaultContext creates a Metadata for the current CLI invocation parameters
|
// ResolveDefaultContext creates a Metadata for the current CLI invocation parameters
|
||||||
func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.ConfigFile, storeconfig store.Config, stderr io.Writer) (*DefaultContext, error) {
|
func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.ConfigFile, storeconfig store.Config, stderr io.Writer) (*DefaultContext, error) {
|
||||||
stackOrchestrator, err := GetStackOrchestrator("", "", config.StackOrchestrator, stderr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
contextTLSData := store.ContextTLSData{
|
contextTLSData := store.ContextTLSData{
|
||||||
Endpoints: make(map[string]store.EndpointTLSData),
|
Endpoints: make(map[string]store.EndpointTLSData),
|
||||||
}
|
}
|
||||||
contextMetadata := store.Metadata{
|
contextMetadata := store.Metadata{
|
||||||
Endpoints: make(map[string]interface{}),
|
Endpoints: make(map[string]interface{}),
|
||||||
Metadata: DockerContext{
|
Metadata: DockerContext{
|
||||||
Description: "",
|
Description: "",
|
||||||
StackOrchestrator: stackOrchestrator,
|
|
||||||
},
|
},
|
||||||
Name: DefaultContextName,
|
Name: DefaultContextName,
|
||||||
}
|
}
|
||||||
|
@ -77,7 +72,7 @@ func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.Conf
|
||||||
}
|
}
|
||||||
ep := get()
|
ep := get()
|
||||||
if i, ok := ep.(EndpointDefaultResolver); ok {
|
if i, ok := ep.(EndpointDefaultResolver); ok {
|
||||||
meta, tls, err := i.ResolveDefault(stackOrchestrator)
|
meta, tls, err := i.ResolveDefault()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,6 @@ func TestDefaultContextInitializer(t *testing.T) {
|
||||||
}, cli.ConfigFile(), DefaultContextStoreConfig(), cli.Err())
|
}, cli.ConfigFile(), DefaultContextStoreConfig(), cli.Err())
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
assert.Equal(t, "default", ctx.Meta.Name)
|
assert.Equal(t, "default", ctx.Meta.Name)
|
||||||
assert.Equal(t, OrchestratorSwarm, ctx.Meta.Metadata.(DockerContext).StackOrchestrator)
|
|
||||||
assert.DeepEqual(t, "ssh://someswarmserver", ctx.Meta.Endpoints[docker.DockerEndpoint].(docker.EndpointMeta).Host)
|
assert.DeepEqual(t, "ssh://someswarmserver", ctx.Meta.Endpoints[docker.DockerEndpoint].(docker.EndpointMeta).Host)
|
||||||
golden.Assert(t, string(ctx.TLS.Endpoints[docker.DockerEndpoint].Files["ca.pem"]), "ca.pem")
|
golden.Assert(t, string(ctx.TLS.Endpoints[docker.DockerEndpoint].Files["ca.pem"]), "ca.pem")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@ package formatter
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ClientContextTableFormat is the default client context format
|
// ClientContextTableFormat is the default client context format
|
||||||
ClientContextTableFormat = "table {{.Name}}{{if .Current}} *{{end}}\t{{.Description}}\t{{.DockerEndpoint}}\t{{.StackOrchestrator}}"
|
ClientContextTableFormat = "table {{.Name}}{{if .Current}} *{{end}}\t{{.Description}}\t{{.DockerEndpoint}}"
|
||||||
|
|
||||||
dockerEndpointHeader = "DOCKER ENDPOINT"
|
dockerEndpointHeader = "DOCKER ENDPOINT"
|
||||||
stackOrchestrastorHeader = "ORCHESTRATOR"
|
quietContextFormat = "{{.Name}}"
|
||||||
quietContextFormat = "{{.Name}}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewClientContextFormat returns a Format for rendering using a Context
|
// NewClientContextFormat returns a Format for rendering using a Context
|
||||||
|
@ -22,11 +21,10 @@ func NewClientContextFormat(source string, quiet bool) Format {
|
||||||
|
|
||||||
// ClientContext is a context for display
|
// ClientContext is a context for display
|
||||||
type ClientContext struct {
|
type ClientContext struct {
|
||||||
Name string
|
Name string
|
||||||
Description string
|
Description string
|
||||||
DockerEndpoint string
|
DockerEndpoint string
|
||||||
StackOrchestrator string
|
Current bool
|
||||||
Current bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientContextWrite writes formatted contexts using the Context
|
// ClientContextWrite writes formatted contexts using the Context
|
||||||
|
@ -50,10 +48,9 @@ type clientContextContext struct {
|
||||||
func newClientContextContext() *clientContextContext {
|
func newClientContextContext() *clientContextContext {
|
||||||
ctx := clientContextContext{}
|
ctx := clientContextContext{}
|
||||||
ctx.Header = SubHeaderContext{
|
ctx.Header = SubHeaderContext{
|
||||||
"Name": NameHeader,
|
"Name": NameHeader,
|
||||||
"Description": DescriptionHeader,
|
"Description": DescriptionHeader,
|
||||||
"DockerEndpoint": dockerEndpointHeader,
|
"DockerEndpoint": dockerEndpointHeader,
|
||||||
"StackOrchestrator": stackOrchestrastorHeader,
|
|
||||||
}
|
}
|
||||||
return &ctx
|
return &ctx
|
||||||
}
|
}
|
||||||
|
@ -81,7 +78,3 @@ func (c *clientContextContext) DockerEndpoint() string {
|
||||||
func (c *clientContextContext) KubernetesEndpoint() string {
|
func (c *clientContextContext) KubernetesEndpoint() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientContextContext) StackOrchestrator() string {
|
|
||||||
return c.c.StackOrchestrator
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Orchestrator type acts as an enum describing supported orchestrators.
|
|
||||||
type Orchestrator string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// OrchestratorKubernetes orchestrator
|
|
||||||
OrchestratorKubernetes = Orchestrator("kubernetes")
|
|
||||||
// OrchestratorSwarm orchestrator
|
|
||||||
OrchestratorSwarm = Orchestrator("swarm")
|
|
||||||
// OrchestratorAll orchestrator
|
|
||||||
OrchestratorAll = Orchestrator("all")
|
|
||||||
orchestratorUnset = Orchestrator("")
|
|
||||||
|
|
||||||
defaultOrchestrator = OrchestratorSwarm
|
|
||||||
envVarDockerStackOrchestrator = "DOCKER_STACK_ORCHESTRATOR"
|
|
||||||
envVarDockerOrchestrator = "DOCKER_ORCHESTRATOR"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HasKubernetes returns true if defined orchestrator has Kubernetes capabilities.
|
|
||||||
// Deprecated: support for kubernetes as orchestrator was removed.
|
|
||||||
func (o Orchestrator) HasKubernetes() bool {
|
|
||||||
return o == OrchestratorKubernetes || o == OrchestratorAll
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasSwarm returns true if defined orchestrator has Swarm capabilities.
|
|
||||||
func (o Orchestrator) HasSwarm() bool {
|
|
||||||
return o == OrchestratorSwarm || o == OrchestratorAll
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasAll returns true if defined orchestrator has both Swarm and Kubernetes capabilities.
|
|
||||||
func (o Orchestrator) HasAll() bool {
|
|
||||||
return o == OrchestratorAll
|
|
||||||
}
|
|
||||||
|
|
||||||
func normalize(value string) (Orchestrator, error) {
|
|
||||||
switch value {
|
|
||||||
case "kubernetes":
|
|
||||||
return OrchestratorKubernetes, nil
|
|
||||||
case "swarm":
|
|
||||||
return OrchestratorSwarm, nil
|
|
||||||
case "", "unset": // unset is the old value for orchestratorUnset. Keep accepting this for backward compat
|
|
||||||
return orchestratorUnset, nil
|
|
||||||
case "all":
|
|
||||||
return OrchestratorAll, nil
|
|
||||||
default:
|
|
||||||
return defaultOrchestrator, fmt.Errorf("specified orchestrator %q is invalid, please use either kubernetes, swarm or all", value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NormalizeOrchestrator parses an orchestrator value and checks if it is valid
|
|
||||||
func NormalizeOrchestrator(value string) (Orchestrator, error) {
|
|
||||||
return normalize(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStackOrchestrator checks DOCKER_STACK_ORCHESTRATOR environment variable and configuration file
|
|
||||||
// orchestrator value and returns user defined Orchestrator.
|
|
||||||
func GetStackOrchestrator(flagValue, contextValue, globalDefault string, stderr io.Writer) (Orchestrator, error) {
|
|
||||||
// Check flag
|
|
||||||
if o, err := normalize(flagValue); o != orchestratorUnset {
|
|
||||||
return o, err
|
|
||||||
}
|
|
||||||
// Check environment variable
|
|
||||||
env := os.Getenv(envVarDockerStackOrchestrator)
|
|
||||||
if env == "" && os.Getenv(envVarDockerOrchestrator) != "" {
|
|
||||||
fmt.Fprintf(stderr, "WARNING: experimental environment variable %s is set. Please use %s instead\n", envVarDockerOrchestrator, envVarDockerStackOrchestrator)
|
|
||||||
}
|
|
||||||
if o, err := normalize(env); o != orchestratorUnset {
|
|
||||||
return o, err
|
|
||||||
}
|
|
||||||
if o, err := normalize(contextValue); o != orchestratorUnset {
|
|
||||||
return o, err
|
|
||||||
}
|
|
||||||
if o, err := normalize(globalDefault); o != orchestratorUnset {
|
|
||||||
return o, err
|
|
||||||
}
|
|
||||||
// Nothing set, use default orchestrator
|
|
||||||
return defaultOrchestrator, nil
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
package command
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"gotest.tools/v3/assert"
|
|
||||||
is "gotest.tools/v3/assert/cmp"
|
|
||||||
"gotest.tools/v3/env"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestOrchestratorSwitch(t *testing.T) {
|
|
||||||
var testcases = []struct {
|
|
||||||
doc string
|
|
||||||
globalOrchestrator string
|
|
||||||
envOrchestrator string
|
|
||||||
flagOrchestrator string
|
|
||||||
contextOrchestrator string
|
|
||||||
expectedOrchestrator string
|
|
||||||
expectedSwarm bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
doc: "default",
|
|
||||||
expectedOrchestrator: "swarm",
|
|
||||||
expectedSwarm: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
doc: "allOrchestratorFlag",
|
|
||||||
flagOrchestrator: "all",
|
|
||||||
expectedOrchestrator: "all",
|
|
||||||
expectedSwarm: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
doc: "contextOverridesConfigFile",
|
|
||||||
globalOrchestrator: "kubernetes",
|
|
||||||
contextOrchestrator: "swarm",
|
|
||||||
expectedOrchestrator: "swarm",
|
|
||||||
expectedSwarm: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
doc: "envOverridesConfigFile",
|
|
||||||
globalOrchestrator: "kubernetes",
|
|
||||||
envOrchestrator: "swarm",
|
|
||||||
expectedOrchestrator: "swarm",
|
|
||||||
expectedSwarm: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
doc: "flagOverridesEnv",
|
|
||||||
envOrchestrator: "kubernetes",
|
|
||||||
flagOrchestrator: "swarm",
|
|
||||||
expectedOrchestrator: "swarm",
|
|
||||||
expectedSwarm: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testcase := range testcases {
|
|
||||||
t.Run(testcase.doc, func(t *testing.T) {
|
|
||||||
if testcase.envOrchestrator != "" {
|
|
||||||
defer env.Patch(t, "DOCKER_STACK_ORCHESTRATOR", testcase.envOrchestrator)()
|
|
||||||
}
|
|
||||||
orchestrator, err := GetStackOrchestrator(testcase.flagOrchestrator, testcase.contextOrchestrator, testcase.globalOrchestrator, ioutil.Discard)
|
|
||||||
assert.NilError(t, err)
|
|
||||||
assert.Check(t, is.Equal(testcase.expectedSwarm, orchestrator.HasSwarm()))
|
|
||||||
assert.Check(t, is.Equal(testcase.expectedOrchestrator, string(orchestrator)))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +1,20 @@
|
||||||
package stack
|
package stack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/cli/command"
|
"github.com/docker/cli/cli/command"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type commonOptions struct {
|
|
||||||
orchestrator command.Orchestrator
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *commonOptions) Orchestrator() command.Orchestrator {
|
|
||||||
if o == nil {
|
|
||||||
return command.OrchestratorSwarm
|
|
||||||
}
|
|
||||||
return o.orchestrator
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewStackCommand returns a cobra command for `stack` subcommands
|
// NewStackCommand returns a cobra command for `stack` subcommands
|
||||||
func NewStackCommand(dockerCli command.Cli) *cobra.Command {
|
func NewStackCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
var opts commonOptions
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "stack [OPTIONS]",
|
Use: "stack [OPTIONS]",
|
||||||
Short: "Manage Docker stacks",
|
Short: "Manage Docker stacks",
|
||||||
Args: cli.NoArgs,
|
Args: cli.NoArgs,
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
RunE: command.ShowHelp(dockerCli.Err()),
|
||||||
orchestrator, err := getOrchestrator(dockerCli, cmd)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
opts.orchestrator = orchestrator
|
|
||||||
hideOrchestrationFlags(cmd, orchestrator)
|
|
||||||
return checkSupportedFlag(cmd, orchestrator)
|
|
||||||
},
|
|
||||||
|
|
||||||
RunE: command.ShowHelp(dockerCli.Err()),
|
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"version": "1.25",
|
"version": "1.25",
|
||||||
},
|
},
|
||||||
|
@ -50,62 +25,18 @@ func NewStackCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
fmt.Fprintln(dockerCli.Err(), err)
|
fmt.Fprintln(dockerCli.Err(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := cmd.PersistentPreRunE(c, args); err != nil {
|
|
||||||
fmt.Fprintln(dockerCli.Err(), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
hideOrchestrationFlags(c, opts.orchestrator)
|
|
||||||
defaultHelpFunc(c, args)
|
defaultHelpFunc(c, args)
|
||||||
})
|
})
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
newDeployCommand(dockerCli, &opts),
|
newDeployCommand(dockerCli),
|
||||||
newListCommand(dockerCli, &opts),
|
newListCommand(dockerCli),
|
||||||
newPsCommand(dockerCli, &opts),
|
newPsCommand(dockerCli),
|
||||||
newRemoveCommand(dockerCli, &opts),
|
newRemoveCommand(dockerCli),
|
||||||
newServicesCommand(dockerCli, &opts),
|
newServicesCommand(dockerCli),
|
||||||
)
|
)
|
||||||
flags := cmd.PersistentFlags()
|
flags := cmd.PersistentFlags()
|
||||||
flags.String("orchestrator", "", "Orchestrator to use (swarm|all)")
|
flags.String("orchestrator", "", "Orchestrator to use (swarm|all)")
|
||||||
flags.SetAnnotation("orchestrator", "deprecated", nil)
|
flags.SetAnnotation("orchestrator", "deprecated", nil)
|
||||||
|
flags.MarkDeprecated("orchestrator", "option will be ignored")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOrchestrator(dockerCli command.Cli, cmd *cobra.Command) (command.Orchestrator, error) {
|
|
||||||
var orchestratorFlag string
|
|
||||||
if o, err := cmd.Flags().GetString("orchestrator"); err == nil {
|
|
||||||
orchestratorFlag = o
|
|
||||||
}
|
|
||||||
return dockerCli.StackOrchestrator(orchestratorFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
func hideOrchestrationFlags(cmd *cobra.Command, orchestrator command.Orchestrator) {
|
|
||||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
|
||||||
if _, ok := f.Annotations["swarm"]; ok && !orchestrator.HasSwarm() {
|
|
||||||
f.Hidden = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
for _, subcmd := range cmd.Commands() {
|
|
||||||
hideOrchestrationFlags(subcmd, orchestrator)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkSupportedFlag(cmd *cobra.Command, orchestrator command.Orchestrator) error {
|
|
||||||
errs := []string{}
|
|
||||||
cmd.Flags().VisitAll(func(f *pflag.Flag) {
|
|
||||||
if !f.Changed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := f.Annotations["swarm"]; ok && !orchestrator.HasSwarm() {
|
|
||||||
errs = append(errs, fmt.Sprintf(`"--%s" is only supported on a Docker cli with swarm features enabled`, f.Name))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
for _, subcmd := range cmd.Commands() {
|
|
||||||
if err := checkSupportedFlag(subcmd, orchestrator); err != nil {
|
|
||||||
errs = append(errs, err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(errs) > 0 {
|
|
||||||
return errors.New(strings.Join(errs, "\n"))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newDeployCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command {
|
func newDeployCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
var opts options.Deploy
|
var opts options.Deploy
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
@ -28,7 +28,7 @@ func newDeployCommand(dockerCli command.Cli, common *commonOptions) *cobra.Comma
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return RunDeploy(dockerCli, cmd.Flags(), config, common.Orchestrator(), opts)
|
return RunDeploy(dockerCli, cmd.Flags(), config, opts)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ func newDeployCommand(dockerCli command.Cli, common *commonOptions) *cobra.Comma
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunDeploy performs a stack deploy against the specified orchestrator
|
// RunDeploy performs a stack deploy against the specified swarm cluster
|
||||||
func RunDeploy(dockerCli command.Cli, flags *pflag.FlagSet, config *composetypes.Config, commonOrchestrator command.Orchestrator, opts options.Deploy) error {
|
func RunDeploy(dockerCli command.Cli, flags *pflag.FlagSet, config *composetypes.Config, opts options.Deploy) error {
|
||||||
return swarm.RunDeploy(dockerCli, opts, config)
|
return swarm.RunDeploy(dockerCli, opts, config)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDeployWithEmptyName(t *testing.T) {
|
func TestDeployWithEmptyName(t *testing.T) {
|
||||||
cmd := newDeployCommand(test.NewFakeCli(&fakeClient{}), nil)
|
cmd := newDeployCommand(test.NewFakeCli(&fakeClient{}))
|
||||||
cmd.SetArgs([]string{"' '"})
|
cmd.SetArgs([]string{"' '"})
|
||||||
cmd.SetOut(ioutil.Discard)
|
cmd.SetOut(ioutil.Discard)
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,9 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// SwarmStackTableFormat is the default Swarm stack format
|
// SwarmStackTableFormat is the default Swarm stack format
|
||||||
SwarmStackTableFormat formatter.Format = "table {{.Name}}\t{{.Services}}\t{{.Orchestrator}}"
|
SwarmStackTableFormat formatter.Format = "table {{.Name}}\t{{.Services}}"
|
||||||
|
|
||||||
stackServicesHeader = "SERVICES"
|
stackServicesHeader = "SERVICES"
|
||||||
stackOrchestrastorHeader = "ORCHESTRATOR"
|
|
||||||
|
|
||||||
// TableFormatKey is an alias for formatter.TableFormatKey
|
// TableFormatKey is an alias for formatter.TableFormatKey
|
||||||
TableFormatKey = formatter.TableFormatKey
|
TableFormatKey = formatter.TableFormatKey
|
||||||
|
@ -29,8 +28,6 @@ type Stack struct {
|
||||||
Name string
|
Name string
|
||||||
// Services is the number of the services
|
// Services is the number of the services
|
||||||
Services int
|
Services int
|
||||||
// Orchestrator is the platform where the stack is deployed
|
|
||||||
Orchestrator string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// StackWrite writes formatted stacks using the Context
|
// StackWrite writes formatted stacks using the Context
|
||||||
|
@ -54,9 +51,8 @@ type stackContext struct {
|
||||||
func newStackContext() *stackContext {
|
func newStackContext() *stackContext {
|
||||||
stackCtx := stackContext{}
|
stackCtx := stackContext{}
|
||||||
stackCtx.Header = formatter.SubHeaderContext{
|
stackCtx.Header = formatter.SubHeaderContext{
|
||||||
"Name": formatter.NameHeader,
|
"Name": formatter.NameHeader,
|
||||||
"Services": stackServicesHeader,
|
"Services": stackServicesHeader,
|
||||||
"Orchestrator": stackOrchestrastorHeader,
|
|
||||||
}
|
}
|
||||||
return &stackCtx
|
return &stackCtx
|
||||||
}
|
}
|
||||||
|
@ -72,7 +68,3 @@ func (s *stackContext) Name() string {
|
||||||
func (s *stackContext) Services() string {
|
func (s *stackContext) Services() string {
|
||||||
return strconv.Itoa(s.s.Services)
|
return strconv.Itoa(s.s.Services)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stackContext) Orchestrator() string {
|
|
||||||
return s.s.Orchestrator
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,9 +27,9 @@ func TestStackContextWrite(t *testing.T) {
|
||||||
// Table format
|
// Table format
|
||||||
{
|
{
|
||||||
formatter.Context{Format: SwarmStackTableFormat},
|
formatter.Context{Format: SwarmStackTableFormat},
|
||||||
`NAME SERVICES ORCHESTRATOR
|
`NAME SERVICES
|
||||||
baz 2 orchestrator1
|
baz 2
|
||||||
bar 1 orchestrator2
|
bar 1
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -49,8 +49,8 @@ bar
|
||||||
}
|
}
|
||||||
|
|
||||||
stacks := []*Stack{
|
stacks := []*Stack{
|
||||||
{Name: "baz", Services: 2, Orchestrator: "orchestrator1"},
|
{Name: "baz", Services: 2},
|
||||||
{Name: "bar", Services: 1, Orchestrator: "orchestrator2"},
|
{Name: "bar", Services: 1},
|
||||||
}
|
}
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tc := tc
|
tc := tc
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newListCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command {
|
func newListCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
opts := options.List{}
|
opts := options.List{}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
@ -21,7 +21,7 @@ func newListCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command
|
||||||
Short: "List stacks",
|
Short: "List stacks",
|
||||||
Args: cli.NoArgs,
|
Args: cli.NoArgs,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
return RunList(cmd, dockerCli, opts, common.orchestrator)
|
return RunList(cmd, dockerCli, opts)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,16 +30,14 @@ func newListCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunList performs a stack list against the specified orchestrator
|
// RunList performs a stack list against the specified swarm cluster
|
||||||
func RunList(cmd *cobra.Command, dockerCli command.Cli, opts options.List, orchestrator command.Orchestrator) error {
|
func RunList(cmd *cobra.Command, dockerCli command.Cli, opts options.List) error {
|
||||||
stacks := []*formatter.Stack{}
|
stacks := []*formatter.Stack{}
|
||||||
if orchestrator.HasSwarm() {
|
ss, err := swarm.GetStacks(dockerCli)
|
||||||
ss, err := swarm.GetStacks(dockerCli)
|
if err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
stacks = append(stacks, ss...)
|
|
||||||
}
|
}
|
||||||
|
stacks = append(stacks, ss...)
|
||||||
return format(dockerCli, opts, stacks)
|
return format(dockerCli, opts, stacks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/command"
|
|
||||||
"github.com/docker/cli/internal/test"
|
"github.com/docker/cli/internal/test"
|
||||||
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
. "github.com/docker/cli/internal/test/builders" // Import builders to get the builder function as package function
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
@ -14,10 +13,6 @@ import (
|
||||||
"gotest.tools/v3/golden"
|
"gotest.tools/v3/golden"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
orchestrator = commonOptions{orchestrator: command.OrchestratorSwarm}
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestListErrors(t *testing.T) {
|
func TestListErrors(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
args []string
|
args []string
|
||||||
|
@ -52,7 +47,7 @@ func TestListErrors(t *testing.T) {
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
cmd := newListCommand(test.NewFakeCli(&fakeClient{
|
cmd := newListCommand(test.NewFakeCli(&fakeClient{
|
||||||
serviceListFunc: tc.serviceListFunc,
|
serviceListFunc: tc.serviceListFunc,
|
||||||
}), &orchestrator)
|
}))
|
||||||
cmd.SetArgs(tc.args)
|
cmd.SetArgs(tc.args)
|
||||||
cmd.SetOut(ioutil.Discard)
|
cmd.SetOut(ioutil.Discard)
|
||||||
for key, value := range tc.flags {
|
for key, value := range tc.flags {
|
||||||
|
@ -118,7 +113,7 @@ func TestStackList(t *testing.T) {
|
||||||
return services, nil
|
return services, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
cmd := newListCommand(cli, &orchestrator)
|
cmd := newListCommand(cli)
|
||||||
for key, value := range tc.flags {
|
for key, value := range tc.flags {
|
||||||
cmd.Flags().Set(key, value)
|
cmd.Flags().Set(key, value)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newPsCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command {
|
func newPsCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
opts := options.PS{Filter: cliopts.NewFilterOpt()}
|
opts := options.PS{Filter: cliopts.NewFilterOpt()}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
@ -22,7 +22,7 @@ func newPsCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command {
|
||||||
if err := validateStackName(opts.Namespace); err != nil {
|
if err := validateStackName(opts.Namespace); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return RunPs(dockerCli, cmd.Flags(), common.Orchestrator(), opts)
|
return RunPs(dockerCli, cmd.Flags(), opts)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
@ -34,7 +34,7 @@ func newPsCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunPs performs a stack ps against the specified orchestrator
|
// RunPs performs a stack ps against the specified swarm cluster
|
||||||
func RunPs(dockerCli command.Cli, flags *pflag.FlagSet, commonOrchestrator command.Orchestrator, opts options.PS) error {
|
func RunPs(dockerCli command.Cli, flags *pflag.FlagSet, opts options.PS) error {
|
||||||
return swarm.RunPS(dockerCli, opts)
|
return swarm.RunPS(dockerCli, opts)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ func TestStackPsErrors(t *testing.T) {
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
cmd := newPsCommand(test.NewFakeCli(&fakeClient{
|
cmd := newPsCommand(test.NewFakeCli(&fakeClient{
|
||||||
taskListFunc: tc.taskListFunc,
|
taskListFunc: tc.taskListFunc,
|
||||||
}), &orchestrator)
|
}))
|
||||||
cmd.SetArgs(tc.args)
|
cmd.SetArgs(tc.args)
|
||||||
cmd.SetOut(ioutil.Discard)
|
cmd.SetOut(ioutil.Discard)
|
||||||
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
assert.ErrorContains(t, cmd.Execute(), tc.expectedError)
|
||||||
|
@ -164,7 +164,7 @@ func TestStackPs(t *testing.T) {
|
||||||
})
|
})
|
||||||
cli.SetConfigFile(&tc.config)
|
cli.SetConfigFile(&tc.config)
|
||||||
|
|
||||||
cmd := newPsCommand(cli, &orchestrator)
|
cmd := newPsCommand(cli)
|
||||||
cmd.SetArgs(tc.args)
|
cmd.SetArgs(tc.args)
|
||||||
for key, value := range tc.flags {
|
for key, value := range tc.flags {
|
||||||
cmd.Flags().Set(key, value)
|
cmd.Flags().Set(key, value)
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newRemoveCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command {
|
func newRemoveCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
var opts options.Remove
|
var opts options.Remove
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
@ -22,13 +22,13 @@ func newRemoveCommand(dockerCli command.Cli, common *commonOptions) *cobra.Comma
|
||||||
if err := validateStackNames(opts.Namespaces); err != nil {
|
if err := validateStackNames(opts.Namespaces); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return RunRemove(dockerCli, cmd.Flags(), common.Orchestrator(), opts)
|
return RunRemove(dockerCli, cmd.Flags(), opts)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunRemove performs a stack remove against the specified orchestrator
|
// RunRemove performs a stack remove against the specified swarm cluster
|
||||||
func RunRemove(dockerCli command.Cli, flags *pflag.FlagSet, commonOrchestrator command.Orchestrator, opts options.Remove) error {
|
func RunRemove(dockerCli command.Cli, flags *pflag.FlagSet, opts options.Remove) error {
|
||||||
return swarm.RunRemove(dockerCli, opts)
|
return swarm.RunRemove(dockerCli, opts)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ func fakeClientForRemoveStackTest(version string) *fakeClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemoveWithEmptyName(t *testing.T) {
|
func TestRemoveWithEmptyName(t *testing.T) {
|
||||||
cmd := newRemoveCommand(test.NewFakeCli(&fakeClient{}), &orchestrator)
|
cmd := newRemoveCommand(test.NewFakeCli(&fakeClient{}))
|
||||||
cmd.SetArgs([]string{"good", "' '", "alsogood"})
|
cmd.SetArgs([]string{"good", "' '", "alsogood"})
|
||||||
cmd.SetOut(ioutil.Discard)
|
cmd.SetOut(ioutil.Discard)
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ func TestRemoveWithEmptyName(t *testing.T) {
|
||||||
|
|
||||||
func TestRemoveStackVersion124DoesNotRemoveConfigsOrSecrets(t *testing.T) {
|
func TestRemoveStackVersion124DoesNotRemoveConfigsOrSecrets(t *testing.T) {
|
||||||
client := fakeClientForRemoveStackTest("1.24")
|
client := fakeClientForRemoveStackTest("1.24")
|
||||||
cmd := newRemoveCommand(test.NewFakeCli(client), &orchestrator)
|
cmd := newRemoveCommand(test.NewFakeCli(client))
|
||||||
cmd.SetArgs([]string{"foo", "bar"})
|
cmd.SetArgs([]string{"foo", "bar"})
|
||||||
|
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
|
@ -63,7 +63,7 @@ func TestRemoveStackVersion124DoesNotRemoveConfigsOrSecrets(t *testing.T) {
|
||||||
|
|
||||||
func TestRemoveStackVersion125DoesNotRemoveConfigs(t *testing.T) {
|
func TestRemoveStackVersion125DoesNotRemoveConfigs(t *testing.T) {
|
||||||
client := fakeClientForRemoveStackTest("1.25")
|
client := fakeClientForRemoveStackTest("1.25")
|
||||||
cmd := newRemoveCommand(test.NewFakeCli(client), &orchestrator)
|
cmd := newRemoveCommand(test.NewFakeCli(client))
|
||||||
cmd.SetArgs([]string{"foo", "bar"})
|
cmd.SetArgs([]string{"foo", "bar"})
|
||||||
|
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
|
@ -75,7 +75,7 @@ func TestRemoveStackVersion125DoesNotRemoveConfigs(t *testing.T) {
|
||||||
|
|
||||||
func TestRemoveStackVersion130RemovesEverything(t *testing.T) {
|
func TestRemoveStackVersion130RemovesEverything(t *testing.T) {
|
||||||
client := fakeClientForRemoveStackTest("1.30")
|
client := fakeClientForRemoveStackTest("1.30")
|
||||||
cmd := newRemoveCommand(test.NewFakeCli(client), &orchestrator)
|
cmd := newRemoveCommand(test.NewFakeCli(client))
|
||||||
cmd.SetArgs([]string{"foo", "bar"})
|
cmd.SetArgs([]string{"foo", "bar"})
|
||||||
|
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
|
@ -106,7 +106,7 @@ func TestRemoveStackSkipEmpty(t *testing.T) {
|
||||||
configs: allConfigs,
|
configs: allConfigs,
|
||||||
}
|
}
|
||||||
fakeCli := test.NewFakeCli(fakeClient)
|
fakeCli := test.NewFakeCli(fakeClient)
|
||||||
cmd := newRemoveCommand(fakeCli, &orchestrator)
|
cmd := newRemoveCommand(fakeCli)
|
||||||
cmd.SetArgs([]string{"foo", "bar"})
|
cmd.SetArgs([]string{"foo", "bar"})
|
||||||
|
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
|
@ -154,7 +154,7 @@ func TestRemoveContinueAfterError(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd := newRemoveCommand(test.NewFakeCli(cli), &orchestrator)
|
cmd := newRemoveCommand(test.NewFakeCli(cli))
|
||||||
cmd.SetOut(ioutil.Discard)
|
cmd.SetOut(ioutil.Discard)
|
||||||
cmd.SetArgs([]string{"foo", "bar"})
|
cmd.SetArgs([]string{"foo", "bar"})
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newServicesCommand(dockerCli command.Cli, common *commonOptions) *cobra.Command {
|
func newServicesCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
opts := options.Services{Filter: cliopts.NewFilterOpt()}
|
opts := options.Services{Filter: cliopts.NewFilterOpt()}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
@ -29,7 +29,7 @@ func newServicesCommand(dockerCli command.Cli, common *commonOptions) *cobra.Com
|
||||||
if err := validateStackName(opts.Namespace); err != nil {
|
if err := validateStackName(opts.Namespace); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return RunServices(dockerCli, cmd.Flags(), common.Orchestrator(), opts)
|
return RunServices(dockerCli, cmd.Flags(), opts)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
@ -39,17 +39,17 @@ func newServicesCommand(dockerCli command.Cli, common *commonOptions) *cobra.Com
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunServices performs a stack services against the specified orchestrator
|
// RunServices performs a stack services against the specified swarm cluster
|
||||||
func RunServices(dockerCli command.Cli, flags *pflag.FlagSet, commonOrchestrator command.Orchestrator, opts options.Services) error {
|
func RunServices(dockerCli command.Cli, flags *pflag.FlagSet, opts options.Services) error {
|
||||||
services, err := GetServices(dockerCli, flags, commonOrchestrator, opts)
|
services, err := GetServices(dockerCli, flags, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return formatWrite(dockerCli, services, opts)
|
return formatWrite(dockerCli, services, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetServices returns the services for the specified orchestrator
|
// GetServices returns the services for the specified swarm cluster
|
||||||
func GetServices(dockerCli command.Cli, flags *pflag.FlagSet, commonOrchestrator command.Orchestrator, opts options.Services) ([]swarmtypes.Service, error) {
|
func GetServices(dockerCli command.Cli, flags *pflag.FlagSet, opts options.Services) ([]swarmtypes.Service, error) {
|
||||||
return swarm.GetServices(dockerCli, opts)
|
return swarm.GetServices(dockerCli, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ func TestStackServicesErrors(t *testing.T) {
|
||||||
nodeListFunc: tc.nodeListFunc,
|
nodeListFunc: tc.nodeListFunc,
|
||||||
taskListFunc: tc.taskListFunc,
|
taskListFunc: tc.taskListFunc,
|
||||||
})
|
})
|
||||||
cmd := newServicesCommand(cli, &orchestrator)
|
cmd := newServicesCommand(cli)
|
||||||
cmd.SetArgs(tc.args)
|
cmd.SetArgs(tc.args)
|
||||||
for key, value := range tc.flags {
|
for key, value := range tc.flags {
|
||||||
cmd.Flags().Set(key, value)
|
cmd.Flags().Set(key, value)
|
||||||
|
@ -86,7 +86,7 @@ func TestStackServicesErrors(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunServicesWithEmptyName(t *testing.T) {
|
func TestRunServicesWithEmptyName(t *testing.T) {
|
||||||
cmd := newServicesCommand(test.NewFakeCli(&fakeClient{}), &orchestrator)
|
cmd := newServicesCommand(test.NewFakeCli(&fakeClient{}))
|
||||||
cmd.SetArgs([]string{"' '"})
|
cmd.SetArgs([]string{"' '"})
|
||||||
cmd.SetOut(ioutil.Discard)
|
cmd.SetOut(ioutil.Discard)
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ func TestStackServicesEmptyServiceList(t *testing.T) {
|
||||||
return []swarm.Service{}, nil
|
return []swarm.Service{}, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
cmd := newServicesCommand(fakeCli, &orchestrator)
|
cmd := newServicesCommand(fakeCli)
|
||||||
cmd.SetArgs([]string{"foo"})
|
cmd.SetArgs([]string{"foo"})
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
assert.Check(t, is.Equal("", fakeCli.OutBuffer().String()))
|
assert.Check(t, is.Equal("", fakeCli.OutBuffer().String()))
|
||||||
|
@ -112,7 +112,7 @@ func TestStackServicesWithQuietOption(t *testing.T) {
|
||||||
return []swarm.Service{*Service(ServiceID("id-foo"))}, nil
|
return []swarm.Service{*Service(ServiceID("id-foo"))}, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
cmd := newServicesCommand(cli, &orchestrator)
|
cmd := newServicesCommand(cli)
|
||||||
cmd.Flags().Set("quiet", "true")
|
cmd.Flags().Set("quiet", "true")
|
||||||
cmd.SetArgs([]string{"foo"})
|
cmd.SetArgs([]string{"foo"})
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
|
@ -127,7 +127,7 @@ func TestStackServicesWithFormat(t *testing.T) {
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
cmd := newServicesCommand(cli, &orchestrator)
|
cmd := newServicesCommand(cli)
|
||||||
cmd.SetArgs([]string{"foo"})
|
cmd.SetArgs([]string{"foo"})
|
||||||
cmd.Flags().Set("format", "{{ .Name }}")
|
cmd.Flags().Set("format", "{{ .Name }}")
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
|
@ -145,7 +145,7 @@ func TestStackServicesWithConfigFormat(t *testing.T) {
|
||||||
cli.SetConfigFile(&configfile.ConfigFile{
|
cli.SetConfigFile(&configfile.ConfigFile{
|
||||||
ServicesFormat: "{{ .Name }}",
|
ServicesFormat: "{{ .Name }}",
|
||||||
})
|
})
|
||||||
cmd := newServicesCommand(cli, &orchestrator)
|
cmd := newServicesCommand(cli)
|
||||||
cmd.SetArgs([]string{"foo"})
|
cmd.SetArgs([]string{"foo"})
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
golden.Assert(t, cli.OutBuffer().String(), "stack-services-with-config-format.golden")
|
golden.Assert(t, cli.OutBuffer().String(), "stack-services-with-config-format.golden")
|
||||||
|
@ -168,7 +168,7 @@ func TestStackServicesWithoutFormat(t *testing.T) {
|
||||||
)}, nil
|
)}, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
cmd := newServicesCommand(cli, &orchestrator)
|
cmd := newServicesCommand(cli)
|
||||||
cmd.SetArgs([]string{"foo"})
|
cmd.SetArgs([]string{"foo"})
|
||||||
assert.NilError(t, cmd.Execute())
|
assert.NilError(t, cmd.Execute())
|
||||||
golden.Assert(t, cli.OutBuffer().String(), "stack-services-without-format.golden")
|
golden.Assert(t, cli.OutBuffer().String(), "stack-services-without-format.golden")
|
||||||
|
|
|
@ -29,9 +29,8 @@ func GetStacks(dockerCli command.Cli) ([]*formatter.Stack, error) {
|
||||||
ztack, ok := m[name]
|
ztack, ok := m[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
m[name] = &formatter.Stack{
|
m[name] = &formatter.Stack{
|
||||||
Name: name,
|
Name: name,
|
||||||
Services: 1,
|
Services: 1,
|
||||||
Orchestrator: "Swarm",
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ztack.Services++
|
ztack.Services++
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
NAME SERVICES ORCHESTRATOR
|
NAME SERVICES
|
||||||
service-name-1-foo 1 Swarm
|
service-name-1-foo 1
|
||||||
service-name-2-foo 1 Swarm
|
service-name-2-foo 1
|
||||||
service-name-10-foo 1 Swarm
|
service-name-10-foo 1
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
NAME SERVICES ORCHESTRATOR
|
NAME SERVICES
|
||||||
service-name-bar 1 Swarm
|
service-name-bar 1
|
||||||
service-name-foo 1 Swarm
|
service-name-foo 1
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
NAME SERVICES ORCHESTRATOR
|
NAME SERVICES
|
||||||
service-name-foo 1 Swarm
|
service-name-foo 1
|
||||||
|
|
|
@ -44,7 +44,7 @@ func (s *tlsStore) getData(contextID contextdir, endpointName, filename string)
|
||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *tlsStore) remove(contextID contextdir, endpointName, filename string) error {
|
func (s *tlsStore) remove(contextID contextdir, endpointName, filename string) error { // nolint:unused
|
||||||
err := os.Remove(s.filePath(contextID, endpointName, filename))
|
err := os.Remove(s.filePath(contextID, endpointName, filename))
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
NAME DESCRIPTION DOCKER ENDPOINT ORCHESTRATOR
|
NAME DESCRIPTION DOCKER ENDPOINT
|
||||||
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
|
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
|
||||||
remote my remote cluster ssh://someserver kubernetes
|
remote my remote cluster ssh://someserver
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
NAME DESCRIPTION DOCKER ENDPOINT ORCHESTRATOR
|
NAME DESCRIPTION DOCKER ENDPOINT
|
||||||
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
|
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
|
||||||
test unix:///var/run/docker.sock swarm
|
test unix:///var/run/docker.sock
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
NAME DESCRIPTION DOCKER ENDPOINT ORCHESTRATOR
|
NAME DESCRIPTION DOCKER ENDPOINT
|
||||||
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
|
default * Current DOCKER_HOST based configuration unix:///var/run/docker.sock
|
||||||
remote my remote cluster ssh://someserver kubernetes
|
remote my remote cluster ssh://someserver
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package stack
|
package stack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -12,23 +11,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDeployWithNamedResources(t *testing.T) {
|
func TestDeployWithNamedResources(t *testing.T) {
|
||||||
t.Run("Swarm", func(t *testing.T) {
|
stackname := "test-stack-deploy-with-names"
|
||||||
testDeployWithNamedResources(t, "swarm")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func testDeployWithNamedResources(t *testing.T, orchestrator string) {
|
|
||||||
stackname := fmt.Sprintf("test-stack-deploy-with-names-%s", orchestrator)
|
|
||||||
composefile := golden.Path("stack-with-named-resources.yml")
|
composefile := golden.Path("stack-with-named-resources.yml")
|
||||||
|
|
||||||
result := icmd.RunCommand("docker", "stack", "deploy",
|
result := icmd.RunCommand("docker", "stack", "deploy",
|
||||||
"-c", composefile, stackname, "--orchestrator", orchestrator)
|
"-c", composefile, stackname)
|
||||||
defer icmd.RunCommand("docker", "stack", "rm",
|
defer icmd.RunCommand("docker", "stack", "rm", stackname)
|
||||||
"--orchestrator", orchestrator, stackname)
|
|
||||||
|
|
||||||
result.Assert(t, icmd.Success)
|
result.Assert(t, icmd.Success)
|
||||||
stdout := strings.Split(result.Stdout(), "\n")
|
stdout := strings.Split(result.Stdout(), "\n")
|
||||||
expected := strings.Split(string(golden.Get(t, fmt.Sprintf("stack-deploy-with-names-%s.golden", orchestrator))), "\n")
|
expected := strings.Split(string(golden.Get(t, "stack-deploy-with-names.golden")), "\n")
|
||||||
sort.Strings(stdout)
|
sort.Strings(stdout)
|
||||||
sort.Strings(expected)
|
sort.Strings(expected)
|
||||||
assert.DeepEqual(t, stdout, expected)
|
assert.DeepEqual(t, stdout, expected)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package stack
|
package stack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gotest.tools/v3/golden"
|
"gotest.tools/v3/golden"
|
||||||
|
@ -9,13 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestStackDeployHelp(t *testing.T) {
|
func TestStackDeployHelp(t *testing.T) {
|
||||||
t.Run("Swarm", func(t *testing.T) {
|
result := icmd.RunCommand("docker", "stack", "deploy", "--help")
|
||||||
testStackDeployHelp(t, "swarm")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func testStackDeployHelp(t *testing.T, orchestrator string) {
|
|
||||||
result := icmd.RunCommand("docker", "stack", "deploy", "--orchestrator", orchestrator, "--help")
|
|
||||||
result.Assert(t, icmd.Success)
|
result.Assert(t, icmd.Success)
|
||||||
golden.Assert(t, result.Stdout(), fmt.Sprintf("stack-deploy-help-%s.golden", orchestrator))
|
golden.Assert(t, result.Stdout(), "stack-deploy-help.golden")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package stack
|
package stack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -14,40 +13,32 @@ import (
|
||||||
var pollSettings = environment.DefaultPollSettings
|
var pollSettings = environment.DefaultPollSettings
|
||||||
|
|
||||||
func TestRemove(t *testing.T) {
|
func TestRemove(t *testing.T) {
|
||||||
t.Run("Swarm", func(t *testing.T) {
|
stackname := "test-stack-remove"
|
||||||
testRemove(t, "swarm")
|
deployFullStack(t, stackname)
|
||||||
})
|
defer cleanupFullStack(t, stackname)
|
||||||
}
|
result := icmd.RunCommand("docker", "stack", "rm", stackname)
|
||||||
|
|
||||||
func testRemove(t *testing.T, orchestrator string) {
|
|
||||||
stackname := "test-stack-remove-" + orchestrator
|
|
||||||
deployFullStack(t, orchestrator, stackname)
|
|
||||||
defer cleanupFullStack(t, orchestrator, stackname)
|
|
||||||
result := icmd.RunCommand("docker", "stack", "rm",
|
|
||||||
stackname, "--orchestrator", orchestrator)
|
|
||||||
result.Assert(t, icmd.Expected{Err: icmd.None})
|
result.Assert(t, icmd.Expected{Err: icmd.None})
|
||||||
golden.Assert(t, result.Stdout(),
|
golden.Assert(t, result.Stdout(), "stack-remove-success.golden")
|
||||||
fmt.Sprintf("stack-remove-%s-success.golden", orchestrator))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deployFullStack(t *testing.T, orchestrator, stackname string) {
|
func deployFullStack(t *testing.T, stackname string) {
|
||||||
// TODO: this stack should have full options not minimal options
|
// TODO: this stack should have full options not minimal options
|
||||||
result := icmd.RunCommand("docker", "stack", "deploy",
|
result := icmd.RunCommand("docker", "stack", "deploy",
|
||||||
"--compose-file=./testdata/full-stack.yml", stackname, "--orchestrator", orchestrator)
|
"--compose-file=./testdata/full-stack.yml", stackname)
|
||||||
result.Assert(t, icmd.Success)
|
result.Assert(t, icmd.Success)
|
||||||
|
|
||||||
poll.WaitOn(t, taskCount(orchestrator, stackname, 2), pollSettings)
|
poll.WaitOn(t, taskCount(stackname, 2), pollSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanupFullStack(t *testing.T, orchestrator, stackname string) {
|
func cleanupFullStack(t *testing.T, stackname string) {
|
||||||
// FIXME(vdemeester) we shouldn't have to do that. it is hiding a race on docker stack rm
|
// FIXME(vdemeester) we shouldn't have to do that. it is hiding a race on docker stack rm
|
||||||
poll.WaitOn(t, stackRm(orchestrator, stackname), pollSettings)
|
poll.WaitOn(t, stackRm(stackname), pollSettings)
|
||||||
poll.WaitOn(t, taskCount(orchestrator, stackname, 0), pollSettings)
|
poll.WaitOn(t, taskCount(stackname, 0), pollSettings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func stackRm(orchestrator, stackname string) func(t poll.LogT) poll.Result {
|
func stackRm(stackname string) func(t poll.LogT) poll.Result {
|
||||||
return func(poll.LogT) poll.Result {
|
return func(poll.LogT) poll.Result {
|
||||||
result := icmd.RunCommand("docker", "stack", "rm", stackname, "--orchestrator", orchestrator)
|
result := icmd.RunCommand("docker", "stack", "rm", stackname)
|
||||||
if result.Error != nil {
|
if result.Error != nil {
|
||||||
if strings.Contains(result.Stderr(), "not found") {
|
if strings.Contains(result.Stderr(), "not found") {
|
||||||
return poll.Success()
|
return poll.Success()
|
||||||
|
@ -58,14 +49,9 @@ func stackRm(orchestrator, stackname string) func(t poll.LogT) poll.Result {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func taskCount(orchestrator, stackname string, expected int) func(t poll.LogT) poll.Result {
|
func taskCount(stackname string, expected int) func(t poll.LogT) poll.Result {
|
||||||
return func(poll.LogT) poll.Result {
|
return func(poll.LogT) poll.Result {
|
||||||
args := []string{"stack", "ps", stackname, "--orchestrator", orchestrator}
|
result := icmd.RunCommand("docker", "stack", "ps", stackname, "-f=desired-state=running")
|
||||||
// FIXME(chris-crone): remove when we support filtering by desired-state on kubernetes
|
|
||||||
if orchestrator == "swarm" {
|
|
||||||
args = append(args, "-f=desired-state=running")
|
|
||||||
}
|
|
||||||
result := icmd.RunCommand("docker", args...)
|
|
||||||
count := lines(result.Stdout()) - 1
|
count := lines(result.Stdout()) - 1
|
||||||
if count == expected {
|
if count == expected {
|
||||||
return poll.Success()
|
return poll.Success()
|
||||||
|
|
|
@ -9,7 +9,6 @@ Aliases:
|
||||||
Options:
|
Options:
|
||||||
-c, --compose-file strings Path to a Compose file, or "-" to read
|
-c, --compose-file strings Path to a Compose file, or "-" to read
|
||||||
from stdin
|
from stdin
|
||||||
--orchestrator string Orchestrator to use (swarm|all)
|
|
||||||
--prune Prune services that are no longer referenced
|
--prune Prune services that are no longer referenced
|
||||||
--resolve-image string Query the registry to resolve image digest
|
--resolve-image string Query the registry to resolve image digest
|
||||||
and supported platforms
|
and supported platforms
|
|
@ -1,7 +0,0 @@
|
||||||
Creating network test-stack-deploy-with-names-swarm_network2
|
|
||||||
Creating network named-network
|
|
||||||
Creating secret named-secret
|
|
||||||
Creating secret test-stack-deploy-with-names-swarm_secret2
|
|
||||||
Creating config test-stack-deploy-with-names-swarm_config2
|
|
||||||
Creating config named-config
|
|
||||||
Creating service test-stack-deploy-with-names-swarm_web
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Removing service test-stack-remove_one
|
||||||
|
Removing service test-stack-remove_two
|
||||||
|
Removing network test-stack-remove_default
|
|
@ -1,3 +0,0 @@
|
||||||
Removing service test-stack-remove-swarm_one
|
|
||||||
Removing service test-stack-remove-swarm_two
|
|
||||||
Removing network test-stack-remove-swarm_default
|
|
|
@ -55,7 +55,8 @@ func NewFakeCli(client client.APIClient, opts ...func(*FakeCli)) *FakeCli {
|
||||||
in: streams.NewIn(ioutil.NopCloser(strings.NewReader(""))),
|
in: streams.NewIn(ioutil.NopCloser(strings.NewReader(""))),
|
||||||
// Use an empty string for filename so that tests don't create configfiles
|
// Use an empty string for filename so that tests don't create configfiles
|
||||||
// Set cli.ConfigFile().Filename to a tempfile to support Save.
|
// Set cli.ConfigFile().Filename to a tempfile to support Save.
|
||||||
configfile: configfile.New(""),
|
configfile: configfile.New(""),
|
||||||
|
currentContext: command.DefaultContextName,
|
||||||
}
|
}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(c)
|
opt(c)
|
||||||
|
@ -214,24 +215,3 @@ func (c *FakeCli) ContentTrustEnabled() bool {
|
||||||
func EnableContentTrust(c *FakeCli) {
|
func EnableContentTrust(c *FakeCli) {
|
||||||
c.contentTrust = true
|
c.contentTrust = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// StackOrchestrator return the selected stack orchestrator
|
|
||||||
func (c *FakeCli) StackOrchestrator(flagValue string) (command.Orchestrator, error) {
|
|
||||||
configOrchestrator := ""
|
|
||||||
if c.configfile != nil {
|
|
||||||
configOrchestrator = c.configfile.StackOrchestrator
|
|
||||||
}
|
|
||||||
ctxOrchestrator := ""
|
|
||||||
if c.currentContext != "" && c.contextStore != nil {
|
|
||||||
meta, err := c.contextStore.GetMetadata(c.currentContext)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
context, err := command.GetDockerContext(meta)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
ctxOrchestrator = string(context.StackOrchestrator)
|
|
||||||
}
|
|
||||||
return command.GetStackOrchestrator(flagValue, ctxOrchestrator, configOrchestrator, c.err)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue