Skip to content

Commit 9ed47aa

Browse files
committed
feat(ps): add pod describe
1 parent fd677ec commit 9ed47aa

3 files changed

Lines changed: 117 additions & 0 deletions

File tree

api/ps.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,18 @@ type Types struct {
5555
func (p PodTypes) Len() int { return len(p) }
5656
func (p PodTypes) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
5757
func (p PodTypes) Less(i, j int) bool { return p[i].Type < p[j].Type }
58+
59+
// ContainerState defines a container state.
60+
type ContainerState struct {
61+
Container string `json:"container"`
62+
Image string `json:"image"`
63+
Command []string `json:"command"`
64+
Args []string `json:"args"`
65+
State map[string]map[string]interface{} `json:"state"`
66+
LastState map[string]map[string]interface{} `json:"lastState"`
67+
Ready bool `json:"ready"`
68+
RestartCount int `json:"restartCount"`
69+
}
70+
71+
// PodState defines a collection of container state.
72+
type PodState []ContainerState

ps/ps.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,22 @@ func Restart(c *drycc.Client, appID string, procType string) error {
122122
return err
123123
}
124124

125+
// Describe pod state
126+
func Describe(c *drycc.Client, appID string, podID string, results int) (api.PodState, int, error) {
127+
u := fmt.Sprintf("/v2/apps/%s/pods/%s/describe/", appID, podID)
128+
129+
body, count, reqErr := c.LimitedRequest(u, results)
130+
if reqErr != nil && !drycc.IsErrAPIMismatch(reqErr) {
131+
return api.PodState{}, -1, reqErr
132+
}
133+
134+
var podState api.PodState
135+
if err := json.Unmarshal([]byte(body), &podState); err != nil {
136+
return api.PodState{}, -1, err
137+
}
138+
return podState, count, reqErr
139+
}
140+
125141
// ByType organizes processes of an app by process type.
126142
func ByType(processes api.PodsList) api.PodTypes {
127143
var pts api.PodTypes

ps/ps_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,39 @@ const processesFixture string = `
3232
]
3333
}`
3434

35+
const podStateFixture string = `
36+
{
37+
"count": 1,
38+
"next": null,
39+
"previous": null,
40+
"results": [{
41+
"container": "web",
42+
"image": "registry.drycc.cc/base/base",
43+
"command": ["bash", "-c"],
44+
"args": ["sleep 3600s"],
45+
"state": {
46+
"running": {
47+
"startedAt": "2024-05-21T02:27:03+00:00"
48+
},
49+
"waiting": {
50+
"message": "container create failed: executable file './start.sh' not found in $PATH: No such file or directory\n",
51+
"reason": "CreateContainerError"
52+
}
53+
},
54+
"lastState": {
55+
"terminated": {
56+
"containerID": "cri-o://ccfc73b0b4d966af4f93ca871a04fa97460620cd8005c1c36f7734a08ba49ed0",
57+
"exitCode": 1,
58+
"finishedAt": "2024-05-21T02:27:03+00:00",
59+
"reason": "Error",
60+
"startedAt": "2024-05-21T02:26:33+00:00"
61+
}
62+
},
63+
"ready": true,
64+
"restartCount": 1
65+
}]
66+
}`
67+
3568
const scaleExpected string = `{"web":2}`
3669

3770
type fakeHTTPServer struct{}
@@ -44,6 +77,11 @@ func (fakeHTTPServer) ServeHTTP(res http.ResponseWriter, req *http.Request) {
4477
return
4578
}
4679

80+
if req.URL.Path == "/v2/apps/example-go/pods/test-pod-web/describe/" && req.Method == "GET" {
81+
res.Write([]byte(podStateFixture))
82+
return
83+
}
84+
4785
if req.URL.Path == "/v2/apps/example-go/pods/restart/" && req.Method == "POST" {
4886
res.WriteHeader(http.StatusNoContent)
4987
return
@@ -235,6 +273,54 @@ func TestAppsRestart(t *testing.T) {
235273
}
236274
}
237275

276+
func TestDescribe(t *testing.T) {
277+
t.Parallel()
278+
279+
handler := fakeHTTPServer{}
280+
server := httptest.NewServer(&handler)
281+
defer server.Close()
282+
283+
drycc, err := drycc.New(false, server.URL, "abc")
284+
if err != nil {
285+
t.Fatal(err)
286+
}
287+
actual, _, err := Describe(drycc, "example-go", "test-pod-web", 100)
288+
if err != nil {
289+
t.Error(err)
290+
}
291+
expected := api.PodState{
292+
{
293+
Container: "web",
294+
Image: "registry.drycc.cc/base/base",
295+
Command: []string{"bash", "-c"},
296+
Args: []string{"sleep 3600s"},
297+
State: map[string]map[string]interface{}{
298+
"running": {
299+
"startedAt": "2024-05-21T02:27:03+00:00",
300+
},
301+
"waiting": {
302+
"message": "container create failed: executable file './start.sh' not found in $PATH: No such file or directory\n",
303+
"reason": "CreateContainerError",
304+
},
305+
},
306+
LastState: map[string]map[string]interface{}{
307+
"terminated": {
308+
"containerID": "cri-o://ccfc73b0b4d966af4f93ca871a04fa97460620cd8005c1c36f7734a08ba49ed0",
309+
"exitCode": 1,
310+
"finishedAt": "2024-05-21T02:27:03+00:00",
311+
"reason": "Error",
312+
"startedAt": "2024-05-21T02:26:33+00:00",
313+
},
314+
},
315+
Ready: true,
316+
RestartCount: 1,
317+
},
318+
}
319+
if !reflect.DeepEqual(actual[0].State, expected[0].State) {
320+
t.Error(fmt.Errorf("Expected %v, Got %v", actual[0].State, expected[0].State))
321+
}
322+
}
323+
238324
func TestScale(t *testing.T) {
239325
t.Parallel()
240326

0 commit comments

Comments
 (0)