mirror of
https://github.com/docker/compose.git
synced 2025-07-23 21:54:40 +02:00
Add compose ls
command for ECS
Signed-off-by: aiordache <anca.iordache@docker.com>
This commit is contained in:
parent
a0a0e391cb
commit
02be463fd7
@ -438,6 +438,9 @@ func (cs *aciComposeService) Ps(ctx context.Context, project string) ([]compose.
|
|||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
func (cs *aciComposeService) List(ctx context.Context, project string) ([]compose.Stack, error) {
|
||||||
|
return nil, errdefs.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
func (cs *aciComposeService) Logs(ctx context.Context, project string, w io.Writer) error {
|
func (cs *aciComposeService) Logs(ctx context.Context, project string, w io.Writer) error {
|
||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
|
@ -73,6 +73,7 @@ func Command() *cobra.Command {
|
|||||||
upCommand(),
|
upCommand(),
|
||||||
downCommand(),
|
downCommand(),
|
||||||
psCommand(),
|
psCommand(),
|
||||||
|
listCommand(),
|
||||||
logsCommand(),
|
logsCommand(),
|
||||||
convertCommand(),
|
convertCommand(),
|
||||||
)
|
)
|
||||||
|
58
cli/cmd/compose/list.go
Normal file
58
cli/cmd/compose/list.go
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compose
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/docker/compose-cli/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
func listCommand() *cobra.Command {
|
||||||
|
opts := composeOptions{}
|
||||||
|
lsCmd := &cobra.Command{
|
||||||
|
Use: "ls",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return runList(cmd.Context(), opts)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
lsCmd.Flags().StringVarP(&opts.Name, "project-name", "p", "", "Project name")
|
||||||
|
return lsCmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func runList(ctx context.Context, opts composeOptions) error {
|
||||||
|
c, err := client.New(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
stackList, err := c.ComposeService().List(ctx, opts.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = printSection(os.Stdout, func(w io.Writer) {
|
||||||
|
for _, stack := range stackList {
|
||||||
|
fmt.Fprintf(w, "%s\t%s\n", stack.Name, stack.Status)
|
||||||
|
}
|
||||||
|
}, "NAME", "STATUS")
|
||||||
|
return err
|
||||||
|
}
|
@ -49,6 +49,11 @@ func (c *composeService) Ps(context.Context, string) ([]compose.ServiceStatus, e
|
|||||||
return nil, errdefs.ErrNotImplemented
|
return nil, errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// List executes the equivalent to a `docker stack ls`
|
||||||
|
func (c *composeService) List(context.Context, string) ([]compose.Stack, error) {
|
||||||
|
return nil, errdefs.ErrNotImplemented
|
||||||
|
}
|
||||||
|
|
||||||
// Convert translate compose model into backend's native format
|
// Convert translate compose model into backend's native format
|
||||||
func (c *composeService) Convert(context.Context, *types.Project) ([]byte, error) {
|
func (c *composeService) Convert(context.Context, *types.Project) ([]byte, error) {
|
||||||
return nil, errdefs.ErrNotImplemented
|
return nil, errdefs.ErrNotImplemented
|
||||||
|
@ -33,6 +33,8 @@ type Service interface {
|
|||||||
Logs(ctx context.Context, projectName string, w io.Writer) error
|
Logs(ctx context.Context, projectName string, w io.Writer) error
|
||||||
// Ps executes the equivalent to a `compose ps`
|
// Ps executes the equivalent to a `compose ps`
|
||||||
Ps(ctx context.Context, projectName string) ([]ServiceStatus, error)
|
Ps(ctx context.Context, projectName string) ([]ServiceStatus, error)
|
||||||
|
// List executes the equivalent to a `docker stack ls`
|
||||||
|
List(ctx context.Context, projectName string) ([]Stack, error)
|
||||||
// Convert translate compose model into backend's native format
|
// Convert translate compose model into backend's native format
|
||||||
Convert(ctx context.Context, project *types.Project) ([]byte, error)
|
Convert(ctx context.Context, project *types.Project) ([]byte, error)
|
||||||
}
|
}
|
||||||
@ -54,3 +56,22 @@ type ServiceStatus struct {
|
|||||||
Ports []string
|
Ports []string
|
||||||
Publishers []PortPublisher
|
Publishers []PortPublisher
|
||||||
}
|
}
|
||||||
|
type State string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Starting indicates that stack is being deployed
|
||||||
|
STARTING State = "starting"
|
||||||
|
// Runnning indicates that stack is deployed and services are running
|
||||||
|
RUNNING State = "running"
|
||||||
|
// Updating indicates that some stack resources are being recreated
|
||||||
|
UPDATING State = "updating"
|
||||||
|
// Removing indicates that stack is being deleted
|
||||||
|
REMOVING State = "removing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StackStatus hold status about a compose application/stack
|
||||||
|
type Stack struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Status State
|
||||||
|
}
|
||||||
|
46
ecs/list.go
46
ecs/list.go
@ -18,53 +18,11 @@ package ecs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/docker/compose-cli/compose"
|
"github.com/docker/compose-cli/compose"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *ecsAPIService) Ps(ctx context.Context, project string) ([]compose.ServiceStatus, error) {
|
func (b *ecsAPIService) List(ctx context.Context, project string) ([]compose.Stack, error) {
|
||||||
parameters, err := b.SDK.ListStackParameters(ctx, project)
|
return b.SDK.ListStacks(ctx, project)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cluster := parameters[parameterClusterName]
|
|
||||||
|
|
||||||
resources, err := b.SDK.ListStackResources(ctx, project)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
servicesARN := []string{}
|
|
||||||
for _, r := range resources {
|
|
||||||
switch r.Type {
|
|
||||||
case "AWS::ECS::Service":
|
|
||||||
servicesARN = append(servicesARN, r.ARN)
|
|
||||||
case "AWS::ECS::Cluster":
|
|
||||||
cluster = r.ARN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(servicesARN) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
status, err := b.SDK.DescribeServices(ctx, cluster, servicesARN)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, state := range status {
|
|
||||||
ports := []string{}
|
|
||||||
for _, lb := range state.Publishers {
|
|
||||||
ports = append(ports, fmt.Sprintf(
|
|
||||||
"%s:%d->%d/%s",
|
|
||||||
lb.URL,
|
|
||||||
lb.PublishedPort,
|
|
||||||
lb.TargetPort,
|
|
||||||
strings.ToLower(lb.Protocol)))
|
|
||||||
}
|
|
||||||
state.Ports = ports
|
|
||||||
status[i] = state
|
|
||||||
}
|
|
||||||
return status, nil
|
|
||||||
}
|
}
|
||||||
|
@ -177,3 +177,6 @@ func (e ecsLocalSimulation) Logs(ctx context.Context, projectName string, w io.W
|
|||||||
func (e ecsLocalSimulation) Ps(ctx context.Context, projectName string) ([]compose.ServiceStatus, error) {
|
func (e ecsLocalSimulation) Ps(ctx context.Context, projectName string) ([]compose.ServiceStatus, error) {
|
||||||
return nil, errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose ps")
|
return nil, errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose ps")
|
||||||
}
|
}
|
||||||
|
func (e ecsLocalSimulation) List(ctx context.Context, projectName string) ([]compose.Stack, error) {
|
||||||
|
return nil, errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose ls")
|
||||||
|
}
|
||||||
|
70
ecs/ps.go
Normal file
70
ecs/ps.go
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2020 Docker, Inc.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package ecs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/compose-cli/compose"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (b *ecsAPIService) Ps(ctx context.Context, project string) ([]compose.ServiceStatus, error) {
|
||||||
|
parameters, err := b.SDK.ListStackParameters(ctx, project)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cluster := parameters[parameterClusterName]
|
||||||
|
|
||||||
|
resources, err := b.SDK.ListStackResources(ctx, project)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
servicesARN := []string{}
|
||||||
|
for _, r := range resources {
|
||||||
|
switch r.Type {
|
||||||
|
case "AWS::ECS::Service":
|
||||||
|
servicesARN = append(servicesARN, r.ARN)
|
||||||
|
case "AWS::ECS::Cluster":
|
||||||
|
cluster = r.ARN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(servicesARN) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
status, err := b.SDK.DescribeServices(ctx, cluster, servicesARN)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, state := range status {
|
||||||
|
ports := []string{}
|
||||||
|
for _, lb := range state.Publishers {
|
||||||
|
ports = append(ports, fmt.Sprintf(
|
||||||
|
"%s:%d->%d/%s",
|
||||||
|
lb.URL,
|
||||||
|
lb.PublishedPort,
|
||||||
|
lb.TargetPort,
|
||||||
|
strings.ToLower(lb.Protocol)))
|
||||||
|
}
|
||||||
|
state.Ports = ports
|
||||||
|
status[i] = state
|
||||||
|
}
|
||||||
|
return status, nil
|
||||||
|
}
|
36
ecs/sdk.go
36
ecs/sdk.go
@ -208,6 +208,12 @@ func (s sdk) CreateStack(ctx context.Context, name string, template *cf.Template
|
|||||||
Capabilities: []*string{
|
Capabilities: []*string{
|
||||||
aws.String(cloudformation.CapabilityCapabilityIam),
|
aws.String(cloudformation.CapabilityCapabilityIam),
|
||||||
},
|
},
|
||||||
|
Tags: []*cloudformation.Tag{
|
||||||
|
{
|
||||||
|
Key: aws.String(compose.ProjectTag),
|
||||||
|
Value: aws.String(name),
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -296,6 +302,36 @@ func (s sdk) GetStackID(ctx context.Context, name string) (string, error) {
|
|||||||
return *stacks.Stacks[0].StackId, nil
|
return *stacks.Stacks[0].StackId, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s sdk) ListStacks(ctx context.Context, name string) ([]compose.Stack, error) {
|
||||||
|
cfStacks, err := s.CF.DescribeStacksWithContext(ctx, &cloudformation.DescribeStacksInput{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
stacks := []compose.Stack{}
|
||||||
|
for _, stack := range cfStacks.Stacks {
|
||||||
|
for _, t := range stack.Tags {
|
||||||
|
if *t.Key == compose.ProjectTag {
|
||||||
|
status := compose.RUNNING
|
||||||
|
switch aws.StringValue(stack.StackStatus) {
|
||||||
|
case "CREATE_IN_PROGRESS":
|
||||||
|
status = compose.STARTING
|
||||||
|
case "DELETE_IN_PROGRESS":
|
||||||
|
status = compose.REMOVING
|
||||||
|
case "UPDATE_IN_PROGRESS":
|
||||||
|
status = compose.UPDATING
|
||||||
|
}
|
||||||
|
stacks = append(stacks, compose.Stack{
|
||||||
|
ID: aws.StringValue(stack.StackId),
|
||||||
|
Name: aws.StringValue(stack.StackName),
|
||||||
|
Status: status,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stacks, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s sdk) DescribeStackEvents(ctx context.Context, stackID string) ([]*cloudformation.StackEvent, error) {
|
func (s sdk) DescribeStackEvents(ctx context.Context, stackID string) ([]*cloudformation.StackEvent, error) {
|
||||||
// Fixme implement Paginator on Events and return as a chan(events)
|
// Fixme implement Paginator on Events and return as a chan(events)
|
||||||
events := []*cloudformation.StackEvent{}
|
events := []*cloudformation.StackEvent{}
|
||||||
|
@ -135,7 +135,9 @@ func (cs *composeService) Down(ctx context.Context, project string) error {
|
|||||||
func (cs *composeService) Ps(ctx context.Context, project string) ([]compose.ServiceStatus, error) {
|
func (cs *composeService) Ps(ctx context.Context, project string) ([]compose.ServiceStatus, error) {
|
||||||
return nil, errdefs.ErrNotImplemented
|
return nil, errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
func (cs *composeService) List(ctx context.Context, project string) ([]compose.Stack, error) {
|
||||||
|
return nil, errdefs.ErrNotImplemented
|
||||||
|
}
|
||||||
func (cs *composeService) Logs(ctx context.Context, project string, w io.Writer) error {
|
func (cs *composeService) Logs(ctx context.Context, project string, w io.Writer) error {
|
||||||
return errdefs.ErrNotImplemented
|
return errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user