Browse Source

set build tag for the ecs context and backend

Signed-off-by: aiordache <[email protected]>
aiordache 5 years ago
parent
commit
2471e51b39

+ 2 - 2
.github/workflows/ci.yml

@@ -45,12 +45,12 @@ jobs:
 
       - name: Test
         env:
-          BUILD_TAGS: example,local
+          BUILD_TAGS: example,local,ecs
         run: make -f builder.Makefile test
 
       - name: Build
         env:
-          BUILD_TAGS: example,local
+          BUILD_TAGS: example,local,ecs
         run: make -f builder.Makefile cli
 
       - name: E2E Test

+ 2 - 2
Makefile

@@ -34,7 +34,7 @@ protos: ## Generate go code from .proto files
 cli: ## Compile the cli
 	@docker build . --target cli \
 	--platform local \
-	--build-arg BUILD_TAGS=example,local \
+	--build-arg BUILD_TAGS=example,local,ecs \
 	--build-arg GIT_TAG=$(GIT_TAG) \
 	--output ./bin
 
@@ -55,7 +55,7 @@ cross: ## Compile the CLI for linux, darwin and windows
 
 test: ## Run unit tests
 	@docker build . \
-	--build-arg BUILD_TAGS=example,local \
+	--build-arg BUILD_TAGS=example,local,ecs \
 	--build-arg GIT_TAG=$(GIT_TAG) \
 	--target test
 

+ 39 - 21
amazon/backend.go

@@ -1,3 +1,18 @@
+// +build ecs
+
+/*
+   Copyright 2020 Docker, Inc.
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+       http://www.apache.org/licenses/LICENSE-2.0
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package amazon
 
 import (
@@ -9,9 +24,12 @@ import (
 	apicontext "github.com/docker/api/context"
 	"github.com/docker/api/context/cloud"
 	"github.com/docker/api/context/store"
-	aws "github.com/docker/ecs-plugin/pkg/amazon/backend"
+	"github.com/docker/api/errdefs"
+	ecs "github.com/docker/ecs-plugin/pkg/amazon/backend"
 )
 
+const backendType = store.EcsContextType
+
 // ContextParams options for creating AWS context
 type ContextParams struct {
 	Description string
@@ -23,61 +41,61 @@ type ContextParams struct {
 }
 
 func init() {
-	backend.Register("aws", "aws", service, getCloudService)
+	backend.Register(backendType, backendType, service, getCloudService)
 }
 
 func service(ctx context.Context) (backend.Service, error) {
 	contextStore := store.ContextStore(ctx)
 	currentContext := apicontext.CurrentContext(ctx)
-	var awsContext store.AwsContext
+	var ecsContext store.EcsContext
 
-	if err := contextStore.GetEndpoint(currentContext, &awsContext); err != nil {
+	if err := contextStore.GetEndpoint(currentContext, &ecsContext); err != nil {
 		return nil, err
 	}
 
-	return getAwsAPIService(awsContext)
+	return getEcsAPIService(ecsContext)
 }
 
-func getAwsAPIService(awsCtx store.AwsContext) (*awsAPIService, error) {
-	backend, err := aws.NewBackend(awsCtx.Profile, awsCtx.Region)
+func getEcsAPIService(ecsCtx store.EcsContext) (*ecsAPIService, error) {
+	backend, err := ecs.NewBackend(ecsCtx.Profile, ecsCtx.Region)
 	if err != nil {
 		return nil, err
 	}
-	return &awsAPIService{
-		ctx:            awsCtx,
+	return &ecsAPIService{
+		ctx:            ecsCtx,
 		composeBackend: backend,
 	}, nil
 }
 
-type awsAPIService struct {
-	ctx            store.AwsContext
-	composeBackend *aws.Backend
+type ecsAPIService struct {
+	ctx            store.EcsContext
+	composeBackend *ecs.Backend
 }
 
-func (a *awsAPIService) ContainerService() containers.Service {
+func (a *ecsAPIService) ContainerService() containers.Service {
 	return nil
 }
 
-func (a *awsAPIService) ComposeService() compose.Service {
+func (a *ecsAPIService) ComposeService() compose.Service {
 	return a.composeBackend
 }
 
 func getCloudService() (cloud.Service, error) {
-	return awsCloudService{}, nil
+	return ecsCloudService{}, nil
 }
 
-type awsCloudService struct {
+type ecsCloudService struct {
 }
 
-func (a awsCloudService) Login(ctx context.Context, params interface{}) error {
-	return nil
+func (a ecsCloudService) Login(ctx context.Context, params interface{}) error {
+	return errdefs.ErrNotImplemented
 }
 
-func (a awsCloudService) Logout(ctx context.Context) error {
-	return nil
+func (a ecsCloudService) Logout(ctx context.Context) error {
+	return errdefs.ErrNotImplemented
 }
 
-func (a awsCloudService) CreateContextData(ctx context.Context, params interface{}) (interface{}, string, error) {
+func (a ecsCloudService) CreateContextData(ctx context.Context, params interface{}) (interface{}, string, error) {
 	contextHelper := newContextCreateHelper()
 	createOpts := params.(ContextParams)
 	return contextHelper.createContextData(ctx, createOpts)

+ 27 - 18
amazon/context.go

@@ -1,3 +1,18 @@
+// +build ecs
+
+/*
+   Copyright 2020 Docker, Inc.
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+       http://www.apache.org/licenses/LICENSE-2.0
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
 package amazon
 
 import (
@@ -30,31 +45,31 @@ func (h contextCreateAWSHelper) createContextData(_ context.Context, opts Contex
 	accessKey := opts.AwsID
 	secretKey := opts.AwsSecret
 
-	awsCtx := store.AwsContext{
+	ecsCtx := store.EcsContext{
 		Profile: opts.Profile,
 		Region:  opts.Region,
 	}
 
-	if h.missingRequiredFlags(awsCtx) {
+	if h.missingRequiredFlags(ecsCtx) {
 		profilesList, err := h.getProfiles()
 		if err != nil {
 			return nil, "", err
 		}
 		// get profile
-		_, ok := profilesList[awsCtx.Profile]
+		_, ok := profilesList[ecsCtx.Profile]
 		if !ok {
 			profile, err := h.chooseProfile(profilesList)
 			if err != nil {
 				return nil, "", err
 			}
-			awsCtx.Profile = profile
+			ecsCtx.Profile = profile
 		}
 		// set region
-		region, err := h.chooseRegion(awsCtx.Region, profilesList[awsCtx.Profile])
+		region, err := h.chooseRegion(ecsCtx.Region, profilesList[ecsCtx.Profile])
 		if err != nil {
 			return nil, "", err
 		}
-		awsCtx.Region = region
+		ecsCtx.Region = region
 
 		accessKey, secretKey, err = h.askCredentials()
 		if err != nil {
@@ -62,20 +77,20 @@ func (h contextCreateAWSHelper) createContextData(_ context.Context, opts Contex
 		}
 	}
 	if accessKey != "" && secretKey != "" {
-		if err := h.saveCredentials(awsCtx.Profile, accessKey, secretKey); err != nil {
+		if err := h.saveCredentials(ecsCtx.Profile, accessKey, secretKey); err != nil {
 			return nil, "", err
 		}
 	}
 
-	description := awsCtx.Region
+	description := ecsCtx.Region
 	if opts.Description != "" {
 		description = fmt.Sprintf("%s (%s)", opts.Description, description)
 	}
 
-	return awsCtx, description, nil
+	return ecsCtx, description, nil
 }
 
-func (h contextCreateAWSHelper) missingRequiredFlags(ctx store.AwsContext) bool {
+func (h contextCreateAWSHelper) missingRequiredFlags(ctx store.EcsContext) bool {
 	if ctx.Profile == "" || ctx.Region == "" {
 		return true
 	}
@@ -86,8 +101,7 @@ func (h contextCreateAWSHelper) saveCredentials(profile string, accessKeyID stri
 	p := credentials.SharedCredentialsProvider{Profile: profile}
 	_, err := p.Retrieve()
 	if err == nil {
-		fmt.Println("credentials already exists!")
-		return nil
+		return fmt.Errorf("credentials already exists!")
 	}
 
 	if err.(awserr.Error).Code() == "SharedCredsLoad" && err.(awserr.Error).Message() == "failed to load shared credentials file" {
@@ -121,9 +135,6 @@ func (h contextCreateAWSHelper) getProfiles() (map[string]ini.Section, error) {
 	if err != nil {
 		return nil, err
 	}
-	if err != nil {
-		return nil, err
-	}
 	for _, section := range credIni.Sections() {
 		if strings.HasPrefix(section.Name(), "profile") {
 			profiles[section.Name()[len("profile "):]] = *section
@@ -142,14 +153,12 @@ func (h contextCreateAWSHelper) chooseProfile(section map[string]ini.Section) (s
 	selected, err := h.user.Select("Select AWS Profile", profiles)
 	if err != nil {
 		if err == terminal.InterruptErr {
-			os.Exit(0)
+			os.Exit(-1)
 		}
 		return "", err
 	}
 	profile := profiles[selected]
-
 	if profiles[selected] == "new profile" {
-
 		return h.user.Input("profile name", "")
 	}
 	return profile, nil

+ 1 - 0
amazon/doc.go

@@ -0,0 +1 @@
+package amazon

+ 13 - 6
cli/cmd/context/create.go

@@ -18,6 +18,8 @@ package context
 
 import (
 	"context"
+	"fmt"
+	"strings"
 
 	"github.com/spf13/cobra"
 
@@ -29,15 +31,18 @@ type descriptionCreateOpts struct {
 	description string
 }
 
+var extraCommands []func() *cobra.Command
+var extraHelp []string
+
 func createCommand() *cobra.Command {
-	const longHelp = `Create a new context
+	help := strings.Join(extraHelp, "\n")
+
+	longHelp := fmt.Sprintf(`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)
+%s
 
 Docker endpoint config:
 
@@ -59,7 +64,7 @@ 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"`
+$ docker context create my-context --description "some description" --docker "host=tcp://myserver:2376,ca=~/ca-file,cert=~/cert-file,key=~/key-file"`, help)
 
 	cmd := &cobra.Command{
 		Use:   "create CONTEXT",
@@ -72,10 +77,12 @@ $ docker context create my-context --description "some description" --docker "ho
 
 	cmd.AddCommand(
 		createAciCommand(),
-		createAwsCommand(),
 		createLocalCommand(),
 		createExampleCommand(),
 	)
+	for _, command := range extraCommands {
+		cmd.AddCommand(command())
+	}
 
 	flags := cmd.Flags()
 	flags.String("description", "", "Description of the context")

+ 9 - 0
cli/cmd/context/createaci.go

@@ -28,6 +28,15 @@ import (
 	"github.com/docker/api/errdefs"
 )
 
+func init() {
+	extraCommands = append(extraCommands, createAciCommand)
+	extraHelp = append(extraHelp, `
+Create Azure Container Instances context:
+$ docker context create aci CONTEXT [flags]
+(see docker context create aci --help)
+`)
+}
+
 func createAciCommand() *cobra.Command {
 	var opts azure.ContextParams
 	cmd := &cobra.Command{

+ 21 - 10
cli/cmd/context/createaws.go → cli/cmd/context/createecs.go

@@ -1,3 +1,5 @@
+// +build ecs
+
 /*
    Copyright 2020 Docker, Inc.
 
@@ -28,39 +30,48 @@ import (
 	"github.com/docker/api/errdefs"
 )
 
-func createAwsCommand() *cobra.Command {
+func init() {
+	extraCommands = append(extraCommands, createEcsCommand)
+	extraHelp = append(extraHelp, `
+Create Amazon ECS context:
+$ docker context create ecs CONTEXT [flags]
+(see docker context create ecs --help)
+`)
+}
+
+func createEcsCommand() *cobra.Command {
 	var opts amazon.ContextParams
 	cmd := &cobra.Command{
-		Use:   "aws CONTEXT [flags]",
+		Use:   "ecs CONTEXT [flags]",
 		Short: "Create a context for Amazon ECS",
 		Args:  cobra.ExactArgs(1),
 		RunE: func(cmd *cobra.Command, args []string) error {
-			return runCreateAws(cmd.Context(), args[0], opts)
+			return runCreateEcs(cmd.Context(), args[0], opts)
 		},
 	}
 
 	addDescriptionFlag(cmd, &opts.Description)
-	cmd.Flags().StringVar(&opts.Profile, "profile", "", "AWS Profile")
-	cmd.Flags().StringVar(&opts.Region, "region", "", "AWS region")
+	cmd.Flags().StringVar(&opts.Profile, "profile", "", "Profile")
+	cmd.Flags().StringVar(&opts.Region, "region", "", "Region")
 	cmd.Flags().StringVar(&opts.AwsID, "key-id", "", "AWS Access Key ID")
 	cmd.Flags().StringVar(&opts.AwsSecret, "secret-key", "", "AWS Secret Access Key")
 	return cmd
 }
 
-func runCreateAws(ctx context.Context, contextName string, opts amazon.ContextParams) error {
+func runCreateEcs(ctx context.Context, contextName string, opts amazon.ContextParams) error {
 	if contextExists(ctx, contextName) {
 		return errors.Wrapf(errdefs.ErrAlreadyExists, "context %s", contextName)
 	}
-	contextData, description, err := getAwsContextData(ctx, opts)
+	contextData, description, err := getEcsContextData(ctx, opts)
 	if err != nil {
 		return err
 	}
-	return createDockerContext(ctx, contextName, store.AwsContextType, description, contextData)
+	return createDockerContext(ctx, contextName, store.EcsContextType, description, contextData)
 
 }
 
-func getAwsContextData(ctx context.Context, opts amazon.ContextParams) (interface{}, string, error) {
-	cs, err := client.GetCloudService(ctx, store.AwsContextType)
+func getEcsContextData(ctx context.Context, opts amazon.ContextParams) (interface{}, string, error) {
+	cs, err := client.GetCloudService(ctx, store.EcsContextType)
 	if err != nil {
 		return nil, "", errors.Wrap(err, "cannot connect to AWS backend")
 	}

+ 2 - 2
context/store/contextmetadata.go

@@ -49,8 +49,8 @@ type AciContext struct {
 	ResourceGroup  string `json:",omitempty"`
 }
 
-// AwsContext is the context for the AWS backend
-type AwsContext struct {
+// EcsContext is the context for the AWS backend
+type EcsContext struct {
 	Profile string `json:",omitempty"`
 	Region  string `json:",omitempty"`
 }

+ 4 - 4
context/store/store.go

@@ -36,8 +36,8 @@ const (
 	DefaultContextName = "default"
 	// DefaultContextType is the type for all moby contexts (not associated with cli backend)
 	DefaultContextType = "moby"
-	// AwsContextType is the type for ecs contexts (currently a CLI plugin, not associated with cli backend)
-	AwsContextType = "aws"
+	// EcsContextType is the type for ecs contexts (currently a CLI plugin, not associated with cli backend)
+	EcsContextType = "ecs"
 	// AciContextType is the endpoint key in the context endpoints for an ACI
 	// backend
 	AciContextType = "aci"
@@ -339,8 +339,8 @@ func getters() map[string]func() interface{} {
 		AciContextType: func() interface{} {
 			return &AciContext{}
 		},
-		AwsContextType: func() interface{} {
-			return &AwsContext{}
+		EcsContextType: func() interface{} {
+			return &EcsContext{}
 		},
 		LocalContextType: func() interface{} {
 			return &LocalContext{}

+ 3 - 2
go.mod

@@ -1,7 +1,8 @@
 module github.com/docker/api
 
 go 1.14
-
+// the distribution version from ecs plugin is quite old and it breaks containerd
+// we need to create a new release tag for docker/distribution
 replace github.com/docker/distribution => github.com/docker/distribution v0.0.0-20200708230824-53e18a9d9bfe
 
 require (
@@ -24,7 +25,7 @@ require (
 	github.com/containerd/containerd v1.3.5 // indirect
 	github.com/docker/cli v0.0.0-20200528204125-dd360c7c0de8
 	github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible
-	github.com/docker/ecs-plugin v1.0.0-beta.2
+	github.com/docker/ecs-plugin v1.0.0-beta.4
 	github.com/docker/go-connections v0.4.0
 	github.com/docker/go-units v0.4.0
 	github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee // indirect

+ 2 - 0
go.sum

@@ -172,6 +172,8 @@ github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGl
 github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
 github.com/docker/ecs-plugin v1.0.0-beta.2 h1:Z9Krz+7zKXusWzENXuskQg7n/3/ViC/cfUl4XYiJWUI=
 github.com/docker/ecs-plugin v1.0.0-beta.2/go.mod h1:1YaNZwrNr0dFjTP3v7zwepluaZgVNV94s0M6fL+i/iA=
+github.com/docker/ecs-plugin v1.0.0-beta.4 h1:hZKojW0tqsdhJjfMKPw6piMw/GJgfX6CVXd1YUuXLg4=
+github.com/docker/ecs-plugin v1.0.0-beta.4/go.mod h1:1YaNZwrNr0dFjTP3v7zwepluaZgVNV94s0M6fL+i/iA=
 github.com/docker/go v1.5.1-1 h1:hr4w35acWBPhGBXlzPoHpmZ/ygPjnmFVxGxxGnMyP7k=
 github.com/docker/go v1.5.1-1/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
 github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=