mirror of https://github.com/docker/compose.git
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
|
||||
}
|
||||
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 {
|
||||
return errdefs.ErrNotImplemented
|
||||
|
|
|
@ -73,6 +73,7 @@ func Command() *cobra.Command {
|
|||
upCommand(),
|
||||
downCommand(),
|
||||
psCommand(),
|
||||
listCommand(),
|
||||
logsCommand(),
|
||||
convertCommand(),
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
// 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
|
||||
func (c *composeService) Convert(context.Context, *types.Project) ([]byte, error) {
|
||||
return nil, errdefs.ErrNotImplemented
|
||||
|
|
|
@ -33,6 +33,8 @@ type Service interface {
|
|||
Logs(ctx context.Context, projectName string, w io.Writer) error
|
||||
// Ps executes the equivalent to a `compose ps`
|
||||
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(ctx context.Context, project *types.Project) ([]byte, error)
|
||||
}
|
||||
|
@ -54,3 +56,22 @@ type ServiceStatus struct {
|
|||
Ports []string
|
||||
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 (
|
||||
"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]
|
||||
func (b *ecsAPIService) List(ctx context.Context, project string) ([]compose.Stack, error) {
|
||||
return b.SDK.ListStacks(ctx, project)
|
||||
|
||||
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) {
|
||||
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")
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
aws.String(cloudformation.CapabilityCapabilityIam),
|
||||
},
|
||||
Tags: []*cloudformation.Tag{
|
||||
{
|
||||
Key: aws.String(compose.ProjectTag),
|
||||
Value: aws.String(name),
|
||||
},
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
@ -296,6 +302,36 @@ func (s sdk) GetStackID(ctx context.Context, name string) (string, error) {
|
|||
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) {
|
||||
// Fixme implement Paginator on Events and return as a chan(events)
|
||||
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) {
|
||||
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 {
|
||||
return errdefs.ErrNotImplemented
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue