mirror of https://github.com/docker/compose.git
CLI command to manage ECS volumes
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
75a5a0f205
commit
de96a0c1d0
|
@ -20,25 +20,27 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
|
|
||||||
"github.com/docker/compose-cli/aci"
|
"github.com/docker/compose-cli/aci"
|
||||||
"github.com/docker/compose-cli/api/client"
|
"github.com/docker/compose-cli/api/client"
|
||||||
"github.com/docker/compose-cli/cli/formatter"
|
"github.com/docker/compose-cli/cli/formatter"
|
||||||
|
"github.com/docker/compose-cli/context/store"
|
||||||
|
"github.com/docker/compose-cli/ecs"
|
||||||
formatter2 "github.com/docker/compose-cli/formatter"
|
formatter2 "github.com/docker/compose-cli/formatter"
|
||||||
"github.com/docker/compose-cli/progress"
|
"github.com/docker/compose-cli/progress"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ACICommand manage volumes
|
// Command manage volumes
|
||||||
func ACICommand() *cobra.Command {
|
func Command(ctype string) *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "volume",
|
Use: "volume",
|
||||||
Short: "Manages volumes",
|
Short: "Manages volumes",
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
createVolume(),
|
createVolume(ctype),
|
||||||
listVolume(),
|
listVolume(),
|
||||||
rmVolume(),
|
rmVolume(),
|
||||||
inspectVolume(),
|
inspectVolume(),
|
||||||
|
@ -46,11 +48,25 @@ func ACICommand() *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func createVolume() *cobra.Command {
|
func createVolume(ctype string) *cobra.Command {
|
||||||
aciOpts := aci.VolumeCreateOptions{}
|
var usage string
|
||||||
|
var short string
|
||||||
|
switch ctype {
|
||||||
|
case store.AciContextType:
|
||||||
|
usage = "create --storage-account ACCOUNT VOLUME"
|
||||||
|
short = "Creates an Azure file share to use as ACI volume."
|
||||||
|
case store.EcsContextType:
|
||||||
|
usage = "create [OPTIONS] VOLUME"
|
||||||
|
short = "Creates an EFS filesystem to use as AWS volume."
|
||||||
|
default:
|
||||||
|
usage = "create [OPTIONS] VOLUME"
|
||||||
|
short = "Creates a volume"
|
||||||
|
}
|
||||||
|
|
||||||
|
var opts interface{}
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "create --storage-account ACCOUNT VOLUME",
|
Use: usage,
|
||||||
Short: "Creates an Azure file share to use as ACI volume.",
|
Short: short,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
|
@ -59,7 +75,7 @@ func createVolume() *cobra.Command {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
result, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
|
result, err := progress.Run(ctx, func(ctx context.Context) (string, error) {
|
||||||
volume, err := c.VolumeService().Create(ctx, args[0], aciOpts)
|
volume, err := c.VolumeService().Create(ctx, args[0], opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -73,8 +89,20 @@ func createVolume() *cobra.Command {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch ctype {
|
||||||
|
case store.AciContextType:
|
||||||
|
aciOpts := aci.VolumeCreateOptions{}
|
||||||
cmd.Flags().StringVar(&aciOpts.Account, "storage-account", "", "Storage account name")
|
cmd.Flags().StringVar(&aciOpts.Account, "storage-account", "", "Storage account name")
|
||||||
_ = cmd.MarkFlagRequired("storage-account")
|
_ = cmd.MarkFlagRequired("storage-account")
|
||||||
|
opts = aciOpts
|
||||||
|
case store.EcsContextType:
|
||||||
|
ecsOpts := ecs.VolumeCreateOptions{}
|
||||||
|
cmd.Flags().StringVar(&ecsOpts.KmsKeyID, "kms-key", "", "ID of the AWS KMS CMK to be used to protect the encrypted file system")
|
||||||
|
cmd.Flags().StringVar(&ecsOpts.PerformanceMode, "performance-mode", "", "performance mode of the file system. (generalPurpose|maxIO)")
|
||||||
|
cmd.Flags().Float64Var(&ecsOpts.ProvisionedThroughputInMibps, "provisioned-throughput", 0, "throughput in MiB/s (1-1024)")
|
||||||
|
cmd.Flags().StringVar(&ecsOpts.ThroughputMode, "throughput-mode", "", "throughput mode (bursting|provisioned)")
|
||||||
|
opts = ecsOpts
|
||||||
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,13 +182,9 @@ func main() {
|
||||||
root.AddCommand(
|
root.AddCommand(
|
||||||
run.Command(ctype),
|
run.Command(ctype),
|
||||||
compose.Command(ctype),
|
compose.Command(ctype),
|
||||||
|
volume.Command(ctype),
|
||||||
)
|
)
|
||||||
|
|
||||||
if ctype == store.AciContextType {
|
|
||||||
// we can also pass ctype as a parameter to the volume command and customize subcommands, flags, etc. when we have other backend implementations
|
|
||||||
root.AddCommand(volume.ACICommand())
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = apicontext.WithCurrentContext(ctx, currentContext)
|
ctx = apicontext.WithCurrentContext(ctx, currentContext)
|
||||||
ctx = store.WithContextStore(ctx, s)
|
ctx = store.WithContextStore(ctx, s)
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ type API interface {
|
||||||
DeleteCapacityProvider(ctx context.Context, arn string) error
|
DeleteCapacityProvider(ctx context.Context, arn string) error
|
||||||
DeleteAutoscalingGroup(ctx context.Context, arn string) error
|
DeleteAutoscalingGroup(ctx context.Context, arn string) error
|
||||||
ResolveFileSystem(ctx context.Context, id string) (awsResource, error)
|
ResolveFileSystem(ctx context.Context, id string) (awsResource, error)
|
||||||
FindFileSystem(ctx context.Context, tags map[string]string) (awsResource, error)
|
ListFileSystems(ctx context.Context, tags map[string]string) ([]awsResource, error)
|
||||||
CreateFileSystem(ctx context.Context, tags map[string]string) (string, error)
|
CreateFileSystem(ctx context.Context, tags map[string]string, options VolumeCreateOptions) (awsResource, error)
|
||||||
DeleteFileSystem(ctx context.Context, id string) error
|
DeleteFileSystem(ctx context.Context, id string) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,12 +253,16 @@ func (b *ecsAPIService) parseExternalVolumes(ctx context.Context, project *types
|
||||||
compose.ProjectTag: project.Name,
|
compose.ProjectTag: project.Name,
|
||||||
compose.VolumeTag: name,
|
compose.VolumeTag: name,
|
||||||
}
|
}
|
||||||
fileSystem, err := b.aws.FindFileSystem(ctx, tags)
|
previous, err := b.aws.ListFileSystems(ctx, tags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if fileSystem != nil {
|
|
||||||
filesystems[name] = fileSystem
|
if len(previous) > 1 {
|
||||||
|
return nil, fmt.Errorf("multiple filesystems are tags as project=%q, volume=%q", project.Name, name)
|
||||||
|
}
|
||||||
|
if len(previous) == 1 {
|
||||||
|
filesystems[name] = previous[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return filesystems, nil
|
return filesystems, nil
|
||||||
|
|
|
@ -6,13 +6,12 @@ package ecs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
context "context"
|
context "context"
|
||||||
reflect "reflect"
|
|
||||||
|
|
||||||
cloudformation "github.com/aws/aws-sdk-go/service/cloudformation"
|
cloudformation "github.com/aws/aws-sdk-go/service/cloudformation"
|
||||||
ecs "github.com/aws/aws-sdk-go/service/ecs"
|
ecs "github.com/aws/aws-sdk-go/service/ecs"
|
||||||
compose "github.com/docker/compose-cli/api/compose"
|
compose "github.com/docker/compose-cli/api/compose"
|
||||||
secrets "github.com/docker/compose-cli/api/secrets"
|
secrets "github.com/docker/compose-cli/api/secrets"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
reflect "reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockAPI is a mock of API interface
|
// MockAPI is a mock of API interface
|
||||||
|
@ -97,18 +96,18 @@ func (mr *MockAPIMockRecorder) CreateCluster(arg0, arg1 interface{}) *gomock.Cal
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFileSystem mocks base method
|
// CreateFileSystem mocks base method
|
||||||
func (m *MockAPI) CreateFileSystem(arg0 context.Context, arg1 map[string]string) (string, error) {
|
func (m *MockAPI) CreateFileSystem(arg0 context.Context, arg1 map[string]string, arg2 VolumeCreateOptions) (awsResource, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CreateFileSystem", arg0, arg1)
|
ret := m.ctrl.Call(m, "CreateFileSystem", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].(string)
|
ret0, _ := ret[0].(awsResource)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateFileSystem indicates an expected call of CreateFileSystem
|
// CreateFileSystem indicates an expected call of CreateFileSystem
|
||||||
func (mr *MockAPIMockRecorder) CreateFileSystem(arg0, arg1 interface{}) *gomock.Call {
|
func (mr *MockAPIMockRecorder) CreateFileSystem(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFileSystem", reflect.TypeOf((*MockAPI)(nil).CreateFileSystem), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFileSystem", reflect.TypeOf((*MockAPI)(nil).CreateFileSystem), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateSecret mocks base method
|
// CreateSecret mocks base method
|
||||||
|
@ -240,21 +239,6 @@ func (mr *MockAPIMockRecorder) DescribeStackEvents(arg0, arg1 interface{}) *gomo
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DescribeStackEvents", reflect.TypeOf((*MockAPI)(nil).DescribeStackEvents), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DescribeStackEvents", reflect.TypeOf((*MockAPI)(nil).DescribeStackEvents), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindFileSystem mocks base method
|
|
||||||
func (m *MockAPI) FindFileSystem(arg0 context.Context, arg1 map[string]string) (awsResource, error) {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "FindFileSystem", arg0, arg1)
|
|
||||||
ret0, _ := ret[0].(awsResource)
|
|
||||||
ret1, _ := ret[1].(error)
|
|
||||||
return ret0, ret1
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindFileSystem indicates an expected call of FindFileSystem
|
|
||||||
func (mr *MockAPIMockRecorder) FindFileSystem(arg0, arg1 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindFileSystem", reflect.TypeOf((*MockAPI)(nil).FindFileSystem), arg0, arg1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDefaultVPC mocks base method
|
// GetDefaultVPC mocks base method
|
||||||
func (m *MockAPI) GetDefaultVPC(arg0 context.Context) (string, error) {
|
func (m *MockAPI) GetDefaultVPC(arg0 context.Context) (string, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@ -454,6 +438,21 @@ func (mr *MockAPIMockRecorder) InspectSecret(arg0, arg1 interface{}) *gomock.Cal
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InspectSecret", reflect.TypeOf((*MockAPI)(nil).InspectSecret), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InspectSecret", reflect.TypeOf((*MockAPI)(nil).InspectSecret), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListFileSystems mocks base method
|
||||||
|
func (m *MockAPI) ListFileSystems(arg0 context.Context, arg1 map[string]string) ([]awsResource, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ListFileSystems", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].([]awsResource)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListFileSystems indicates an expected call of ListFileSystems
|
||||||
|
func (mr *MockAPIMockRecorder) ListFileSystems(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListFileSystems", reflect.TypeOf((*MockAPI)(nil).ListFileSystems), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
// ListSecrets mocks base method
|
// ListSecrets mocks base method
|
||||||
func (m *MockAPI) ListSecrets(arg0 context.Context) ([]secrets.Secret, error) {
|
func (m *MockAPI) ListSecrets(arg0 context.Context) ([]secrets.Secret, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|
|
@ -98,7 +98,7 @@ func (b *ecsAPIService) SecretsService() secrets.Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ecsAPIService) VolumeService() volumes.Service {
|
func (b *ecsAPIService) VolumeService() volumes.Service {
|
||||||
return nil
|
return ecsVolumeService{backend: b}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *ecsAPIService) ResourceService() resources.Service {
|
func (b *ecsAPIService) ResourceService() resources.Service {
|
||||||
|
|
|
@ -390,7 +390,7 @@ volumes:
|
||||||
throughput_mode: provisioned
|
throughput_mode: provisioned
|
||||||
provisioned_throughput: 1024
|
provisioned_throughput: 1024
|
||||||
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
||||||
m.FindFileSystem(gomock.Any(), map[string]string{
|
m.ListFileSystems(gomock.Any(), map[string]string{
|
||||||
compose.ProjectTag: t.Name(),
|
compose.ProjectTag: t.Name(),
|
||||||
compose.VolumeTag: "db-data",
|
compose.VolumeTag: "db-data",
|
||||||
}).Return(nil, nil)
|
}).Return(nil, nil)
|
||||||
|
@ -420,7 +420,7 @@ volumes:
|
||||||
uid: 1002
|
uid: 1002
|
||||||
gid: 1002
|
gid: 1002
|
||||||
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
||||||
m.FindFileSystem(gomock.Any(), gomock.Any()).Return(nil, nil)
|
m.ListFileSystems(gomock.Any(), gomock.Any()).Return(nil, nil)
|
||||||
})
|
})
|
||||||
a := template.Resources["DbdataAccessPoint"].(*efs.AccessPoint)
|
a := template.Resources["DbdataAccessPoint"].(*efs.AccessPoint)
|
||||||
assert.Check(t, a != nil)
|
assert.Check(t, a != nil)
|
||||||
|
@ -436,10 +436,14 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
db-data: {}
|
db-data: {}
|
||||||
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
`, useDefaultVPC, func(m *MockAPIMockRecorder) {
|
||||||
m.FindFileSystem(gomock.Any(), map[string]string{
|
m.ListFileSystems(gomock.Any(), map[string]string{
|
||||||
compose.ProjectTag: t.Name(),
|
compose.ProjectTag: t.Name(),
|
||||||
compose.VolumeTag: "db-data",
|
compose.VolumeTag: "db-data",
|
||||||
}).Return(existingAWSResource{id: "fs-123abc"}, nil)
|
}).Return([]awsResource{
|
||||||
|
existingAWSResource{
|
||||||
|
id: "fs-123abc",
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
})
|
})
|
||||||
s := template.Resources["DbdataNFSMountTargetOnSubnet1"].(*efs.MountTarget)
|
s := template.Resources["DbdataNFSMountTargetOnSubnet1"].(*efs.MountTarget)
|
||||||
assert.Check(t, s != nil)
|
assert.Check(t, s != nil)
|
||||||
|
|
42
ecs/sdk.go
42
ecs/sdk.go
|
@ -904,7 +904,8 @@ func (s sdk) ResolveFileSystem(ctx context.Context, id string) (awsResource, err
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s sdk) FindFileSystem(ctx context.Context, tags map[string]string) (awsResource, error) {
|
func (s sdk) ListFileSystems(ctx context.Context, tags map[string]string) ([]awsResource, error) {
|
||||||
|
var results []awsResource
|
||||||
var token *string
|
var token *string
|
||||||
for {
|
for {
|
||||||
desc, err := s.EFS.DescribeFileSystemsWithContext(ctx, &efs.DescribeFileSystemsInput{
|
desc, err := s.EFS.DescribeFileSystemsWithContext(ctx, &efs.DescribeFileSystemsInput{
|
||||||
|
@ -915,14 +916,14 @@ func (s sdk) FindFileSystem(ctx context.Context, tags map[string]string) (awsRes
|
||||||
}
|
}
|
||||||
for _, filesystem := range desc.FileSystems {
|
for _, filesystem := range desc.FileSystems {
|
||||||
if containsAll(filesystem.Tags, tags) {
|
if containsAll(filesystem.Tags, tags) {
|
||||||
return existingAWSResource{
|
results = append(results, existingAWSResource{
|
||||||
arn: aws.StringValue(filesystem.FileSystemArn),
|
arn: aws.StringValue(filesystem.FileSystemArn),
|
||||||
id: aws.StringValue(filesystem.FileSystemId),
|
id: aws.StringValue(filesystem.FileSystemId),
|
||||||
}, nil
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if desc.NextMarker == token {
|
if desc.NextMarker == token {
|
||||||
return nil, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
token = desc.NextMarker
|
token = desc.NextMarker
|
||||||
}
|
}
|
||||||
|
@ -941,7 +942,7 @@ TAGS:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s sdk) CreateFileSystem(ctx context.Context, tags map[string]string) (string, error) {
|
func (s sdk) CreateFileSystem(ctx context.Context, tags map[string]string, options VolumeCreateOptions) (awsResource, error) {
|
||||||
var efsTags []*efs.Tag
|
var efsTags []*efs.Tag
|
||||||
for k, v := range tags {
|
for k, v := range tags {
|
||||||
efsTags = append(efsTags, &efs.Tag{
|
efsTags = append(efsTags, &efs.Tag{
|
||||||
|
@ -949,16 +950,39 @@ func (s sdk) CreateFileSystem(ctx context.Context, tags map[string]string) (stri
|
||||||
Value: aws.String(v),
|
Value: aws.String(v),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
|
k *string
|
||||||
|
p *string
|
||||||
|
f *float64
|
||||||
|
t *string
|
||||||
|
)
|
||||||
|
if options.ProvisionedThroughputInMibps > 1 {
|
||||||
|
f = aws.Float64(options.ProvisionedThroughputInMibps)
|
||||||
|
}
|
||||||
|
if options.KmsKeyID != "" {
|
||||||
|
k = aws.String(options.KmsKeyID)
|
||||||
|
}
|
||||||
|
if options.PerformanceMode != "" {
|
||||||
|
p = aws.String(options.PerformanceMode)
|
||||||
|
}
|
||||||
|
if options.ThroughputMode != "" {
|
||||||
|
t = aws.String(options.ThroughputMode)
|
||||||
|
}
|
||||||
res, err := s.EFS.CreateFileSystemWithContext(ctx, &efs.CreateFileSystemInput{
|
res, err := s.EFS.CreateFileSystemWithContext(ctx, &efs.CreateFileSystemInput{
|
||||||
Encrypted: aws.Bool(true),
|
Encrypted: aws.Bool(true),
|
||||||
|
KmsKeyId: k,
|
||||||
|
PerformanceMode: p,
|
||||||
|
ProvisionedThroughputInMibps: f,
|
||||||
|
ThroughputMode: t,
|
||||||
Tags: efsTags,
|
Tags: efsTags,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
id := aws.StringValue(res.FileSystemId)
|
return existingAWSResource{
|
||||||
logrus.Debugf("Created file system %q", id)
|
id: aws.StringValue(res.FileSystemId),
|
||||||
return id, nil
|
arn: aws.StringValue(res.FileSystemArn),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s sdk) DeleteFileSystem(ctx context.Context, id string) error {
|
func (s sdk) DeleteFileSystem(ctx context.Context, id string) error {
|
||||||
|
|
|
@ -17,13 +17,17 @@
|
||||||
package ecs
|
package ecs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/docker/compose-cli/api/compose"
|
"github.com/docker/compose-cli/api/compose"
|
||||||
|
"github.com/docker/compose-cli/api/volumes"
|
||||||
|
"github.com/docker/compose-cli/errdefs"
|
||||||
|
|
||||||
"github.com/awslabs/goformation/v4/cloudformation"
|
"github.com/awslabs/goformation/v4/cloudformation"
|
||||||
"github.com/awslabs/goformation/v4/cloudformation/efs"
|
"github.com/awslabs/goformation/v4/cloudformation/efs"
|
||||||
"github.com/compose-spec/compose-go/types"
|
"github.com/compose-spec/compose-go/types"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *ecsAPIService) createNFSMountTarget(project *types.Project, resources awsResources, template *cloudformation.Template) {
|
func (b *ecsAPIService) createNFSMountTarget(project *types.Project, resources awsResources, template *cloudformation.Template) {
|
||||||
|
@ -97,3 +101,56 @@ func (b *ecsAPIService) createAccessPoints(project *types.Project, r awsResource
|
||||||
template.Resources[n] = &ap
|
template.Resources[n] = &ap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VolumeCreateOptions hold EFS filesystem creation options
|
||||||
|
type VolumeCreateOptions struct {
|
||||||
|
KmsKeyID string
|
||||||
|
PerformanceMode string
|
||||||
|
ProvisionedThroughputInMibps float64
|
||||||
|
ThroughputMode string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ecsVolumeService struct {
|
||||||
|
backend *ecsAPIService
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ecsVolumeService) List(ctx context.Context) ([]volumes.Volume, error) {
|
||||||
|
filesystems, err := e.backend.aws.ListFileSystems(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var vol []volumes.Volume
|
||||||
|
for _, fs := range filesystems {
|
||||||
|
vol = append(vol, volumes.Volume{
|
||||||
|
ID: fs.ID(),
|
||||||
|
Description: fs.ARN(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return vol, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ecsVolumeService) Create(ctx context.Context, name string, options interface{}) (volumes.Volume, error) {
|
||||||
|
fs, err := e.backend.aws.CreateFileSystem(ctx, map[string]string{
|
||||||
|
"Name": name,
|
||||||
|
}, options.(VolumeCreateOptions))
|
||||||
|
return volumes.Volume{
|
||||||
|
ID: fs.ID(),
|
||||||
|
Description: fs.ARN(),
|
||||||
|
}, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ecsVolumeService) Delete(ctx context.Context, volumeID string, options interface{}) error {
|
||||||
|
return e.backend.aws.DeleteFileSystem(ctx, volumeID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e ecsVolumeService) Inspect(ctx context.Context, volumeID string) (volumes.Volume, error) {
|
||||||
|
ok, err := e.backend.aws.ResolveFileSystem(ctx, volumeID)
|
||||||
|
if ok == nil {
|
||||||
|
err = errors.Wrapf(errdefs.ErrNotFound, "filesystem %q does not exists", volumeID)
|
||||||
|
}
|
||||||
|
return volumes.Volume{
|
||||||
|
ID: volumeID,
|
||||||
|
Description: ok.ARN(),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue