Merge pull request #159 from docker/fix_azure_login

Fix Azure login : no need for ACI context first
This commit is contained in:
Djordje Lukic 2020-05-29 06:23:27 -07:00 committed by GitHub
commit 6830724ab9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 84 additions and 62 deletions

View File

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

View File

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

View File

@ -19,11 +19,13 @@ var (
) )
type initFunc func(context.Context) (Service, error) type initFunc func(context.Context) (Service, error)
type getCloudServiceFunc func() (cloud.Service, error)
type registeredBackend struct { type registeredBackend struct {
name string name string
backendType string backendType string
init initFunc init initFunc
getCloudService getCloudServiceFunc
} }
var backends = struct { var backends = struct {
@ -34,11 +36,10 @@ var backends = struct {
type Service interface { type Service interface {
ContainerService() containers.Service ContainerService() containers.Service
ComposeService() compose.Service ComposeService() compose.Service
CloudService() cloud.Service
} }
// Register adds a typed backend to the registry // 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 == "" { if name == "" {
logrus.Fatal(errNoName) logrus.Fatal(errNoName)
} }
@ -55,6 +56,7 @@ func Register(name string, backendType string, init initFunc) {
name, name,
backendType, backendType,
init, 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) 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)
}

View File

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

View File

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

View File

@ -1,9 +1,25 @@
package cloud package cloud
import "context" import (
"context"
"github.com/docker/api/errdefs"
)
// Service cloud specific services // Service cloud specific services
type Service interface { type Service interface {
// Login login to cloud provider // Login login to cloud provider
Login(ctx context.Context, params map[string]string) error 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
}

View File

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

View File

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