Skip to content

Commit cb65bda

Browse files
authored
fix(api): role/clusterole/podlist endpoints (#8881)
* fix: role/clusterrole listing, improve logging when metrics are disabled and add container statuses to pod list * fix unit tests and license check * update cd-helm workflow * remove chart lint from master workflow * remove debug log line * regenerate schema
1 parent d72a202 commit cb65bda

File tree

14 files changed

+352
-87
lines changed

14 files changed

+352
-87
lines changed

.github/workflows/cd-helm.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ jobs:
3434
with:
3535
version: v3.12.1
3636
- uses: helm/[email protected]
37-
- run: ct lint --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }}
3837
- uses: helm/[email protected]
3938
with:
4039
node_image: kindest/node:v1.29.0

modules/api/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ fix-go: $(PRE)
6161
.PHONY: run
6262
run: build
6363
@$(API_DIST_BINARY) \
64-
--kubeconfig=$(KUBECONFIG)
64+
--kubeconfig=$(KUBECONFIG) \
65+
--metrics-provider=none
6566

6667
.PHONY: schema
6768
schema: --ensure-kind-cluster build --swagger

modules/api/pkg/handler/apihandler.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,12 @@ func CreateHTTPAPIHandler(iManager integration.Manager) (*restful.Container, err
994994
Returns(http.StatusOK, "OK", clusterrolebinding.ClusterRoleBindingDetail{}))
995995

996996
// Role
997+
apiV1Ws.Route(
998+
apiV1Ws.GET("/role").To(apiHandler.handleGetRoleList).
999+
// docs
1000+
Doc("returns a list of Roles from all namespace").
1001+
Writes(role.RoleList{}).
1002+
Returns(http.StatusOK, "OK", role.RoleList{}))
9971003
apiV1Ws.Route(
9981004
apiV1Ws.GET("/role/{namespace}").To(apiHandler.handleGetRoleList).
9991005
// docs
@@ -1011,6 +1017,12 @@ func CreateHTTPAPIHandler(iManager integration.Manager) (*restful.Container, err
10111017
Returns(http.StatusOK, "OK", role.RoleDetail{}))
10121018

10131019
// RoleBinding
1020+
apiV1Ws.Route(
1021+
apiV1Ws.GET("/rolebinding").To(apiHandler.handleGetRoleBindingList).
1022+
// docs
1023+
Doc("returns a list of RoleBindings from all namespace").
1024+
Writes(rolebinding.RoleBindingList{}).
1025+
Returns(http.StatusOK, "OK", rolebinding.RoleBindingList{}))
10141026
apiV1Ws.Route(
10151027
apiV1Ws.GET("/rolebinding/{namespace}").To(apiHandler.handleGetRoleBindingList).
10161028
// docs

modules/api/pkg/resource/dataselect/dataselect.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
package dataselect
1616

1717
import (
18-
"log"
1918
"sort"
2019

20+
"k8s.io/klog/v2"
21+
2122
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
2223
"k8s.io/dashboard/errors"
2324
)
@@ -129,7 +130,7 @@ func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
129130
metricPromises := make([]metricapi.MetricPromises, 0)
130131

131132
if metricClient == nil {
132-
return metricPromises, errors.NewInternal("No metric client provided. Skipping metrics.")
133+
return metricPromises, nil
133134
}
134135

135136
metricNames := self.DataSelectQuery.MetricQuery.MetricNames
@@ -142,7 +143,7 @@ func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
142143
// make sure data cells support metrics
143144
metricDataCell, ok := dataCell.(MetricDataCell)
144145
if !ok {
145-
log.Printf("Data cell does not implement MetricDataCell. Skipping. %v", dataCell)
146+
klog.V(0).InfoS("Data cell does not implement MetricDataCell. Skipping.", "dataCell", dataCell)
146147
continue
147148
}
148149

@@ -162,7 +163,11 @@ func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
162163
func (self *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataSelector {
163164
metricPromisesList, err := self.getMetrics(metricClient)
164165
if err != nil {
165-
log.Print(err)
166+
klog.ErrorS(err, "error during getting metrics")
167+
return self
168+
}
169+
170+
if len(metricPromisesList) == 0 {
166171
return self
167172
}
168173

@@ -180,13 +185,17 @@ func (self *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataS
180185
func (self *DataSelector) GetCumulativeMetrics(metricClient metricapi.MetricClient) *DataSelector {
181186
metricPromisesList, err := self.getMetrics(metricClient)
182187
if err != nil {
183-
log.Print(err)
188+
klog.ErrorS(err, "error during getting metrics")
189+
return self
190+
}
191+
192+
if len(metricPromisesList) == 0 {
184193
return self
185194
}
186195

187196
metricNames := self.DataSelectQuery.MetricQuery.MetricNames
188197
if metricNames == nil {
189-
log.Print("No metrics specified. Skipping metrics.")
198+
klog.V(1).Info("Metrics names not provided. Skipping.")
190199
return self
191200
}
192201

modules/api/pkg/resource/node/detail.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ type NodeDetail struct {
8484
Node `json:",inline"`
8585

8686
// NodePhase is the current lifecycle phase of the node.
87+
// Deprecated
8788
Phase v1.NodePhase `json:"phase"`
8889

8990
// PodCIDR represents the pod IP range assigned to the node.
@@ -339,8 +340,10 @@ func toNodeDetail(node v1.Node, pods *pod.PodList, eventList *common.EventList,
339340
Node: Node{
340341
ObjectMeta: types.NewObjectMeta(node.ObjectMeta),
341342
TypeMeta: types.NewTypeMeta(types.ResourceKindNode),
343+
Ready: getNodeConditionStatus(node, v1.NodeReady),
342344
AllocatedResources: allocatedResources,
343345
},
346+
// TODO: Remove deprecated field
344347
Phase: node.Status.Phase,
345348
ProviderID: node.Spec.ProviderID,
346349
PodCIDR: node.Spec.PodCIDR,

modules/api/pkg/resource/node/detail_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ func TestGetNodeDetail(t *testing.T) {
6464
PodCapacity: 0,
6565
PodFraction: 0,
6666
},
67+
Ready: v1.ConditionUnknown,
6768
},
6869
PodCIDR: "127.0.0.1",
6970
ProviderID: "ID-1",

modules/api/pkg/resource/pod/common_test.go

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ func TestToPodPodStatusFailed(t *testing.T) {
4040
}
4141

4242
expected := Pod{
43-
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
44-
Status: string(v1.PodFailed),
45-
Warnings: []common.Event{},
43+
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
44+
Status: string(v1.PodFailed),
45+
Warnings: []common.Event{},
46+
ContainerStatuses: make([]ContainerStatus, 0),
4647
}
4748

4849
actual := toPod(pod, &MetricsByPod{}, []common.Event{})
@@ -67,9 +68,10 @@ func TestToPodPodStatusSucceeded(t *testing.T) {
6768
}
6869

6970
expected := Pod{
70-
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
71-
Status: string(v1.PodSucceeded),
72-
Warnings: []common.Event{},
71+
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
72+
Status: string(v1.PodSucceeded),
73+
Warnings: []common.Event{},
74+
ContainerStatuses: make([]ContainerStatus, 0),
7375
}
7476

7577
actual := toPod(pod, &MetricsByPod{}, []common.Event{})
@@ -98,9 +100,10 @@ func TestToPodPodStatusRunning(t *testing.T) {
98100
}
99101

100102
expected := Pod{
101-
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
102-
Status: string(v1.PodRunning),
103-
Warnings: []common.Event{},
103+
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
104+
Status: string(v1.PodRunning),
105+
Warnings: []common.Event{},
106+
ContainerStatuses: make([]ContainerStatus, 0),
104107
}
105108

106109
actual := toPod(pod, &MetricsByPod{}, []common.Event{})
@@ -125,9 +128,10 @@ func TestToPodPodStatusPending(t *testing.T) {
125128
}
126129

127130
expected := Pod{
128-
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
129-
Status: string(v1.PodPending),
130-
Warnings: []common.Event{},
131+
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
132+
Status: string(v1.PodPending),
133+
Warnings: []common.Event{},
134+
ContainerStatuses: make([]ContainerStatus, 0),
131135
}
132136

133137
actual := toPod(pod, &MetricsByPod{}, []common.Event{})
@@ -165,6 +169,14 @@ func TestToPodContainerStates(t *testing.T) {
165169
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
166170
Status: "Terminated",
167171
Warnings: []common.Event{},
172+
ContainerStatuses: []ContainerStatus{
173+
{
174+
State: Terminated,
175+
},
176+
{
177+
State: Waiting,
178+
},
179+
},
168180
}
169181

170182
actual := toPod(pod, &MetricsByPod{}, []common.Event{})
@@ -184,8 +196,9 @@ func TestToPod(t *testing.T) {
184196
{
185197
pod: &v1.Pod{}, metrics: &MetricsByPod{},
186198
expected: Pod{
187-
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
188-
Warnings: []common.Event{},
199+
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
200+
Warnings: []common.Event{},
201+
ContainerStatuses: make([]ContainerStatus, 0),
189202
},
190203
}, {
191204
pod: &v1.Pod{
@@ -199,7 +212,8 @@ func TestToPod(t *testing.T) {
199212
Name: "test-pod",
200213
Namespace: "test-namespace",
201214
},
202-
Warnings: []common.Event{},
215+
Warnings: []common.Event{},
216+
ContainerStatuses: make([]ContainerStatus, 0),
203217
},
204218
},
205219
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2017 The Kubernetes Authors.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package pod
16+
17+
import (
18+
v1 "k8s.io/api/core/v1"
19+
)
20+
21+
type ContainerStatus struct {
22+
Name string `json:"name"`
23+
State ContainerState `json:"state"`
24+
Ready bool `json:"ready"`
25+
}
26+
27+
type ContainerState string
28+
29+
const (
30+
Waiting ContainerState = "Waiting"
31+
Running ContainerState = "Running"
32+
Terminated ContainerState = "Terminated"
33+
Unknown ContainerState = "Unknown"
34+
)
35+
36+
func ToContainerStatuses(containerStatuses []v1.ContainerStatus) []ContainerStatus {
37+
result := make([]ContainerStatus, len(containerStatuses))
38+
for i, c := range containerStatuses {
39+
result[i] = ContainerStatus{
40+
Name: c.Name,
41+
State: toContainerState(c.State),
42+
Ready: c.Ready,
43+
}
44+
}
45+
46+
return result
47+
}
48+
49+
func toContainerState(state v1.ContainerState) ContainerState {
50+
if state.Waiting != nil {
51+
return Waiting
52+
}
53+
54+
if state.Terminated != nil {
55+
return Terminated
56+
}
57+
58+
if state.Running != nil {
59+
return Running
60+
}
61+
62+
return Unknown
63+
}

modules/api/pkg/resource/pod/list.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ type Pod struct {
7373

7474
// ContainerImages holds a list of the Pod images.
7575
ContainerImages []string `json:"containerImages"`
76+
77+
ContainerStatuses []ContainerStatus `json:"containerStatuses"`
7678
}
7779

7880
var EmptyPodList = &PodList{
@@ -155,13 +157,14 @@ func ToPodList(pods []v1.Pod, events []v1.Event, nonCriticalErrors []error, dsQu
155157

156158
func toPod(pod *v1.Pod, metrics *MetricsByPod, warnings []common.Event) Pod {
157159
podDetail := Pod{
158-
ObjectMeta: types.NewObjectMeta(pod.ObjectMeta),
159-
TypeMeta: types.NewTypeMeta(types.ResourceKindPod),
160-
Warnings: warnings,
161-
Status: getPodStatus(*pod),
162-
RestartCount: getRestartCount(*pod),
163-
NodeName: pod.Spec.NodeName,
164-
ContainerImages: common.GetContainerImages(&pod.Spec),
160+
ObjectMeta: types.NewObjectMeta(pod.ObjectMeta),
161+
TypeMeta: types.NewTypeMeta(types.ResourceKindPod),
162+
Warnings: warnings,
163+
Status: getPodStatus(*pod),
164+
RestartCount: getRestartCount(*pod),
165+
NodeName: pod.Spec.NodeName,
166+
ContainerImages: common.GetContainerImages(&pod.Spec),
167+
ContainerStatuses: ToContainerStatuses(append(pod.Status.InitContainerStatuses, pod.Status.ContainerStatuses...)),
165168
}
166169

167170
if m, exists := metrics.MetricsMap[pod.UID]; exists {

modules/api/pkg/resource/pod/list_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,9 @@ func TestGetPodListFromChannels(t *testing.T) {
102102
Labels: map[string]string{"key": "value"},
103103
CreationTimestamp: metav1.Unix(111, 222),
104104
},
105-
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
106-
Warnings: []common.Event{},
105+
TypeMeta: types.TypeMeta{Kind: types.ResourceKindPod},
106+
Warnings: []common.Event{},
107+
ContainerStatuses: make([]pod.ContainerStatus, 0),
107108
}},
108109
Errors: []error{},
109110
},

0 commit comments

Comments
 (0)