浏览代码

Fix Azure login : allow getting a backend when no corresponding context already exists with an explicit call from the login command. Will be usefull next for context creation with azure interactive things

Guillaume Tardif 5 年之前
父节点
当前提交
01aaec2dbe
共有 8 个文件被更改,包括 80 次插入58 次删除
  1. 19 24
      azure/backend.go
  2. 11 3
      azure/backend_test.go
  3. 19 5
      backend/backend.go
  4. 3 4
      cli/cmd/context/login/login.go
  5. 5 6
      client/client.go
  6. 17 1
      context/cloud/api.go
  7. 4 6
      example/backend.go
  8. 2 9
      moby/backend.go

+ 19 - 24
azure/backend.go

@@ -31,58 +31,53 @@ const singleContainerName = "single--container--aci"
 var ErrNoSuchContainer = errors.New("no such container")
 
 func init() {
-	backend.Register("aci", "aci", func(ctx context.Context) (backend.Service, error) {
-		return New(ctx)
-	})
+	backend.Register("aci", "aci", service, getCloudService)
 }
 
-// New creates a backend that can manage containers
-func New(ctx context.Context) (backend.Service, error) {
-	currentContext := apicontext.CurrentContext(ctx)
+func service(ctx context.Context) (backend.Service, error) {
 	contextStore := store.ContextStore(ctx)
-
+	currentContext := apicontext.CurrentContext(ctx)
 	var aciContext store.AciContext
+
 	if err := contextStore.GetEndpoint(currentContext, &aciContext); err != nil {
 		return nil, err
 	}
 
-	return getAciAPIService(aciContext)
+	return getAciAPIService(aciContext), nil
 }
 
-func getAciAPIService(aciCtx store.AciContext) (*aciAPIService, error) {
+func getCloudService() (cloud.Service, error) {
 	service, err := login.NewAzureLoginService()
 	if err != nil {
 		return nil, err
 	}
+	return &aciCloudService{
+		loginService: service,
+	}, nil
+}
+
+func getAciAPIService(aciCtx store.AciContext) *aciAPIService {
 	return &aciAPIService{
-		aciContainerService: aciContainerService{
+		aciContainerService: &aciContainerService{
 			ctx: aciCtx,
 		},
-		aciComposeService: aciComposeService{
+		aciComposeService: &aciComposeService{
 			ctx: aciCtx,
 		},
-		aciCloudService: aciCloudService{
-			loginService: service,
-		},
-	}, nil
+	}
 }
 
 type aciAPIService struct {
-	aciContainerService
-	aciComposeService
-	aciCloudService
+	*aciContainerService
+	*aciComposeService
 }
 
 func (a *aciAPIService) ContainerService() containers.Service {
-	return &a.aciContainerService
+	return a.aciContainerService
 }
 
 func (a *aciAPIService) ComposeService() compose.Service {
-	return &a.aciComposeService
-}
-
-func (a *aciAPIService) CloudService() cloud.Service {
-	return &a.aciCloudService
+	return a.aciComposeService
 }
 
 type aciContainerService struct {

+ 11 - 3
azure/backend_test.go

@@ -3,13 +3,16 @@ package azure
 import (
 	"testing"
 
+	"github.com/stretchr/testify/suite"
+
 	. "github.com/onsi/gomega"
 )
 
-// TestGetContainerName ensures we can read container group name / container name from a containerID
-func TestGetContainerName(t *testing.T) {
-	RegisterTestingT(t)
+type BackendSuiteTest struct {
+	suite.Suite
+}
 
+func (suite *BackendSuiteTest) TestGetContainerName() {
 	group, container := getGroupAndContainerName("docker1234")
 	Expect(group).To(Equal("docker1234"))
 	Expect(container).To(Equal(singleContainerName))
@@ -22,3 +25,8 @@ func TestGetContainerName(t *testing.T) {
 	Expect(group).To(Equal("compose_stack"))
 	Expect(container).To(Equal("service1"))
 }
+
+func TestBackendSuite(t *testing.T) {
+	RegisterTestingT(t)
+	suite.Run(t, new(BackendSuiteTest))
+}

+ 19 - 5
backend/backend.go

@@ -19,11 +19,13 @@ var (
 )
 
 type initFunc func(context.Context) (Service, error)
+type getCloudServiceFunc func() (cloud.Service, error)
 
 type registeredBackend struct {
-	name        string
-	backendType string
-	init        initFunc
+	name            string
+	backendType     string
+	init            initFunc
+	getCloudService getCloudServiceFunc
 }
 
 var backends = struct {
@@ -34,11 +36,10 @@ var backends = struct {
 type Service interface {
 	ContainerService() containers.Service
 	ComposeService() compose.Service
-	CloudService() cloud.Service
 }
 
 // Register adds a typed backend to the registry
-func Register(name string, backendType string, init initFunc) {
+func Register(name string, backendType string, init initFunc, getCoudService getCloudServiceFunc) {
 	if name == "" {
 		logrus.Fatal(errNoName)
 	}
@@ -55,6 +56,7 @@ func Register(name string, backendType string, init initFunc) {
 		name,
 		backendType,
 		init,
+		getCoudService,
 	})
 }
 
@@ -69,3 +71,15 @@ func Get(ctx context.Context, backendType string) (Service, error) {
 
 	return nil, fmt.Errorf("backend not found for context %q", backendType)
 }
+
+// GetCloudService returns the backend registered for a particular type, it returns
+// an error if there is no registered backends for the given type.
+func GetCloudService(ctx context.Context, backendType string) (cloud.Service, error) {
+	for _, b := range backends.r {
+		if b.backendType == backendType {
+			return b.getCloudService()
+		}
+	}
+
+	return nil, fmt.Errorf("backend not found for backend type %s", backendType)
+}

+ 3 - 4
cli/cmd/context/login/login.go

@@ -5,7 +5,6 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/docker/api/client"
-	apicontext "github.com/docker/api/context"
 )
 
 // Command returns the compose command with its child commands
@@ -24,12 +23,12 @@ func azureLoginCommand() *cobra.Command {
 	azureLoginCmd := &cobra.Command{
 		Use: "azure",
 		RunE: func(cmd *cobra.Command, args []string) error {
-			ctx := apicontext.WithCurrentContext(cmd.Context(), "aci")
-			c, err := client.New(ctx)
+			ctx := cmd.Context()
+			cs, err := client.GetCloudService(ctx, "aci")
 			if err != nil {
 				return errors.Wrap(err, "cannot connect to backend")
 			}
-			return c.CloudService().Login(ctx, nil)
+			return cs.Login(ctx, nil)
 		},
 	}
 

+ 5 - 6
client/client.go

@@ -39,7 +39,7 @@ import (
 	"github.com/docker/api/context/store"
 )
 
-// New returns a backend client
+// New returns a backend client associated with current context
 func New(ctx context.Context) (*Client, error) {
 	currentContext := apicontext.CurrentContext(ctx)
 	s := store.ContextStore(ctx)
@@ -58,7 +58,11 @@ func New(ctx context.Context) (*Client, error) {
 		backendType: cc.Type,
 		bs:          service,
 	}, nil
+}
 
+// GetCloudService returns a backend CloudService (typically login, create context)
+func GetCloudService(ctx context.Context, backendType string) (cloud.Service, error) {
+	return backend.GetCloudService(ctx, backendType)
 }
 
 // Client is a multi-backend client
@@ -76,8 +80,3 @@ func (c *Client) ContainerService() containers.Service {
 func (c *Client) ComposeService() compose.Service {
 	return c.bs.ComposeService()
 }
-
-// CloudService returns the backend service for the current context
-func (c *Client) CloudService() cloud.Service {
-	return c.bs.CloudService()
-}

+ 17 - 1
context/cloud/api.go

@@ -1,9 +1,25 @@
 package cloud
 
-import "context"
+import (
+	"context"
+
+	"github.com/docker/api/errdefs"
+)
 
 // Service cloud specific services
 type Service interface {
 	// Login login to cloud provider
 	Login(ctx context.Context, params map[string]string) error
 }
+
+// NotImplementedCloudService to use for backend that don't provide cloud services
+func NotImplementedCloudService() (Service, error) {
+	return notImplementedCloudService{}, nil
+}
+
+type notImplementedCloudService struct {
+}
+
+func (cs notImplementedCloudService) Login(ctx context.Context, params map[string]string) error {
+	return errdefs.ErrNotImplemented
+}

+ 4 - 6
example/backend.go

@@ -26,14 +26,12 @@ func (a *apiService) ComposeService() compose.Service {
 	return &a.composeService
 }
 
-func (a *apiService) CloudService() cloud.Service {
-	return nil
+func init() {
+	backend.Register("example", "example", service, cloud.NotImplementedCloudService)
 }
 
-func init() {
-	backend.Register("example", "example", func(ctx context.Context) (backend.Service, error) {
-		return &apiService{}, nil
-	})
+func service(ctx context.Context) (backend.Service, error) {
+	return &apiService{}, nil
 }
 
 type containerService struct{}

+ 2 - 9
moby/backend.go

@@ -27,13 +27,10 @@ type mobyService struct {
 }
 
 func init() {
-	backend.Register("moby", "moby", func(ctx context.Context) (backend.Service, error) {
-		return New()
-	})
+	backend.Register("moby", "moby", service, cloud.NotImplementedCloudService)
 }
 
-// New returns a moby backend implementation
-func New() (backend.Service, error) {
+func service(ctx context.Context) (backend.Service, error) {
 	apiClient, err := client.NewClientWithOpts(client.FromEnv)
 	if err != nil {
 		return nil, err
@@ -52,10 +49,6 @@ func (ms *mobyService) ComposeService() compose.Service {
 	return nil
 }
 
-func (ms *mobyService) CloudService() cloud.Service {
-	return nil
-}
-
 func (ms *mobyService) List(ctx context.Context, all bool) ([]containers.Container, error) {
 	css, err := ms.apiClient.ContainerList(ctx, types.ContainerListOptions{
 		All: all,