Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit f368036

Browse files
committed
Add compose ps listing pod statuses (retrieve pods from compose project label)
This does not yet retrieve port sharing data (need to reconcile ports with kube services) Signed-off-by: Guillaume Tardif <guillaume.tardif@gmail.com>
1 parent 73e94b4 commit f368036

File tree

4 files changed

+111
-1
lines changed

4 files changed

+111
-1
lines changed

kube/client/client.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,24 @@
1919
package client
2020

2121
import (
22+
"context"
23+
"encoding/json"
24+
"fmt"
25+
26+
v1 "k8s.io/api/core/v1"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2228
"k8s.io/cli-runtime/pkg/genericclioptions"
2329
"k8s.io/client-go/kubernetes"
30+
31+
"github.com/docker/compose-cli/api/compose"
2432
)
2533

34+
// KubeClient API to access kube objects
2635
type KubeClient struct {
2736
client *kubernetes.Clientset
2837
}
2938

39+
// NewKubeClient new kubernetes client
3040
func NewKubeClient(config genericclioptions.RESTClientGetter) (*KubeClient, error) {
3141
restConfig, err := config.ToRESTConfig()
3242
if err != nil {
@@ -41,3 +51,31 @@ func NewKubeClient(config genericclioptions.RESTClientGetter) (*KubeClient, erro
4151
client: clientset,
4252
}, nil
4353
}
54+
55+
// GetContainers get containers for a given compose project
56+
func (kc KubeClient) GetContainers(ctx context.Context, projectName string, all bool) ([]compose.ContainerSummary, error) {
57+
pods, err := kc.client.CoreV1().Pods("").List(ctx, metav1.ListOptions{LabelSelector: fmt.Sprintf("%s=%s", compose.ProjectTag, projectName)})
58+
59+
if err != nil {
60+
return nil, err
61+
}
62+
json, _ := json.MarshalIndent(pods, "", " ")
63+
fmt.Println(string(json))
64+
fmt.Printf("containers: %d\n", len(pods.Items))
65+
result := []compose.ContainerSummary{}
66+
for _, pod := range pods.Items {
67+
result = append(result, podToContainerSummary(pod))
68+
}
69+
70+
return result, nil
71+
}
72+
73+
func podToContainerSummary(pod v1.Pod) compose.ContainerSummary {
74+
return compose.ContainerSummary{
75+
ID: pod.GetObjectMeta().GetName(),
76+
Name: pod.GetObjectMeta().GetName(),
77+
Service: pod.GetObjectMeta().GetLabels()[compose.ServiceTag],
78+
State: string(pod.Status.Phase),
79+
Project: pod.GetObjectMeta().GetLabels()[compose.ProjectTag],
80+
}
81+
}

kube/client/client_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// +build kube
2+
3+
/*
4+
Copyright 2020 Docker Compose CLI authors
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package client
20+
21+
import (
22+
"testing"
23+
24+
v1 "k8s.io/api/core/v1"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
27+
"gotest.tools/v3/assert"
28+
29+
"github.com/docker/compose-cli/api/compose"
30+
)
31+
32+
func TestPodToContainerSummary(t *testing.T) {
33+
pod := v1.Pod{
34+
ObjectMeta: metav1.ObjectMeta{
35+
Name: "c1-123",
36+
Labels: map[string]string{
37+
compose.ProjectTag: "myproject",
38+
compose.ServiceTag: "service1",
39+
},
40+
},
41+
Status: v1.PodStatus{
42+
Phase: "Running",
43+
},
44+
}
45+
46+
container := podToContainerSummary(pod)
47+
48+
expected := compose.ContainerSummary{
49+
ID: "c1-123",
50+
Name: "c1-123",
51+
Project: "myproject",
52+
Service: "service1",
53+
State: "Running",
54+
}
55+
assert.DeepEqual(t, container, expected)
56+
}

kube/compose.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ func NewComposeService(ctx context.Context) (compose.Service, error) {
5454
return nil, err
5555
}
5656
actions, err := helm.NewActions(config)
57+
if err != nil {
58+
return nil, err
59+
}
5760
apiClient, err := client.NewKubeClient(config)
5861
if err != nil {
5962
return nil, err
@@ -156,7 +159,7 @@ func (s *composeService) Logs(ctx context.Context, projectName string, consumer
156159

157160
// Ps executes the equivalent to a `compose ps`
158161
func (s *composeService) Ps(ctx context.Context, projectName string, options compose.PsOptions) ([]compose.ContainerSummary, error) {
159-
return nil, errdefs.ErrNotImplemented
162+
return s.client.GetContainers(ctx, projectName, options.All)
160163
}
161164

162165
// Convert translate compose model into backend's native format

kube/e2e/compose_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"testing"
2525
"time"
2626

27+
testify "github.com/stretchr/testify/assert"
2728
"gotest.tools/v3/assert"
2829
"gotest.tools/v3/icmd"
2930

@@ -78,6 +79,18 @@ func TestComposeUp(t *testing.T) {
7879
res.Assert(t, icmd.Expected{Out: `[{"Name":"compose-kube-demo","Status":"deployed"}]`})
7980
})
8081

82+
t.Run("compose ps", func(t *testing.T) {
83+
getServiceRegx := func(project string, service string) string {
84+
// match output with random hash / spaces like:
85+
// myproject-db-698f4dd798-jd9gw db Running
86+
return fmt.Sprintf("%s-%s-.*\\s+%s\\s+Pending\\s+", project, service, service)
87+
}
88+
res := c.RunDockerCmd("compose", "ps", "-p", projectName)
89+
testify.Regexp(t, getServiceRegx(projectName, "db"), res.Stdout())
90+
testify.Regexp(t, getServiceRegx(projectName, "words"), res.Stdout())
91+
testify.Regexp(t, getServiceRegx(projectName, "web"), res.Stdout())
92+
})
93+
8194
t.Run("check running project", func(t *testing.T) {
8295
// Docker Desktop kube cluster automatically exposes ports on the host, this is not the case with kind on Desktop,
8396
//we need to connect to the clusterIP, from the kind container

0 commit comments

Comments
 (0)