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")
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 &aciAPIService{
aciContainerService: aciContainerService{
ctx: aciCtx,
},
aciComposeService: aciComposeService{
ctx: aciCtx,
},
aciCloudService: aciCloudService{
loginService: service,
},
return &aciCloudService{
loginService: service,
}, nil
}
func getAciAPIService(aciCtx store.AciContext) *aciAPIService {
return &aciAPIService{
aciContainerService: &aciContainerService{
ctx: aciCtx,
},
aciComposeService: &aciComposeService{
ctx: aciCtx,
},
}
}
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 {

View File

@ -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))
}

View File

@ -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)
}

View File

@ -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)
},
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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{}

View File

@ -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,