Merge pull request #1172 from docker/ls_filters

introduce `--filter` option on `compose ls`
This commit is contained in:
Nicolas De loof 2021-01-22 10:54:20 +01:00 committed by GitHub
commit dc790d542f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 48 additions and 30 deletions

View File

@ -163,20 +163,17 @@ 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) {
func (cs *aciComposeService) List(ctx context.Context) ([]compose.Stack, error) {
containerGroups, err := getACIContainerGroups(ctx, cs.ctx.SubscriptionID, cs.ctx.ResourceGroup)
if err != nil {
return nil, err
}
stacks := []compose.Stack{}
var stacks []compose.Stack
for _, group := range containerGroups {
if _, found := group.Tags[composeContainerTag]; !found {
continue
}
if project != "" && *group.Name != project {
continue
}
state := compose.RUNNING
for _, container := range *group.ContainerGroupProperties.Containers {
containerState := convert.GetStatus(container, group)

View File

@ -64,7 +64,7 @@ func (c *composeService) Ps(context.Context, string) ([]compose.ContainerSummary
return nil, errdefs.ErrNotImplemented
}
func (c *composeService) List(context.Context, string) ([]compose.Stack, error) {
func (c *composeService) List(context.Context) ([]compose.Stack, error) {
return nil, errdefs.ErrNotImplemented
}

View File

@ -44,7 +44,7 @@ type Service interface {
// Ps executes the equivalent to a `compose ps`
Ps(ctx context.Context, projectName string) ([]ContainerSummary, error)
// List executes the equivalent to a `docker stack ls`
List(ctx context.Context, projectName string) ([]Stack, error)
List(ctx context.Context) ([]Stack, error)
// Convert translate compose model into backend's native format
Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
// RunOneOffContainer creates a service oneoff container and starts its dependencies

View File

@ -23,6 +23,7 @@ import (
"os"
"strings"
"github.com/docker/cli/opts"
"github.com/spf13/cobra"
"github.com/docker/compose-cli/api/client"
@ -33,10 +34,11 @@ import (
type lsOptions struct {
Format string
Quiet bool
Filter opts.FilterOpt
}
func listCommand() *cobra.Command {
opts := lsOptions{}
opts := lsOptions{Filter: opts.NewFilterOpt()}
lsCmd := &cobra.Command{
Use: "ls",
Short: "List running compose projects",
@ -45,16 +47,28 @@ func listCommand() *cobra.Command {
},
}
lsCmd.Flags().StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
lsCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
lsCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs.")
lsCmd.Flags().Var(&opts.Filter, "filter", "Filter output based on conditions provided.")
return lsCmd
}
var acceptedListFilters = map[string]bool{
"name": true,
}
func runList(ctx context.Context, opts lsOptions) error {
filters := opts.Filter.Value()
err := filters.Validate(acceptedListFilters)
if err != nil {
return err
}
c, err := client.NewWithDefaultLocalBackend(ctx)
if err != nil {
return err
}
stackList, err := c.ComposeService().List(ctx, "")
stackList, err := c.ComposeService().List(ctx)
if err != nil {
return err
}
@ -64,6 +78,18 @@ func runList(ctx context.Context, opts lsOptions) error {
}
return nil
}
if filters.Len() > 0 {
var filtered []compose.Stack
for _, s := range stackList {
if filters.Contains("name") && !filters.Match("name", s.Name) {
continue
}
filtered = append(filtered, s)
}
stackList = filtered
}
view := viewFromStackList(stackList)
return formatter.Print(view, opts.Format, os.Stdout, func(w io.Writer) {
for _, stack := range view {

View File

@ -77,7 +77,7 @@ func (p *proxy) Services(ctx context.Context, request *composev1.ComposeServices
}
func (p *proxy) Stacks(ctx context.Context, request *composev1.ComposeStacksRequest) (*composev1.ComposeStacksResponse, error) {
stacks, err := Client(ctx).ComposeService().List(ctx, request.ProjectName)
stacks, err := Client(ctx).ComposeService().List(ctx)
if err != nil {
return nil, err
}

View File

@ -49,7 +49,7 @@ type API interface {
UpdateStack(ctx context.Context, changeset string) error
WaitStackComplete(ctx context.Context, name string, operation int) error
GetStackID(ctx context.Context, name string) (string, error)
ListStacks(ctx context.Context, name string) ([]compose.Stack, error)
ListStacks(ctx context.Context) ([]compose.Stack, error)
GetStackClusterID(ctx context.Context, stack string) (string, error)
GetServiceTaskDefinition(ctx context.Context, cluster string, serviceArns []string) (map[string]string, error)
ListStackServices(ctx context.Context, stack string) ([]string, error)

View File

@ -6,14 +6,12 @@ package ecs
import (
context "context"
reflect "reflect"
cloudformation "github.com/aws/aws-sdk-go/service/cloudformation"
ecs "github.com/aws/aws-sdk-go/service/ecs"
gomock "github.com/golang/mock/gomock"
compose "github.com/docker/compose-cli/api/compose"
secrets "github.com/docker/compose-cli/api/secrets"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
// MockAPI is a mock of API interface
@ -546,18 +544,18 @@ func (mr *MockAPIMockRecorder) ListStackServices(arg0, arg1 interface{}) *gomock
}
// ListStacks mocks base method
func (m *MockAPI) ListStacks(arg0 context.Context, arg1 string) ([]compose.Stack, error) {
func (m *MockAPI) ListStacks(arg0 context.Context) ([]compose.Stack, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListStacks", arg0, arg1)
ret := m.ctrl.Call(m, "ListStacks", arg0)
ret0, _ := ret[0].([]compose.Stack)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListStacks indicates an expected call of ListStacks
func (mr *MockAPIMockRecorder) ListStacks(arg0, arg1 interface{}) *gomock.Call {
func (mr *MockAPIMockRecorder) ListStacks(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListStacks", reflect.TypeOf((*MockAPI)(nil).ListStacks), arg0, arg1)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListStacks", reflect.TypeOf((*MockAPI)(nil).ListStacks), arg0)
}
// ListTasks mocks base method

View File

@ -122,7 +122,7 @@ func TestCompose(t *testing.T) {
})
t.Run("compose ls", func(t *testing.T) {
res := c.RunDockerCmd("compose", "ls", "--project-name", stack)
res := c.RunDockerCmd("compose", "ls", "--filter", "name="+stack)
lines := strings.Split(strings.TrimSpace(res.Stdout()), "\n")
assert.Equal(t, 2, len(lines))

View File

@ -23,8 +23,8 @@ import (
"github.com/docker/compose-cli/api/compose"
)
func (b *ecsAPIService) List(ctx context.Context, project string) ([]compose.Stack, error) {
stacks, err := b.aws.ListStacks(ctx, project)
func (b *ecsAPIService) List(ctx context.Context) ([]compose.Stack, error) {
stacks, err := b.aws.ListStacks(ctx)
if err != nil {
return nil, err
}

View File

@ -161,8 +161,8 @@ func (e ecsLocalSimulation) Logs(ctx context.Context, projectName string, consum
func (e ecsLocalSimulation) Ps(ctx context.Context, projectName string) ([]compose.ContainerSummary, error) {
return e.compose.Ps(ctx, projectName)
}
func (e ecsLocalSimulation) List(ctx context.Context, projectName string) ([]compose.Stack, error) {
return e.compose.List(ctx, projectName)
func (e ecsLocalSimulation) List(ctx context.Context) ([]compose.Stack, error) {
return e.compose.List(ctx)
}
func (e ecsLocalSimulation) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
return errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose run")

View File

@ -444,11 +444,8 @@ 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) {
func (s sdk) ListStacks(ctx context.Context) ([]compose.Stack, error) {
params := cloudformation.DescribeStacksInput{}
if name != "" {
params.StackName = &name
}
var token *string
var stacks []compose.Stack
for {

View File

@ -27,7 +27,7 @@ import (
"github.com/docker/docker/api/types/filters"
)
func (s *composeService) List(ctx context.Context, projectName string) ([]compose.Stack, error) {
func (s *composeService) List(ctx context.Context) ([]compose.Stack, error) {
list, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
Filters: filters.NewArgs(hasProjectLabelFilter()),
})