mirror of
https://github.com/docker/compose.git
synced 2025-07-22 13:14:29 +02:00
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
This commit is contained in:
parent
832651b1dc
commit
01aaec2dbe
@ -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{
|
|
||||||
ctx: aciCtx,
|
|
||||||
},
|
|
||||||
aciComposeService: aciComposeService{
|
|
||||||
ctx: aciCtx,
|
|
||||||
},
|
|
||||||
aciCloudService: aciCloudService{
|
|
||||||
loginService: service,
|
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 {
|
||||||
|
@ -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))
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
@ -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)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
|
||||||
}
|
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
@ -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{}
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user