Merge pull request #204 from docker/context_create_refacto

Context create refacto
This commit is contained in:
Guillaume Tardif 2020-06-15 12:39:37 +02:00 committed by GitHub
commit 3566c720e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 251 additions and 160 deletions

View File

@ -45,7 +45,7 @@ cli: ## Compile the cli
--output ./bin --output ./bin
e2e-local: ## Run End to end local tests e2e-local: ## Run End to end local tests
go test -v ./tests/e2e ./tests/skip-win-ci-e2e ./moby/e2e go test -v ./tests/e2e ./tests/skip-win-ci-e2e ./local/e2e
e2e-win-ci: ## Run End to end local tests on windows CI, no docker for linux containers available ATM e2e-win-ci: ## Run End to end local tests on windows CI, no docker for linux containers available ATM
go test -v ./tests/e2e go test -v ./tests/e2e

View File

@ -29,75 +29,118 @@ package context
import ( import (
"context" "context"
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/docker/api/client" "github.com/docker/api/cli/dockerclassic"
"github.com/docker/api/context/store" "github.com/docker/api/context/store"
) )
// AciCreateOpts Options for ACI context create type descriptionCreateOpts struct {
type AciCreateOpts struct {
description string description string
aciLocation string
aciSubscriptionID string
aciResourceGroup string
} }
func createCommand() *cobra.Command { func createCommand() *cobra.Command {
var opts AciCreateOpts const longHelp = `Create a new context
Create docker engine context:
$ docker context create CONTEXT [flags]
Create Azure Container Instances context:
$ docker context create aci CONTEXT [flags]
(see docker context create aci --help)
Docker endpoint config:
NAME DESCRIPTION
from Copy named context's Docker endpoint configuration
host Docker endpoint on which to connect
ca Trust certs signed only by this CA
cert Path to TLS certificate file
key Path to TLS key file
skip-tls-verify Skip TLS certificate validation
Kubernetes endpoint config:
NAME DESCRIPTION
from Copy named context's Kubernetes endpoint configuration
config-file Path to a Kubernetes config file
context-override Overrides the context set in the kubernetes config file
namespace-override Overrides the namespace set in the kubernetes config file
Example:
$ docker context create my-context --description "some description" --docker "host=tcp://myserver:2376,ca=~/ca-file,cert=~/cert-file,key=~/key-file"`
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "create CONTEXT BACKEND [OPTIONS]", Use: "create CONTEXT",
Short: "Create a context", Short: "Create new context",
Args: cobra.ExactArgs(2),
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return runCreate(cmd.Context(), opts, args[0], args[1]) return dockerclassic.ExecCmd(cmd)
}, },
Long: longHelp,
} }
cmd.Flags().StringVar(&opts.description, "description", "", "Description of the context") cmd.AddCommand(
cmd.Flags().StringVar(&opts.aciLocation, "aci-location", "eastus", "Location") createAciCommand(),
cmd.Flags().StringVar(&opts.aciSubscriptionID, "aci-subscription-id", "", "Location") createLocalCommand(),
cmd.Flags().StringVar(&opts.aciResourceGroup, "aci-resource-group", "", "Resource group") createExampleCommand(),
)
flags := cmd.Flags()
flags.String("description", "", "Description of the context")
flags.String(
"default-stack-orchestrator", "",
"Default orchestrator for stack operations to use with this context (swarm|kubernetes|all)")
flags.StringToString("docker", nil, "set the docker endpoint")
flags.StringToString("kubernetes", nil, "set the kubernetes endpoint")
flags.String("from", "", "create context from a named context")
return cmd return cmd
} }
func runCreate(ctx context.Context, opts AciCreateOpts, name string, contextType string) error { func createLocalCommand() *cobra.Command {
contextData, description, err := getContextData(ctx, contextType, opts) var opts descriptionCreateOpts
if err != nil { cmd := &cobra.Command{
return nil Use: "local CONTEXT",
Short: "Create a context for accessing local engine",
Args: cobra.ExactArgs(1),
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
return createDockerContext(cmd.Context(), args[0], store.LocalContextType, opts.description, store.LocalContext{})
},
} }
addDescriptionFlag(cmd, &opts.description)
return cmd
}
func createExampleCommand() *cobra.Command {
var opts descriptionCreateOpts
cmd := &cobra.Command{
Use: "example CONTEXT",
Short: "Create a test context returning fixed output",
Args: cobra.ExactArgs(1),
Hidden: true,
RunE: func(cmd *cobra.Command, args []string) error {
return createDockerContext(cmd.Context(), args[0], store.ExampleContextType, opts.description, store.ExampleContext{})
},
}
addDescriptionFlag(cmd, &opts.description)
return cmd
}
func createDockerContext(ctx context.Context, name string, contextType string, description string, data interface{}) error {
s := store.ContextStore(ctx) s := store.ContextStore(ctx)
return s.Create( result := s.Create(
name, name,
contextType, contextType,
description, description,
contextData, data,
) )
return result
} }
func getContextData(ctx context.Context, contextType string, opts AciCreateOpts) (interface{}, string, error) { func addDescriptionFlag(cmd *cobra.Command, descriptionOpt *string) {
switch contextType { cmd.Flags().StringVar(descriptionOpt, "description", "", "Description of the context")
case "aci":
cs, err := client.GetCloudService(ctx, "aci")
if err != nil {
return nil, "", errors.Wrap(err, "cannot connect to ACI backend")
}
params := map[string]string{
"aciSubscriptionId": opts.aciSubscriptionID,
"aciResourceGroup": opts.aciResourceGroup,
"aciLocation": opts.aciLocation,
"description": opts.description,
}
return cs.CreateContextData(ctx, params)
case "moby":
return store.MobyContext{}, opts.description, nil
case "example":
return store.ExampleContext{}, opts.description, nil
default:
return nil, "", errors.New(fmt.Sprintf("incorrect context type %s, must be one of (aci | moby | docker)", contextType))
}
} }

View File

@ -1,35 +0,0 @@
package context
import (
"context"
"testing"
"github.com/docker/api/context/store"
. "github.com/onsi/gomega"
"github.com/stretchr/testify/suite"
_ "github.com/docker/api/example"
"github.com/docker/api/tests/framework"
)
type PsSuite struct {
framework.CliSuite
}
func (sut *PsSuite) TestCreateContextDataMoby() {
data, description, err := getContextData(context.TODO(), "moby", AciCreateOpts{})
Expect(err).To(BeNil())
Expect(data).To(Equal(store.MobyContext{}))
Expect(description).To(Equal(""))
}
func (sut *PsSuite) TestErrorOnUnknownContextType() {
_, _, err := getContextData(context.TODO(), "foo", AciCreateOpts{})
Expect(err).To(MatchError("incorrect context type foo, must be one of (aci | moby | docker)"))
}
func TestPs(t *testing.T) {
RegisterTestingT(t)
suite.Run(t, new(PsSuite))
}

View File

@ -0,0 +1,85 @@
/*
Copyright (c) 2020 Docker Inc.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use, copy,
modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package context
import (
"context"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/docker/api/client"
"github.com/docker/api/context/store"
)
type aciCreateOpts struct {
description string
location string
subscriptionID string
resourceGroup string
}
func createAciCommand() *cobra.Command {
var opts aciCreateOpts
cmd := &cobra.Command{
Use: "aci CONTEXT [flags]",
Short: "Create a context for Azure Container Instances",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
contextData, description, err := getAciContextData(cmd.Context(), opts)
if err != nil {
return nil
}
return createDockerContext(cmd.Context(), args[0], store.AciContextType, description, contextData)
},
}
addDescriptionFlag(cmd, &opts.description)
cmd.Flags().StringVar(&opts.location, "location", "eastus", "Location")
cmd.Flags().StringVar(&opts.subscriptionID, "subscription-id", "", "Location")
cmd.Flags().StringVar(&opts.resourceGroup, "resource-group", "", "Resource group")
return cmd
}
func getAciContextData(ctx context.Context, opts aciCreateOpts) (interface{}, string, error) {
cs, err := client.GetCloudService(ctx, store.AciContextType)
if err != nil {
return nil, "", errors.Wrap(err, "cannot connect to ACI backend")
}
return cs.CreateContextData(ctx, convertAciOpts(opts))
}
func convertAciOpts(opts aciCreateOpts) map[string]string {
return map[string]string{
"aciSubscriptionId": opts.subscriptionID,
"aciResourceGroup": opts.resourceGroup,
"aciLocation": opts.location,
"description": opts.description,
}
}

View File

@ -94,7 +94,7 @@ func getEndpoint(name string, meta map[string]interface{}) string {
if !ok { if !ok {
return "" return ""
} }
data, ok := endpoints.(store.Endpoint) data, ok := endpoints.(*store.Endpoint)
if !ok { if !ok {
return "" return ""
} }

View File

@ -45,7 +45,7 @@ import (
// Backend registrations // Backend registrations
_ "github.com/docker/api/azure" _ "github.com/docker/api/azure"
_ "github.com/docker/api/example" _ "github.com/docker/api/example"
_ "github.com/docker/api/moby" _ "github.com/docker/api/local"
"github.com/docker/api/cli/cmd" "github.com/docker/api/cli/cmd"
"github.com/docker/api/cli/cmd/compose" "github.com/docker/api/cli/cmd/compose"

View File

@ -39,7 +39,7 @@ import (
var sampleConfig = []byte(`{ var sampleConfig = []byte(`{
"otherField": "value", "otherField": "value",
"currentContext": "moby" "currentContext": "local"
}`) }`)
type ConfigTestSuite struct { type ConfigTestSuite struct {
@ -66,14 +66,14 @@ func (s *ConfigTestSuite) TestLoadFile() {
writeSampleConfig(s.T(), s.configDir) writeSampleConfig(s.T(), s.configDir)
f, err := LoadFile(s.configDir) f, err := LoadFile(s.configDir)
require.NoError(s.T(), err) require.NoError(s.T(), err)
require.Equal(s.T(), "moby", f.CurrentContext) require.Equal(s.T(), "local", f.CurrentContext)
} }
func (s *ConfigTestSuite) TestOverWriteCurrentContext() { func (s *ConfigTestSuite) TestOverWriteCurrentContext() {
writeSampleConfig(s.T(), s.configDir) writeSampleConfig(s.T(), s.configDir)
f, err := LoadFile(s.configDir) f, err := LoadFile(s.configDir)
require.NoError(s.T(), err) require.NoError(s.T(), err)
require.Equal(s.T(), "moby", f.CurrentContext) require.Equal(s.T(), "local", f.CurrentContext)
err = WriteCurrentContext(s.configDir, "overwrite") err = WriteCurrentContext(s.configDir, "overwrite")
require.NoError(s.T(), err) require.NoError(s.T(), err)

View File

@ -33,8 +33,8 @@ type AciContext struct {
ResourceGroup string `json:",omitempty"` ResourceGroup string `json:",omitempty"`
} }
// MobyContext is the context for the moby backend // LocalContext is the context for the local backend
type MobyContext struct{} type LocalContext struct{}
// ExampleContext is the context for the example backend // ExampleContext is the context for the example backend
type ExampleContext struct{} type ExampleContext struct{}

View File

@ -96,9 +96,9 @@ const (
// AciContextType is the endpoint key in the context endpoints for an ACI // AciContextType is the endpoint key in the context endpoints for an ACI
// backend // backend
AciContextType = "aci" AciContextType = "aci"
// MobyContextType is the endpoint key in the context endpoints for a moby // LocalContextType is the endpoint key in the context endpoints for a new
// backend // local backend
MobyContextType = "moby" LocalContextType = "local"
// ExampleContextType is the endpoint key in the context endpoints for an // ExampleContextType is the endpoint key in the context endpoints for an
// example backend // example backend
ExampleContextType = "example" ExampleContextType = "example"
@ -211,12 +211,14 @@ func toTypedEndpoints(endpoints map[string]interface{}) (map[string]interface{},
return nil, err return nil, err
} }
typeGetters := getters() typeGetters := getters()
if _, ok := typeGetters[k]; !ok { typeGetter, ok := typeGetters[k]
result[k] = v if !ok {
continue typeGetter = func() interface{} {
return &Endpoint{}
}
} }
val := typeGetters[k]() val := typeGetter()
err = json.Unmarshal(bytes, &val) err = json.Unmarshal(bytes, &val)
if err != nil { if err != nil {
return nil, err return nil, err
@ -333,8 +335,8 @@ func getters() map[string]func() interface{} {
"aci": func() interface{} { "aci": func() interface{} {
return &AciContext{} return &AciContext{}
}, },
"moby": func() interface{} { "local": func() interface{} {
return &MobyContext{} return &LocalContext{}
}, },
"example": func() interface{} { "example": func() interface{} {
return &ExampleContext{} return &ExampleContext{}

View File

@ -8,7 +8,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
const defaultContextType = "docker" const defaultContextType = "moby"
// Represents a context as created by the docker cli // Represents a context as created by the docker cli
type defaultContext struct { type defaultContext struct {
@ -58,10 +58,10 @@ func dockerDefaultContext() (*DockerContext, error) {
meta := DockerContext{ meta := DockerContext{
Name: "default", Name: "default",
Endpoints: map[string]interface{}{ Endpoints: map[string]interface{}{
"docker": Endpoint{ "docker": &Endpoint{
Host: defaultCtx.Endpoints.Docker.Host, Host: defaultCtx.Endpoints.Docker.Host,
}, },
"kubernetes": Endpoint{ "kubernetes": &Endpoint{
Host: defaultCtx.Endpoints.Kubernetes.Host, Host: defaultCtx.Endpoints.Kubernetes.Host,
DefaultNamespace: defaultCtx.Endpoints.Kubernetes.DefaultNamespace, DefaultNamespace: defaultCtx.Endpoints.Kubernetes.DefaultNamespace,
}, },

View File

@ -26,7 +26,7 @@ Insert a really small tutorial or links here.
We have made some changes to the syntax of a few commands to make them easier to understand. Where we still support the old We have made some changes to the syntax of a few commands to make them easier to understand. Where we still support the old
forms, the command line will tell you the new form, but will still work correctly. In cases where we remove the old forms, the command line will tell you the new form, but will still work correctly. In cases where we remove the old
form you will get help text. If we remove a verb, for example "docker stack" we will display a message saying that the command form you will get help text. If we remove a verb, for example "docker stack" we will display a message saying that the command
is only available with the Moby backend. For example is only available with the Local backend. For example
``` ```
> docker context create my-context --description "some description" --docker "host=tcp://myserver:2376" > docker context create my-context --description "some description" --docker "host=tcp://myserver:2376"

View File

@ -1,4 +1,4 @@
package moby package local
import ( import (
"bufio" "bufio"
@ -24,12 +24,12 @@ import (
"github.com/docker/api/errdefs" "github.com/docker/api/errdefs"
) )
type mobyService struct { type local struct {
apiClient *client.Client apiClient *client.Client
} }
func init() { func init() {
backend.Register("moby", "moby", service, cloud.NotImplementedCloudService) backend.Register("local", "local", service, cloud.NotImplementedCloudService)
} }
func service(ctx context.Context) (backend.Service, error) { func service(ctx context.Context) (backend.Service, error) {
@ -38,20 +38,20 @@ func service(ctx context.Context) (backend.Service, error) {
return nil, err return nil, err
} }
return &mobyService{ return &local{
apiClient, apiClient,
}, nil }, nil
} }
func (ms *mobyService) ContainerService() containers.Service { func (ms *local) ContainerService() containers.Service {
return ms return ms
} }
func (ms *mobyService) ComposeService() compose.Service { func (ms *local) ComposeService() compose.Service {
return nil return nil
} }
func (ms *mobyService) List(ctx context.Context, all bool) ([]containers.Container, error) { func (ms *local) List(ctx context.Context, all bool) ([]containers.Container, error) {
css, err := ms.apiClient.ContainerList(ctx, types.ContainerListOptions{ css, err := ms.apiClient.ContainerList(ctx, types.ContainerListOptions{
All: all, All: all,
}) })
@ -78,7 +78,7 @@ func (ms *mobyService) List(ctx context.Context, all bool) ([]containers.Contain
return result, nil return result, nil
} }
func (ms *mobyService) Run(ctx context.Context, r containers.ContainerConfig) error { func (ms *local) Run(ctx context.Context, r containers.ContainerConfig) error {
exposedPorts, hostBindings, err := fromPorts(r.Ports) exposedPorts, hostBindings, err := fromPorts(r.Ports)
if err != nil { if err != nil {
return err return err
@ -125,7 +125,7 @@ func (ms *mobyService) Run(ctx context.Context, r containers.ContainerConfig) er
return ms.apiClient.ContainerStart(ctx, created.ID, types.ContainerStartOptions{}) return ms.apiClient.ContainerStart(ctx, created.ID, types.ContainerStartOptions{})
} }
func (ms *mobyService) Stop(ctx context.Context, containerID string, timeout *uint32) error { func (ms *local) Stop(ctx context.Context, containerID string, timeout *uint32) error {
var t *time.Duration var t *time.Duration
if timeout != nil { if timeout != nil {
timeoutValue := time.Duration(*timeout) * time.Second timeoutValue := time.Duration(*timeout) * time.Second
@ -134,7 +134,7 @@ func (ms *mobyService) Stop(ctx context.Context, containerID string, timeout *ui
return ms.apiClient.ContainerStop(ctx, containerID, t) return ms.apiClient.ContainerStop(ctx, containerID, t)
} }
func (ms *mobyService) Exec(ctx context.Context, name string, command string, reader io.Reader, writer io.Writer) error { func (ms *local) Exec(ctx context.Context, name string, command string, reader io.Reader, writer io.Writer) error {
cec, err := ms.apiClient.ContainerExecCreate(ctx, name, types.ExecConfig{ cec, err := ms.apiClient.ContainerExecCreate(ctx, name, types.ExecConfig{
Cmd: []string{command}, Cmd: []string{command},
Tty: true, Tty: true,
@ -176,7 +176,7 @@ func (ms *mobyService) Exec(ctx context.Context, name string, command string, re
} }
} }
func (ms *mobyService) Logs(ctx context.Context, containerName string, request containers.LogsRequest) error { func (ms *local) Logs(ctx context.Context, containerName string, request containers.LogsRequest) error {
c, err := ms.apiClient.ContainerInspect(ctx, containerName) c, err := ms.apiClient.ContainerInspect(ctx, containerName)
if err != nil { if err != nil {
return err return err
@ -204,7 +204,7 @@ func (ms *mobyService) Logs(ctx context.Context, containerName string, request c
return err return err
} }
func (ms *mobyService) Delete(ctx context.Context, containerID string, force bool) error { func (ms *local) Delete(ctx context.Context, containerID string, force bool) error {
err := ms.apiClient.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{ err := ms.apiClient.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{
Force: force, Force: force,
}) })

View File

@ -11,26 +11,26 @@ import (
"github.com/docker/api/tests/framework" "github.com/docker/api/tests/framework"
) )
type MobyBackendTestSuite struct { type LocalBackendTestSuite struct {
framework.Suite framework.Suite
} }
func (m *MobyBackendTestSuite) BeforeTest(suiteName string, testName string) { func (m *LocalBackendTestSuite) BeforeTest(suiteName string, testName string) {
m.NewDockerCommand("context", "create", "test-context", "moby").ExecOrDie() m.NewDockerCommand("context", "create", "local", "test-context").ExecOrDie()
m.NewDockerCommand("context", "use", "test-context").ExecOrDie() m.NewDockerCommand("context", "use", "test-context").ExecOrDie()
} }
func (m *MobyBackendTestSuite) AfterTest(suiteName string, testName string) { func (m *LocalBackendTestSuite) AfterTest(suiteName string, testName string) {
m.NewDockerCommand("context", "rm", "test-context").ExecOrDie() m.NewDockerCommand("context", "rm", "test-context").ExecOrDie()
m.NewDockerCommand("context", "use", "default").ExecOrDie() m.NewDockerCommand("context", "use", "default").ExecOrDie()
} }
func (m *MobyBackendTestSuite) TestPs() { func (m *LocalBackendTestSuite) TestPs() {
out := m.NewDockerCommand("ps").ExecOrDie() out := m.NewDockerCommand("ps").ExecOrDie()
require.Equal(m.T(), "CONTAINER ID IMAGE COMMAND STATUS PORTS\n", out) require.Equal(m.T(), "CONTAINER ID IMAGE COMMAND STATUS PORTS\n", out)
} }
func (m *MobyBackendTestSuite) TestRun() { func (m *LocalBackendTestSuite) TestRun() {
_, err := m.NewDockerCommand("run", "--name", "nginx", "nginx").Exec() _, err := m.NewDockerCommand("run", "--name", "nginx", "nginx").Exec()
require.Nil(m.T(), err) require.Nil(m.T(), err)
out := m.NewDockerCommand("ps").ExecOrDie() out := m.NewDockerCommand("ps").ExecOrDie()
@ -41,7 +41,7 @@ func (m *MobyBackendTestSuite) TestRun() {
assert.Equal(m.T(), 3, len(lines)) assert.Equal(m.T(), 3, len(lines))
} }
func (m *MobyBackendTestSuite) TestRunWithPorts() { func (m *LocalBackendTestSuite) TestRunWithPorts() {
_, err := m.NewDockerCommand("run", "--name", "nginx", "-p", "8080:80", "nginx").Exec() _, err := m.NewDockerCommand("run", "--name", "nginx", "-p", "8080:80", "nginx").Exec()
require.Nil(m.T(), err) require.Nil(m.T(), err)
out := m.NewDockerCommand("ps").ExecOrDie() out := m.NewDockerCommand("ps").ExecOrDie()
@ -51,6 +51,6 @@ func (m *MobyBackendTestSuite) TestRunWithPorts() {
assert.Contains(m.T(), out, "8080") assert.Contains(m.T(), out, "8080")
} }
func TestMobyBackendTestSuite(t *testing.T) { func TestLocalBackendTestSuite(t *testing.T) {
suite.Run(t, new(MobyBackendTestSuite)) suite.Run(t, new(LocalBackendTestSuite))
} }

View File

@ -38,16 +38,6 @@ type E2eACISuite struct {
Suite Suite
} }
func (s *E2eACISuite) TestContextHelp() {
It("ensures context command includes azure-login and aci-create", func() {
output := s.NewDockerCommand("context", "create", "--help").ExecOrDie()
Expect(output).To(ContainSubstring("docker context create CONTEXT BACKEND [OPTIONS] [flags]"))
Expect(output).To(ContainSubstring("--aci-location"))
Expect(output).To(ContainSubstring("--aci-subscription-id"))
Expect(output).To(ContainSubstring("--aci-resource-group"))
})
}
func (s *E2eACISuite) TestContextDefault() { func (s *E2eACISuite) TestContextDefault() {
It("should be initialized with default context", func() { It("should be initialized with default context", func() {
_, err := s.NewCommand("docker", "context", "rm", "-f", contextName).Exec() _, err := s.NewCommand("docker", "context", "rm", "-f", contextName).Exec()
@ -70,7 +60,7 @@ func (s *E2eACISuite) TestACIBackend() {
Expect(err).To(BeNil()) Expect(err).To(BeNil())
subscriptionID = *models[0].SubscriptionID subscriptionID = *models[0].SubscriptionID
s.NewDockerCommand("context", "create", contextName, "aci", "--aci-subscription-id", subscriptionID, "--aci-resource-group", resourceGroupName, "--aci-location", location).ExecOrDie() s.NewDockerCommand("context", "create", "aci", contextName, "--subscription-id", subscriptionID, "--resource-group", resourceGroupName, "--location", location).ExecOrDie()
// Expect(output).To(ContainSubstring("ACI context acitest created")) // Expect(output).To(ContainSubstring("ACI context acitest created"))
}) })

View File

@ -46,36 +46,36 @@ type E2eSuite struct {
} }
func (s *E2eSuite) TestContextHelp() { func (s *E2eSuite) TestContextHelp() {
It("ensures context command includes azure-login and aci-create", func() { output := s.NewDockerCommand("context", "create", "aci", "--help").ExecOrDie()
output := s.NewDockerCommand("context", "create", "--help").ExecOrDie() Expect(output).To(ContainSubstring("docker context create aci CONTEXT [flags]"))
Expect(output).To(ContainSubstring("docker context create CONTEXT BACKEND [OPTIONS] [flags]")) Expect(output).To(ContainSubstring("--location"))
Expect(output).To(ContainSubstring("--aci-location")) Expect(output).To(ContainSubstring("--subscription-id"))
Expect(output).To(ContainSubstring("--aci-subscription-id")) Expect(output).To(ContainSubstring("--resource-group"))
Expect(output).To(ContainSubstring("--aci-resource-group"))
})
} }
func (s *E2eSuite) TestContextDefault() { func (s *E2eSuite) TestListAndShowDefaultContext() {
It("should be initialized with default context", func() {
output := s.NewDockerCommand("context", "show").ExecOrDie() output := s.NewDockerCommand("context", "show").ExecOrDie()
Expect(output).To(ContainSubstring("default")) Expect(output).To(ContainSubstring("default"))
output = s.NewCommand("docker", "context", "ls").ExecOrDie() output = s.NewCommand("docker", "context", "ls").ExecOrDie()
golden.Assert(s.T(), output, GoldenFile("ls-out-default")) golden.Assert(s.T(), output, GoldenFile("ls-out-default"))
})
} }
func (s *E2eSuite) TestContextLegacy() { func (s *E2eSuite) TestCreateDockerContextAndListIt() {
It("should inspect default", func() { s.NewDockerCommand("context", "create", "test-docker", "--from", "default").ExecOrDie()
output := s.NewCommand("docker", "context", "ls").ExecOrDie()
golden.Assert(s.T(), output, GoldenFile("ls-out-test-docker"))
}
func (s *E2eSuite) TestInspectDefaultContext() {
output := s.NewDockerCommand("context", "inspect", "default").ExecOrDie() output := s.NewDockerCommand("context", "inspect", "default").ExecOrDie()
Expect(output).To(ContainSubstring(`"Name": "default"`)) Expect(output).To(ContainSubstring(`"Name": "default"`))
})
} }
func (s *E2eSuite) TestContextCreateParseErrorDoesNotDelegateToLegacy() { func (s *E2eSuite) TestContextCreateParseErrorDoesNotDelegateToLegacy() {
It("should dispay new cli error when parsing context create flags", func() { It("should dispay new cli error when parsing context create flags", func() {
_, err := s.NewDockerCommand("context", "create", "--aci-subscription-id", "titi").Exec() _, err := s.NewDockerCommand("context", "create", "aci", "--subscription-id", "titi").Exec()
Expect(err.Error()).NotTo(ContainSubstring("unknown flag")) Expect(err.Error()).NotTo(ContainSubstring("unknown flag"))
Expect(err.Error()).To(ContainSubstring("accepts 2 arg(s), received 0")) Expect(err.Error()).To(ContainSubstring("accepts 1 arg(s), received 0"))
}) })
} }
@ -135,7 +135,7 @@ func (s *E2eSuite) TestLeaveLegacyErrorMessagesUnchanged() {
} }
func (s *E2eSuite) TestDisplayFriendlyErrorMessageForLegacyCommands() { func (s *E2eSuite) TestDisplayFriendlyErrorMessageForLegacyCommands() {
s.NewDockerCommand("context", "create", "test-example", "example").ExecOrDie() s.NewDockerCommand("context", "create", "example", "test-example").ExecOrDie()
output, err := s.NewDockerCommand("--context", "test-example", "images").Exec() output, err := s.NewDockerCommand("--context", "test-example", "images").Exec()
Expect(output).To(Equal("Command \"images\" not available in current context (test-example), you can use the \"default\" context to run this command\n")) Expect(output).To(Equal("Command \"images\" not available in current context (test-example), you can use the \"default\" context to run this command\n"))
Expect(err).NotTo(BeNil()) Expect(err).NotTo(BeNil())
@ -149,7 +149,7 @@ func (s *E2eSuite) TestDisplaysAdditionalLineInDockerVersion() {
func (s *E2eSuite) TestMockBackend() { func (s *E2eSuite) TestMockBackend() {
It("creates a new test context to hardcoded example backend", func() { It("creates a new test context to hardcoded example backend", func() {
s.NewDockerCommand("context", "create", "test-example", "example").ExecOrDie() s.NewDockerCommand("context", "create", "example", "test-example").ExecOrDie()
// Expect(output).To(ContainSubstring("test-example context acitest created")) // Expect(output).To(ContainSubstring("test-example context acitest created"))
}) })

View File

@ -1,2 +1,2 @@
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default * docker Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm default * moby Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm

View File

@ -1,2 +1,2 @@
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default * docker Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm default * moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm

View File

@ -0,0 +1,3 @@
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default * moby Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm
test-docker moby npipe:////./pipe/docker_engine swarm

View File

@ -0,0 +1,3 @@
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default * moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
test-docker moby unix:///var/run/docker.sock swarm

View File

@ -1,3 +1,3 @@
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default docker Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm default moby Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm
test-example * example test-example * example

View File

@ -1,3 +1,3 @@
NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR NAME TYPE DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default docker Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm default moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
test-example * example test-example * example