Skip to content

Commit 99b95b4

Browse files
committed
feat(ps): add ps describe
1 parent 49a6b8f commit 99b95b4

7 files changed

Lines changed: 128 additions & 3 deletions

File tree

cmd/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ type Commander interface {
8888
PsExec(string, string, bool, bool, []string) error
8989
PsScale(string, []string) error
9090
PsRestart(string, string) error
91+
PsDescribe(string, string) error
9192
RegistryList(string) error
9293
RegistrySet(string, []string) error
9394
RegistryUnset(string, []string) error

cmd/ps.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,53 @@ func (d *DryccCmd) PsRestart(appID, target string) error {
159159
return nil
160160
}
161161

162+
// PsDescribe describe an app's processes.
163+
func (d *DryccCmd) PsDescribe(appID, podID string) error {
164+
s, appID, err := load(d.ConfigFile, appID)
165+
if err != nil {
166+
return err
167+
}
168+
// The 1000 is fake for now until API understands limits
169+
podState, _, err := ps.Describe(s.Client, appID, podID, 1000)
170+
if d.checkAPICompatibility(s.Client, err) != nil {
171+
return err
172+
}
173+
table := d.getDefaultFormatTable([]string{})
174+
for _, containerState := range podState {
175+
table.Append([]string{"Container:", containerState.Container})
176+
table.Append([]string{"Image:", containerState.Image})
177+
table.Append([]string{"Command:"})
178+
for _, command := range containerState.Command {
179+
table.Append([]string{"", fmt.Sprintf("- %v", command)})
180+
}
181+
table.Append([]string{"Args:"})
182+
for _, arg := range containerState.Args {
183+
table.Append([]string{"", fmt.Sprintf("- %v", arg)})
184+
}
185+
// State
186+
for key := range containerState.State {
187+
table.Append([]string{"State:", key})
188+
value := containerState.State[key]
189+
for innerKey := range value {
190+
table.Append([]string{fmt.Sprintf(" %s:", innerKey), strconv.Quote(fmt.Sprintf("%v", value[innerKey]))})
191+
}
192+
}
193+
// LastState
194+
for key := range containerState.LastState {
195+
table.Append([]string{"Last State:", key})
196+
value := containerState.LastState[key]
197+
for innerKey := range value {
198+
table.Append([]string{fmt.Sprintf(" %s:", innerKey), strconv.Quote(fmt.Sprintf("%v", value[innerKey]))})
199+
}
200+
}
201+
table.Append([]string{"Ready:", fmt.Sprintf("%v", containerState.Ready)})
202+
table.Append([]string{"Restart Count:", fmt.Sprintf("%v", containerState.RestartCount)})
203+
table.Append([]string{})
204+
}
205+
table.Render()
206+
return nil
207+
}
208+
162209
func printProcesses(d *DryccCmd, appID string, input []api.Pods) {
163210
processes := ps.ByType(input)
164211

cmd/ps_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,3 +242,52 @@ func TestPsRestart(t *testing.T) {
242242
err = cmdr.PsRestart("testapp", "web")
243243
assert.NoError(t, err)
244244
}
245+
246+
func TestPsDescribe(t *testing.T) {
247+
t.Parallel()
248+
cf, server, err := testutil.NewTestServerAndClient()
249+
if err != nil {
250+
t.Fatal(err)
251+
}
252+
defer server.Close()
253+
var b bytes.Buffer
254+
cmdr := DryccCmd{WOut: &b, ConfigFile: cf}
255+
256+
server.Mux.HandleFunc("/v2/apps/foo/pods/foo-web-111/describe/", func(w http.ResponseWriter, _ *http.Request) {
257+
testutil.SetHeaders(w)
258+
fmt.Fprintf(w, `{
259+
"count": 1,
260+
"next": null,
261+
"previous": null,
262+
"results": [{
263+
"container": "web",
264+
"image": "registry.drycc.cc/base/base",
265+
"command": ["bash", "-c"],
266+
"args": ["sleep 3600s"],
267+
"state": {
268+
"running": {
269+
"startedAt": "2024-05-21T02:27:03+00:00"
270+
},
271+
"waiting": {
272+
"message": "container create failed: executable file './start.sh' not found in $PATH: No such file or directory\n",
273+
"reason": "CreateContainerError"
274+
}
275+
},
276+
"lastState": {
277+
"terminated": {
278+
"containerID": "cri-o://ccfc73b0b4d966af4f93ca871a04fa97460620cd8005c1c36f7734a08ba49ed0",
279+
"exitCode": 1,
280+
"finishedAt": "2024-05-21T02:27:03+00:00",
281+
"reason": "Error",
282+
"startedAt": "2024-05-21T02:26:33+00:00"
283+
}
284+
},
285+
"ready": true,
286+
"restartCount": 1
287+
}]
288+
}`)
289+
})
290+
291+
err = cmdr.PsDescribe("foo", "foo-web-111")
292+
assert.NoError(t, err)
293+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.22
55
require (
66
github.com/containerd/console v1.0.4
77
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
8-
github.com/drycc/controller-sdk-go v0.0.0-20240501162129-fd677ec39e8c
8+
github.com/drycc/controller-sdk-go v0.0.0-20240522092128-9ed47aac090e
99
github.com/drycc/pkg v0.0.0-20240225112316-78fc9239f51f
1010
github.com/olekukonko/tablewriter v0.0.5
1111
github.com/stretchr/testify v1.9.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
44
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
55
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
66
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
7-
github.com/drycc/controller-sdk-go v0.0.0-20240501162129-fd677ec39e8c h1:C581oO1EmNJky8GpAricQftIufdeg2tlWgTvA5xPjJ0=
8-
github.com/drycc/controller-sdk-go v0.0.0-20240501162129-fd677ec39e8c/go.mod h1:n6eQe1irJqjwLo/7t9+Dhdv6faSESQN+ATnZRBP3/Uc=
7+
github.com/drycc/controller-sdk-go v0.0.0-20240522092128-9ed47aac090e h1:4gZBm6S2nsHH2JvX7Ky92XEM0JGPmVv6p6W7Phehz34=
8+
github.com/drycc/controller-sdk-go v0.0.0-20240522092128-9ed47aac090e/go.mod h1:n6eQe1irJqjwLo/7t9+Dhdv6faSESQN+ATnZRBP3/Uc=
99
github.com/drycc/pkg v0.0.0-20240225112316-78fc9239f51f h1:kgjvUQJeAszDoU1Vo4vTTE92KI8Av3JPb6Qn890niXg=
1010
github.com/drycc/pkg v0.0.0-20240225112316-78fc9239f51f/go.mod h1:n+QxGif6ha9CEoxVnlipxb9IdmerybcUSzTEDFkvjiA=
1111
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=

parser/ps.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ ps:logs print the logs for a container
1818
ps:exec execute a command in a container
1919
ps:restart restart an application or process type
2020
ps:scale scale processes (e.g. web=4 worker=2)
21+
ps:describe print a detailed description of the selected process
2122
2223
Use 'drycc help [command]' to learn more.
2324
`
@@ -33,6 +34,8 @@ Use 'drycc help [command]' to learn more.
3334
return psRestart(argv, cmdr)
3435
case "ps:scale":
3536
return psScale(argv, cmdr)
37+
case "ps:describe":
38+
return psDescribe(argv, cmdr)
3639
default:
3740
if printHelp(argv, usage) {
3841
return nil
@@ -184,3 +187,25 @@ Options:
184187
apps := safeGetString(args, "--app")
185188
return cmdr.PsScale(apps, args["<type>=<num>"].([]string))
186189
}
190+
191+
func psDescribe(argv []string, cmdr cmd.Commander) error {
192+
usage := `
193+
Print a detailed description of the selected process.
194+
195+
Usage: drycc ps:describe <pod> [options]
196+
197+
Options:
198+
-a --app=<app>
199+
the uniquely identifiable name for the application.
200+
`
201+
202+
args, err := docopt.ParseArgs(usage, argv, "")
203+
204+
if err != nil {
205+
return err
206+
}
207+
208+
app := safeGetString(args, "--app")
209+
pod := safeGetString(args, "<pod>")
210+
return cmdr.PsDescribe(app, pod)
211+
}

parser/ps_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ func (d FakeDryccCmd) PsRestart(string, string) error {
3232
return errors.New("ps:restart")
3333
}
3434

35+
func (d FakeDryccCmd) PsDescribe(string, string) error {
36+
return errors.New("ps:describe")
37+
}
3538
func TestPs(t *testing.T) {
3639
t.Parallel()
3740

0 commit comments

Comments
 (0)