Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit 9483623

Browse files
committed
runv: implement ps command
The PS command is currently limited by the runv-containerd interfacer. Until runv and hyperstart is refactored, print out the information that the current design can support. Signed-off-by: Antonios Motakis <antonios.motakis@huawei.com>
1 parent 1fb28a3 commit 9483623

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ func main() {
152152
execCommand,
153153
killCommand,
154154
listCommand,
155+
psCommand,
155156
runCommand,
156157
specCommand,
157158
startCommand,

ps.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
"text/tabwriter"
9+
10+
"github.com/hyperhq/runv/containerd/api/grpc/types"
11+
"github.com/urfave/cli"
12+
netcontext "golang.org/x/net/context"
13+
)
14+
15+
var psCommand = cli.Command{
16+
Name: "ps",
17+
Usage: "ps displays the processes running inside a container",
18+
ArgsUsage: `<container-id> [ps options]`, Flags: []cli.Flag{
19+
cli.StringFlag{
20+
Name: "format, f",
21+
Value: "table",
22+
Usage: `select one of: ` + formatOptions,
23+
},
24+
},
25+
Action: func(context *cli.Context) error {
26+
container := context.Args().First()
27+
if container == "" {
28+
return cli.NewExitError("container id cannot be empty", -1)
29+
}
30+
c, err := getContainerApi(context, container)
31+
if err != nil {
32+
return cli.NewExitError(fmt.Sprintf("can't access container, %v", err), -1)
33+
}
34+
35+
switch context.String("format") {
36+
case "table":
37+
w := tabwriter.NewWriter(os.Stdout, 12, 1, 3, ' ', 0)
38+
fmt.Fprint(w, "PROCESS\tCMD\n")
39+
// we are limited by the containerd interface for now
40+
for _, p := range c.Processes {
41+
fmt.Fprintf(w, "%s\t%s\n",
42+
p.Pid,
43+
p.Args)
44+
}
45+
if err := w.Flush(); err != nil {
46+
fatal(err)
47+
}
48+
case "json":
49+
pids := make([]string, 0)
50+
for _, p := range c.Processes {
51+
pids = append(pids, p.Pid)
52+
}
53+
54+
data, err := json.Marshal(pids)
55+
if err != nil {
56+
fatal(err)
57+
}
58+
os.Stdout.Write(data)
59+
return nil
60+
default:
61+
return cli.NewExitError(fmt.Sprintf("invalid format option"), -1)
62+
}
63+
64+
return nil
65+
},
66+
}
67+
68+
func getContainerApi(context *cli.Context, container string) (*types.Container, error) {
69+
api, err := getClient(filepath.Join(context.GlobalString("root"), container, "namespace/namespaced.sock"))
70+
if err != nil {
71+
return nil, fmt.Errorf("failed to get client: %v", err)
72+
}
73+
74+
s, err := api.State(netcontext.Background(), &types.StateRequest{Id: container})
75+
if err != nil {
76+
return nil, fmt.Errorf("get container state failed, %v", err)
77+
}
78+
79+
for _, c := range s.Containers {
80+
if c.Id == container {
81+
return c, nil
82+
}
83+
}
84+
85+
return nil, fmt.Errorf("container %s not found", container)
86+
}

0 commit comments

Comments
 (0)