mirror of https://github.com/docker/compose.git
Connecting it all
Signed-off-by: Guillaume Tardif <guillaume.tardif@docker.com>
This commit is contained in:
parent
9ed06ece5b
commit
08562b403e
|
@ -35,8 +35,8 @@ import (
|
|||
"github.com/docker/compose-cli/aci/login"
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/containers"
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
"github.com/docker/compose-cli/api/secrets"
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
"github.com/docker/compose-cli/backend"
|
||||
apicontext "github.com/docker/compose-cli/context"
|
||||
"github.com/docker/compose-cli/context/cloud"
|
||||
|
@ -110,6 +110,9 @@ func getAciAPIService(aciCtx store.AciContext) *aciAPIService {
|
|||
aciComposeService: &aciComposeService{
|
||||
ctx: aciCtx,
|
||||
},
|
||||
aciVolumeService: &aciVolumeService{
|
||||
ctx: aciCtx,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,20 +172,20 @@ func getContainerGroups(ctx context.Context, subscriptionID string, resourceGrou
|
|||
var containerGroups []containerinstance.ContainerGroup
|
||||
result, err := groupsClient.ListByResourceGroup(ctx, resourceGroup)
|
||||
if err != nil {
|
||||
return []containerinstance.ContainerGroup{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for result.NotDone() {
|
||||
containerGroups = append(containerGroups, result.Values()...)
|
||||
if err := result.NextWithContext(ctx); err != nil {
|
||||
return []containerinstance.ContainerGroup{}, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var groups []containerinstance.ContainerGroup
|
||||
for _, group := range containerGroups {
|
||||
group, err := groupsClient.Get(ctx, resourceGroup, *group.Name)
|
||||
if err != nil {
|
||||
return []containerinstance.ContainerGroup{}, err
|
||||
return nil, err
|
||||
}
|
||||
groups = append(groups, group)
|
||||
}
|
||||
|
@ -507,11 +510,23 @@ type aciVolumeService struct {
|
|||
}
|
||||
|
||||
func (cs *aciVolumeService) List(ctx context.Context) ([]volumes.Volume, error) {
|
||||
return nil, nil
|
||||
storageHelper := login.StorageAccountHelper{AciContext: cs.ctx}
|
||||
return storageHelper.ListFileShare(ctx)
|
||||
}
|
||||
|
||||
//VolumeCreateOptions options to create a new ACI volume
|
||||
type VolumeCreateOptions struct {
|
||||
Account string
|
||||
Fileshare string
|
||||
}
|
||||
|
||||
func (cs *aciVolumeService) Create(ctx context.Context, options interface{}) (volumes.Volume, error) {
|
||||
return volumes.Volume{}, nil
|
||||
opts, ok := options.(VolumeCreateOptions)
|
||||
if !ok {
|
||||
return volumes.Volume{}, errors.New("Could not read azure LoginParams struct from generic parameter")
|
||||
}
|
||||
storageHelper := login.StorageAccountHelper{AciContext: cs.ctx}
|
||||
return storageHelper.CreateFileShare(ctx, opts.Account, opts.Fileshare)
|
||||
}
|
||||
|
||||
type aciCloudService struct {
|
||||
|
|
|
@ -56,13 +56,8 @@ const (
|
|||
func ToContainerGroup(ctx context.Context, aciContext store.AciContext, p types.Project) (containerinstance.ContainerGroup, error) {
|
||||
project := projectAciHelper(p)
|
||||
containerGroupName := strings.ToLower(project.Name)
|
||||
loginService, err := login.NewAzureLoginService()
|
||||
if err != nil {
|
||||
return containerinstance.ContainerGroup{}, err
|
||||
}
|
||||
storageHelper := login.StorageAccountHelper{
|
||||
LoginService: *loginService,
|
||||
AciContext: aciContext,
|
||||
AciContext: aciContext,
|
||||
}
|
||||
volumesCache, volumesSlice, err := project.getAciFileVolumes(ctx, storageHelper)
|
||||
if err != nil {
|
||||
|
|
|
@ -67,7 +67,7 @@ func NewStorageAccountsClient(subscriptionID string) (storage.AccountsClient, er
|
|||
return containerGroupsClient, nil
|
||||
}
|
||||
|
||||
// NewStorageAccountsClient get client to manipulate storage accounts
|
||||
// NewFileShareClient get client to manipulate file shares
|
||||
func NewFileShareClient(subscriptionID string) (storage.FileSharesClient, error) {
|
||||
containerGroupsClient := storage.NewFileSharesClient(subscriptionID)
|
||||
err := setupClient(&containerGroupsClient.Client)
|
||||
|
@ -80,7 +80,6 @@ func NewFileShareClient(subscriptionID string) (storage.FileSharesClient, error)
|
|||
return containerGroupsClient, nil
|
||||
}
|
||||
|
||||
|
||||
// NewSubscriptionsClient get subscription client
|
||||
func NewSubscriptionsClient() (subscription.SubscriptionsClient, error) {
|
||||
subc := subscription.NewSubscriptionsClient()
|
||||
|
|
|
@ -19,8 +19,12 @@ package login
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage"
|
||||
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
"github.com/docker/compose-cli/errdefs"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/docker/compose-cli/context/store"
|
||||
|
@ -28,8 +32,7 @@ import (
|
|||
|
||||
// StorageAccountHelper helper for Azure Storage Account
|
||||
type StorageAccountHelper struct {
|
||||
LoginService AzureLoginService
|
||||
AciContext store.AciContext
|
||||
AciContext store.AciContext
|
||||
}
|
||||
|
||||
// GetAzureStorageAccountKey retrieves the storage account ket from the current azure login
|
||||
|
@ -50,61 +53,99 @@ func (helper StorageAccountHelper) GetAzureStorageAccountKey(ctx context.Context
|
|||
return *key.Value, nil
|
||||
}
|
||||
|
||||
func (helper StorageAccountHelper) ListFileShare(ctx context.Context) ([]string, error) {
|
||||
// ListFileShare list file shares in all visible storage accounts
|
||||
func (helper StorageAccountHelper) ListFileShare(ctx context.Context) ([]volumes.Volume, error) {
|
||||
aciContext := helper.AciContext
|
||||
accountClient, err := NewStorageAccountsClient(aciContext.SubscriptionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := accountClient.ListByResourceGroup(ctx, aciContext.ResourceGroup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accounts := result.Value
|
||||
fileShareClient, err := NewFileShareClient(aciContext.SubscriptionID)
|
||||
fileShares := []string{}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileShares := []volumes.Volume{}
|
||||
for _, account := range *accounts {
|
||||
fileSharePage, err := fileShareClient.List(ctx, aciContext.ResourceGroup, *account.Name, "", "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for ; fileSharePage.NotDone() ; fileSharePage.NextWithContext(ctx) {
|
||||
|
||||
for fileSharePage.NotDone() {
|
||||
values := fileSharePage.Values()
|
||||
for _, fileShare := range values {
|
||||
fileShares = append(fileShares, *fileShare.Name)
|
||||
fileShares = append(fileShares, toVolume(account, *fileShare.Name))
|
||||
}
|
||||
if err := fileSharePage.NextWithContext(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileShares, nil
|
||||
}
|
||||
|
||||
func (helper StorageAccountHelper) CreateFileShare(ctx context.Context, accountName string, fileShareName string) (storage.FileShare, error) {
|
||||
func toVolume(account storage.Account, fileShareName string) volumes.Volume {
|
||||
return volumes.Volume{
|
||||
ID: fmt.Sprintf("%s@%s", *account.Name, fileShareName),
|
||||
Name: fileShareName,
|
||||
Description: fmt.Sprintf("Fileshare %s in %s storage account", fileShareName, *account.Name),
|
||||
}
|
||||
}
|
||||
|
||||
// CreateFileShare create a new fileshare
|
||||
func (helper StorageAccountHelper) CreateFileShare(ctx context.Context, accountName string, fileShareName string) (volumes.Volume, error) {
|
||||
aciContext := helper.AciContext
|
||||
accountClient, err := NewStorageAccountsClient(aciContext.SubscriptionID)
|
||||
if err != nil {
|
||||
return storage.FileShare{}, err
|
||||
return volumes.Volume{}, err
|
||||
}
|
||||
account, err := accountClient.GetProperties(ctx, aciContext.ResourceGroup, accountName, "")
|
||||
if err != nil {
|
||||
//TODO check err not found
|
||||
parameters := storage.AccountCreateParameters{
|
||||
Location: &aciContext.Location,
|
||||
Sku:&storage.Sku{
|
||||
Name: storage.StandardLRS,
|
||||
Tier: storage.Standard,
|
||||
},
|
||||
if account.StatusCode != 404 {
|
||||
return volumes.Volume{}, err
|
||||
}
|
||||
//TODO confirm storage account creation
|
||||
parameters := defaultStorageAccountParams(aciContext)
|
||||
// TODO progress account creation
|
||||
future, err := accountClient.Create(ctx, aciContext.ResourceGroup, accountName, parameters)
|
||||
if err != nil {
|
||||
return storage.FileShare{}, err
|
||||
return volumes.Volume{}, err
|
||||
}
|
||||
account, err = future.Result(accountClient)
|
||||
if err != nil {
|
||||
return volumes.Volume{}, err
|
||||
}
|
||||
}
|
||||
fileShareClient, err := NewFileShareClient(aciContext.SubscriptionID)
|
||||
fileShare, err := fileShareClient.Get(ctx, aciContext.ResourceGroup, *account.Name, fileShareName, "")
|
||||
if err != nil {
|
||||
// TODO check err not found
|
||||
fileShare, err = fileShareClient.Create(ctx, aciContext.ResourceGroup, *account.Name, fileShareName, storage.FileShare{})
|
||||
return volumes.Volume{}, err
|
||||
}
|
||||
|
||||
return fileShare, nil
|
||||
fileShare, err := fileShareClient.Get(ctx, aciContext.ResourceGroup, *account.Name, fileShareName, "")
|
||||
if err == nil {
|
||||
return volumes.Volume{}, errors.Wrapf(errdefs.ErrAlreadyExists, "Azure fileshare %q already exists", fileShareName)
|
||||
}
|
||||
if fileShare.StatusCode != 404 {
|
||||
return volumes.Volume{}, err
|
||||
}
|
||||
fileShare, err = fileShareClient.Create(ctx, aciContext.ResourceGroup, *account.Name, fileShareName, storage.FileShare{})
|
||||
if err != nil {
|
||||
return volumes.Volume{}, err
|
||||
}
|
||||
return toVolume(account, *fileShare.Name), nil
|
||||
}
|
||||
|
||||
func defaultStorageAccountParams(aciContext store.AciContext) storage.AccountCreateParameters {
|
||||
return storage.AccountCreateParameters{
|
||||
Location: &aciContext.Location,
|
||||
Sku: &storage.Sku{
|
||||
Name: storage.StandardLRS,
|
||||
Tier: storage.Standard,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package client
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
|
@ -87,6 +88,7 @@ func (c *Client) SecretsService() secrets.Service {
|
|||
|
||||
return &secretsService{}
|
||||
}
|
||||
|
||||
// VolumeService returns the backend service for the current context
|
||||
func (c *Client) VolumeService() volumes.Service {
|
||||
if vs := c.bs.VolumeService(); vs != nil {
|
||||
|
|
|
@ -18,6 +18,7 @@ package client
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
"github.com/docker/compose-cli/errdefs"
|
||||
)
|
||||
|
@ -31,6 +32,6 @@ func (c *volumeService) List(ctx context.Context) ([]volumes.Volume, error) {
|
|||
}
|
||||
|
||||
// Create creates a volume
|
||||
func (c *volumeService) Create(ctx context.Context, options interface {}) (volumes.Volume, error) {
|
||||
func (c *volumeService) Create(ctx context.Context, options interface{}) (volumes.Volume, error) {
|
||||
return volumes.Volume{}, errdefs.ErrNotImplemented
|
||||
}
|
||||
|
|
|
@ -20,13 +20,11 @@ import (
|
|||
"context"
|
||||
)
|
||||
|
||||
// Volume volume info
|
||||
type Volume struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
type VolumeCreateOptions struct {
|
||||
account string
|
||||
fileshare string
|
||||
ID string
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
// Service interacts with the underlying container backend
|
||||
|
|
|
@ -18,17 +18,21 @@ package volume
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/docker/compose-cli/aci"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose-cli/api/client"
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
)
|
||||
|
||||
type createVolumeOptions struct {
|
||||
Account string
|
||||
Fileshare string
|
||||
}
|
||||
|
||||
// SecretCommand manage secrets
|
||||
func VolumeCommand() *cobra.Command {
|
||||
// Command manage volumes
|
||||
func Command() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "volume",
|
||||
Short: "Manages volumes",
|
||||
|
@ -36,16 +40,17 @@ func VolumeCommand() *cobra.Command {
|
|||
|
||||
cmd.AddCommand(
|
||||
createVolume(),
|
||||
listVolume(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func createVolume() *cobra.Command {
|
||||
opts := createVolumeOptions{}
|
||||
opts := aci.VolumeCreateOptions{}
|
||||
cmd := &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Creates an Azure file share to use as ACI volume.",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Args: cobra.ExactArgs(0),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c, err := client.New(cmd.Context())
|
||||
if err != nil {
|
||||
|
@ -60,7 +65,43 @@ func createVolume() *cobra.Command {
|
|||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&opts.Account, "storage-account", "", "Storage account name")
|
||||
cmd.Flags().StringVar(&opts.Account, "storage-account", "", "Storage account name")
|
||||
cmd.Flags().StringVar(&opts.Fileshare, "fileshare", "", "Fileshare name")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func listVolume() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "ls",
|
||||
Short: "list Azure file shares usable as ACI volumes.",
|
||||
Args: cobra.ExactArgs(0),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
c, err := client.New(cmd.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vols, err := c.VolumeService().List(cmd.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(os.Stdout, vols)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func printList(out io.Writer, volumes []volumes.Volume) {
|
||||
printSection(out, func(w io.Writer) {
|
||||
for _, vol := range volumes {
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\n", vol.ID, vol.Name, vol.Description) // nolint:errcheck
|
||||
}
|
||||
}, "ID", "NAME", "DESCRIPTION")
|
||||
}
|
||||
|
||||
func printSection(out io.Writer, printer func(io.Writer), headers ...string) {
|
||||
w := tabwriter.NewWriter(out, 20, 1, 3, ' ', 0)
|
||||
fmt.Fprintln(w, strings.Join(headers, "\t")) // nolint:errcheck
|
||||
printer(w)
|
||||
w.Flush() // nolint:errcheck
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ package main
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
volume "github.com/docker/compose-cli/cli/cmd/volume"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -28,6 +27,8 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
volume "github.com/docker/compose-cli/cli/cmd/volume"
|
||||
|
||||
"github.com/docker/compose-cli/cli/cmd/compose"
|
||||
|
||||
"github.com/docker/compose-cli/cli/cmd/logout"
|
||||
|
@ -134,7 +135,7 @@ func main() {
|
|||
|
||||
// Place holders
|
||||
cmd.EcsCommand(),
|
||||
volume.VolumeCommand(),
|
||||
volume.Command(),
|
||||
)
|
||||
|
||||
helpFunc := root.HelpFunc()
|
||||
|
|
|
@ -18,6 +18,7 @@ package ecs
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
|
|
|
@ -18,12 +18,14 @@ package local
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/containers"
|
||||
"github.com/docker/compose-cli/api/secrets"
|
||||
"github.com/docker/docker/client"
|
||||
|
||||
"github.com/docker/compose-cli/backend"
|
||||
"github.com/docker/compose-cli/context/cloud"
|
||||
|
|
|
@ -38,8 +38,8 @@ import (
|
|||
|
||||
"github.com/docker/compose-cli/api/compose"
|
||||
"github.com/docker/compose-cli/api/containers"
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
"github.com/docker/compose-cli/api/secrets"
|
||||
"github.com/docker/compose-cli/api/volumes"
|
||||
"github.com/docker/compose-cli/backend"
|
||||
"github.com/docker/compose-cli/context/cloud"
|
||||
"github.com/docker/compose-cli/errdefs"
|
||||
|
|
|
@ -21,8 +21,9 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
. "github.com/docker/compose-cli/tests/framework"
|
||||
"gotest.tools/v3/icmd"
|
||||
|
||||
. "github.com/docker/compose-cli/tests/framework"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
Loading…
Reference in New Issue