github.com/kunnos/engine@v1.13.1/cli/command/stack/list.go (about) 1 package stack 2 3 import ( 4 "fmt" 5 "io" 6 "strconv" 7 "text/tabwriter" 8 9 "golang.org/x/net/context" 10 11 "github.com/docker/docker/api/types" 12 "github.com/docker/docker/cli" 13 "github.com/docker/docker/cli/command" 14 "github.com/docker/docker/cli/compose/convert" 15 "github.com/docker/docker/client" 16 "github.com/spf13/cobra" 17 ) 18 19 const ( 20 listItemFmt = "%s\t%s\n" 21 ) 22 23 type listOptions struct { 24 } 25 26 func newListCommand(dockerCli *command.DockerCli) *cobra.Command { 27 opts := listOptions{} 28 29 cmd := &cobra.Command{ 30 Use: "ls", 31 Aliases: []string{"list"}, 32 Short: "List stacks", 33 Args: cli.NoArgs, 34 RunE: func(cmd *cobra.Command, args []string) error { 35 return runList(dockerCli, opts) 36 }, 37 } 38 39 return cmd 40 } 41 42 func runList(dockerCli *command.DockerCli, opts listOptions) error { 43 client := dockerCli.Client() 44 ctx := context.Background() 45 46 stacks, err := getStacks(ctx, client) 47 if err != nil { 48 return err 49 } 50 51 out := dockerCli.Out() 52 printTable(out, stacks) 53 return nil 54 } 55 56 func printTable(out io.Writer, stacks []*stack) { 57 writer := tabwriter.NewWriter(out, 0, 4, 2, ' ', 0) 58 59 // Ignore flushing errors 60 defer writer.Flush() 61 62 fmt.Fprintf(writer, listItemFmt, "NAME", "SERVICES") 63 for _, stack := range stacks { 64 fmt.Fprintf( 65 writer, 66 listItemFmt, 67 stack.Name, 68 strconv.Itoa(stack.Services), 69 ) 70 } 71 } 72 73 type stack struct { 74 // Name is the name of the stack 75 Name string 76 // Services is the number of the services 77 Services int 78 } 79 80 func getStacks( 81 ctx context.Context, 82 apiclient client.APIClient, 83 ) ([]*stack, error) { 84 services, err := apiclient.ServiceList( 85 ctx, 86 types.ServiceListOptions{Filters: getAllStacksFilter()}) 87 if err != nil { 88 return nil, err 89 } 90 m := make(map[string]*stack, 0) 91 for _, service := range services { 92 labels := service.Spec.Labels 93 name, ok := labels[convert.LabelNamespace] 94 if !ok { 95 return nil, fmt.Errorf("cannot get label %s for service %s", 96 convert.LabelNamespace, service.ID) 97 } 98 ztack, ok := m[name] 99 if !ok { 100 m[name] = &stack{ 101 Name: name, 102 Services: 1, 103 } 104 } else { 105 ztack.Services++ 106 } 107 } 108 var stacks []*stack 109 for _, stack := range m { 110 stacks = append(stacks, stack) 111 } 112 return stacks, nil 113 }