-
Notifications
You must be signed in to change notification settings - Fork 950
/
Copy pathps.go
188 lines (161 loc) · 6.45 KB
/
ps.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
package main
import (
"context"
"fmt"
"os"
"sort"
"text/tabwriter"
"text/template"
"time"
"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/cli/formatter"
"github.com/alibaba/pouch/pkg/utils/filters"
"github.com/spf13/cobra"
)
// psDescription is used to describe ps command in detail and auto generate command doc.
var psDescription = "\nList Containers with container name, ID, status, creation time, image reference and runtime."
var psDefaultFormat = "table {{.Names}}\t{{.ID}}\t{{.Status}}\t{{.RunningFor}}\t{{.Image}}\t{{.Runtime}}\n"
// containerList is used to save the container list.
type containerList []*types.Container
// PsCommand is used to implement 'ps' command.
type PsCommand struct {
baseCommand
// flags for ps command
flagAll bool
flagQuiet bool
flagNoTrunc bool
flagFilter []string
flagFormat string
}
// Init initializes PsCommand command.
func (p *PsCommand) Init(c *Cli) {
p.cli = c
p.cmd = &cobra.Command{
Use: "ps [OPTIONS]",
Short: "List containers",
Long: psDescription,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return p.runPs(args)
},
Example: psExample(),
}
p.addFlags()
}
// addFlags adds flags for specific command.
func (p *PsCommand) addFlags() {
flagSet := p.cmd.Flags()
flagSet.BoolVarP(&p.flagAll, "all", "a", false, "Show all containers (default shows just running)")
flagSet.BoolVarP(&p.flagQuiet, "quiet", "q", false, "Only show numeric IDs")
flagSet.BoolVar(&p.flagNoTrunc, "no-trunc", false, "Do not truncate output")
flagSet.StringVarP(&p.flagFormat, "format", "", "", "intelligent-print containers based on Go template")
flagSet.StringSliceVarP(&p.flagFilter, "filter", "f", nil, "Filter output based on given conditions, support filter key [ id label name status ]")
}
// runPs is the entry of PsCommand command.
func (p *PsCommand) runPs(args []string) error {
ctx := context.Background()
apiClient := p.cli.Client()
filter, err := filters.Parse(p.flagFilter)
if err != nil {
return err
}
var containers containerList
option := types.ContainerListOptions{
All: p.flagAll,
Filter: filter,
}
containers, err = apiClient.ContainerList(ctx, option)
if err != nil {
return fmt.Errorf("failed to get container list: %v", err)
}
sort.Sort(containers)
if p.flagQuiet {
for _, c := range containers {
id := c.ID[:6]
if p.flagNoTrunc {
id = c.ID
}
fmt.Println(id)
}
return nil
}
// add to format the output with go template
format := p.flagFormat
tmplH := template.New("ps_head")
w := tabwriter.NewWriter(os.Stdout, 0, 0, p.cli.padding, ' ', 0)
if len(format) == 0 {
format = psDefaultFormat
}
// true is table,false is raw
tableOrRaw := formatter.IsTable(format)
format = formatter.PreFormat(format)
if tableOrRaw {
containerHeader := formatter.ContainerHeader
err = p.cli.FormatDisplay(format, tmplH, containerHeader, w)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "format display error:%+v\n", err)
}
}
for _, c := range containers {
containerContext, err := formatter.NewContainerContext(c, p.flagNoTrunc)
if err != nil {
return err
}
tmplD := template.New("ps_detail")
err = p.cli.FormatDisplay(format, tmplD, containerContext, w)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "format display error:%+v\n", err)
}
}
_ = w.Flush()
return nil
}
// psExample shows examples in ps command, and is used in auto-generated cli docs.
func psExample() string {
return `$ pouch ps
Name ID Status Created Image Runtime
2 e42c68 Up 15 minutes 16 minutes ago docker.io/library/busybox:latest runc
1 a8c2ea Up 16 minutes 17 minutes ago docker.io/library/busybox:latest runc
$ pouch ps -a
Name ID Status Created Image Runtime
3 faf132 created 16 seconds ago docker.io/library/busybox:latest runc
2 e42c68 Up 16 minutes 16 minutes ago docker.io/library/busybox:latest runc
1 a8c2ea Up 17 minutes 18 minutes ago docker.io/library/busybox:latest runc
$ pouch ps -q
e42c68
a8c2ea
$ pouch ps -a -q
faf132
e42c68
a8c2ea
$ pouch ps --no-trunc
Name ID Status Created Image Runtime
foo2 692c77587b38f60bbd91d986ec3703848d72aea5030e320d4988eb02aa3f9d48 Up 1 minute 1 minute ago docker.io/library/redis:alpine runc
foo 18592900006405ee64788bd108ef1de3d24dc3add73725891f4787d0f8e036f5 Up 1 minute 1 minute ago docker.io/library/redis:alpine runc
$ pouch ps --no-trunc -q
692c77587b38f60bbd91d986ec3703848d72aea5030e320d4988eb02aa3f9d48
18592900006405ee64788bd108ef1de3d24dc3add73725891f4787d0f8e036f5
$ pouch ps --no-trunc -a
Name ID Status Created Image Runtime
foo3 63fd6371f3d614bb1ecad2780972d5975ca1ab534ec280c5f7d8f4c7b2e9989d created 2 minutes ago docker.io/library/redis:alpine runc
foo2 692c77587b38f60bbd91d986ec3703848d72aea5030e320d4988eb02aa3f9d48 Up 2 minutes 2 minutes ago docker.io/library/redis:alpine runc
foo 18592900006405ee64788bd108ef1de3d24dc3add73725891f4787d0f8e036f5 Up 2 minutes 2 minutes ago docker.io/library/redis:alpine runc
$ pouch ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Command}}\t{{.CreatedAt}}\t{{.RunningFor}}\t{{.Ports}}\t{{.Status}}\t{{.Size}}\t{{.Labels}}\t{{.Mounts}}\t{{.LocalVolumes}}\t{{.Networks}}\t{{.Runtime}}\t{{.ImageID}}"
ID Name Image Command CreatedAt Created Ports Status Size Labels Mounts Volumes Networks Runtime ImageID
869433 test registry.hub.docker.com/library/busybox:1.28 sh 2019-05-29 05:40:46.64617376 +0000 UTC 6 seconds ago 3333/tcp->:3333; Up 6 seconds 0B a = b; /root/test; 0 bridge runc sha256:8c811b4aec35f259572d0f79207bc0678df4c736eeec50bc9fec37ed936a472a
`
}
// Len implements the sort interface.
func (c containerList) Len() int {
return len(c)
}
// Swap implements the sort interface.
func (c containerList) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
// Less implements the sort interface.
func (c containerList) Less(i, j int) bool {
iValue := time.Unix(c[i].Created, 0)
jValue := time.Unix(c[j].Created, 0)
return iValue.After(jValue)
}