mirror of https://github.com/docker/compose.git
Merge pull request #1172 from docker/ls_filters
introduce `--filter` option on `compose ls`
This commit is contained in:
commit
dc790d542f
|
@ -163,20 +163,17 @@ 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) {
|
func (cs *aciComposeService) List(ctx context.Context) ([]compose.Stack, error) {
|
||||||
containerGroups, err := getACIContainerGroups(ctx, cs.ctx.SubscriptionID, cs.ctx.ResourceGroup)
|
containerGroups, err := getACIContainerGroups(ctx, cs.ctx.SubscriptionID, cs.ctx.ResourceGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
stacks := []compose.Stack{}
|
var stacks []compose.Stack
|
||||||
for _, group := range containerGroups {
|
for _, group := range containerGroups {
|
||||||
if _, found := group.Tags[composeContainerTag]; !found {
|
if _, found := group.Tags[composeContainerTag]; !found {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if project != "" && *group.Name != project {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
state := compose.RUNNING
|
state := compose.RUNNING
|
||||||
for _, container := range *group.ContainerGroupProperties.Containers {
|
for _, container := range *group.ContainerGroupProperties.Containers {
|
||||||
containerState := convert.GetStatus(container, group)
|
containerState := convert.GetStatus(container, group)
|
||||||
|
|
|
@ -64,7 +64,7 @@ func (c *composeService) Ps(context.Context, string) ([]compose.ContainerSummary
|
||||||
return nil, errdefs.ErrNotImplemented
|
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
|
return nil, errdefs.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ type Service interface {
|
||||||
// Ps executes the equivalent to a `compose ps`
|
// Ps executes the equivalent to a `compose ps`
|
||||||
Ps(ctx context.Context, projectName string) ([]ContainerSummary, error)
|
Ps(ctx context.Context, projectName string) ([]ContainerSummary, error)
|
||||||
// List executes the equivalent to a `docker stack ls`
|
// 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 translate compose model into backend's native format
|
||||||
Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
|
Convert(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
|
||||||
// RunOneOffContainer creates a service oneoff container and starts its dependencies
|
// RunOneOffContainer creates a service oneoff container and starts its dependencies
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/cli/opts"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/docker/compose-cli/api/client"
|
"github.com/docker/compose-cli/api/client"
|
||||||
|
@ -33,10 +34,11 @@ import (
|
||||||
type lsOptions struct {
|
type lsOptions struct {
|
||||||
Format string
|
Format string
|
||||||
Quiet bool
|
Quiet bool
|
||||||
|
Filter opts.FilterOpt
|
||||||
}
|
}
|
||||||
|
|
||||||
func listCommand() *cobra.Command {
|
func listCommand() *cobra.Command {
|
||||||
opts := lsOptions{}
|
opts := lsOptions{Filter: opts.NewFilterOpt()}
|
||||||
lsCmd := &cobra.Command{
|
lsCmd := &cobra.Command{
|
||||||
Use: "ls",
|
Use: "ls",
|
||||||
Short: "List running compose projects",
|
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().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
|
return lsCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var acceptedListFilters = map[string]bool{
|
||||||
|
"name": true,
|
||||||
|
}
|
||||||
|
|
||||||
func runList(ctx context.Context, opts lsOptions) error {
|
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)
|
c, err := client.NewWithDefaultLocalBackend(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
stackList, err := c.ComposeService().List(ctx, "")
|
stackList, err := c.ComposeService().List(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -64,6 +78,18 @@ func runList(ctx context.Context, opts lsOptions) error {
|
||||||
}
|
}
|
||||||
return nil
|
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)
|
view := viewFromStackList(stackList)
|
||||||
return formatter.Print(view, opts.Format, os.Stdout, func(w io.Writer) {
|
return formatter.Print(view, opts.Format, os.Stdout, func(w io.Writer) {
|
||||||
for _, stack := range view {
|
for _, stack := range view {
|
||||||
|
|
|
@ -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) {
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ type API interface {
|
||||||
UpdateStack(ctx context.Context, changeset string) error
|
UpdateStack(ctx context.Context, changeset string) error
|
||||||
WaitStackComplete(ctx context.Context, name string, operation int) error
|
WaitStackComplete(ctx context.Context, name string, operation int) error
|
||||||
GetStackID(ctx context.Context, name string) (string, 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)
|
GetStackClusterID(ctx context.Context, stack string) (string, error)
|
||||||
GetServiceTaskDefinition(ctx context.Context, cluster string, serviceArns []string) (map[string]string, error)
|
GetServiceTaskDefinition(ctx context.Context, cluster string, serviceArns []string) (map[string]string, error)
|
||||||
ListStackServices(ctx context.Context, stack string) ([]string, error)
|
ListStackServices(ctx context.Context, stack string) ([]string, error)
|
||||||
|
|
|
@ -6,14 +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"
|
||||||
gomock "github.com/golang/mock/gomock"
|
|
||||||
|
|
||||||
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"
|
||||||
|
reflect "reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MockAPI is a mock of API interface
|
// MockAPI is a mock of API interface
|
||||||
|
@ -546,18 +544,18 @@ func (mr *MockAPIMockRecorder) ListStackServices(arg0, arg1 interface{}) *gomock
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListStacks mocks base method
|
// 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()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "ListStacks", arg0, arg1)
|
ret := m.ctrl.Call(m, "ListStacks", arg0)
|
||||||
ret0, _ := ret[0].([]compose.Stack)
|
ret0, _ := ret[0].([]compose.Stack)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListStacks indicates an expected call of ListStacks
|
// 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()
|
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
|
// ListTasks mocks base method
|
||||||
|
|
|
@ -122,7 +122,7 @@ func TestCompose(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("compose ls", func(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")
|
lines := strings.Split(strings.TrimSpace(res.Stdout()), "\n")
|
||||||
|
|
||||||
assert.Equal(t, 2, len(lines))
|
assert.Equal(t, 2, len(lines))
|
||||||
|
|
|
@ -23,8 +23,8 @@ import (
|
||||||
"github.com/docker/compose-cli/api/compose"
|
"github.com/docker/compose-cli/api/compose"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *ecsAPIService) List(ctx context.Context, project string) ([]compose.Stack, error) {
|
func (b *ecsAPIService) List(ctx context.Context) ([]compose.Stack, error) {
|
||||||
stacks, err := b.aws.ListStacks(ctx, project)
|
stacks, err := b.aws.ListStacks(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
func (e ecsLocalSimulation) Ps(ctx context.Context, projectName string) ([]compose.ContainerSummary, error) {
|
||||||
return e.compose.Ps(ctx, projectName)
|
return e.compose.Ps(ctx, projectName)
|
||||||
}
|
}
|
||||||
func (e ecsLocalSimulation) List(ctx context.Context, projectName string) ([]compose.Stack, error) {
|
func (e ecsLocalSimulation) List(ctx context.Context) ([]compose.Stack, error) {
|
||||||
return e.compose.List(ctx, projectName)
|
return e.compose.List(ctx)
|
||||||
}
|
}
|
||||||
func (e ecsLocalSimulation) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
|
func (e ecsLocalSimulation) RunOneOffContainer(ctx context.Context, project *types.Project, opts compose.RunOptions) error {
|
||||||
return errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose run")
|
return errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose run")
|
||||||
|
|
|
@ -444,11 +444,8 @@ 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) {
|
func (s sdk) ListStacks(ctx context.Context) ([]compose.Stack, error) {
|
||||||
params := cloudformation.DescribeStacksInput{}
|
params := cloudformation.DescribeStacksInput{}
|
||||||
if name != "" {
|
|
||||||
params.StackName = &name
|
|
||||||
}
|
|
||||||
var token *string
|
var token *string
|
||||||
var stacks []compose.Stack
|
var stacks []compose.Stack
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -27,7 +27,7 @@ import (
|
||||||
"github.com/docker/docker/api/types/filters"
|
"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{
|
list, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{
|
||||||
Filters: filters.NewArgs(hasProjectLabelFilter()),
|
Filters: filters.NewArgs(hasProjectLabelFilter()),
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue