зеркало из https://github.com/docker/compose-cli.git
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:
Родитель
832651b1dc
Коммит
01aaec2dbe
|
@ -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 {
|
||||
|
|
|
@ -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,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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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{}
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче