Skip to content

Commit 7a68617

Browse files
Sebastian FlorekSebastian Florek
authored andcommitted
Add pet set detail page (#805)
1 parent bc3c542 commit 7a68617

21 files changed

+693
-10
lines changed

i18n/messages-en.xtb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,15 @@
144144
<translation id="5143266087600531180" key="MSG_NAMESPACE_SELECT_ARIA_LABEL" source="/usr/local/google/home/bryk/src/github.com/dashboard/.tmp/serve/app-dev.js" desc="Text describing what namespace selector is">Selector for namespaces</translation>
145145
<translation id="7612562063769289643" key="MSG_PODS_ARE_FAILED_TOOLTIP" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="tooltip for failed pod card icon">One or more pods have errors.</translation>
146146
<translation id="7471636163011126552" key="MSG_PODS_ARE_PENDING_TOOLTIP" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="tooltip for pending pod card icon">One or more pods are in pending state.</translation>
147+
<translation id="5059203627384479637" key="MSG_PET_SET_DETAIL_OVERVIEW_TAB" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Overview tab label on the pet set detail page.">Overview</translation>
148+
<translation id="6998996832659188031" key="MSG_PET_SET_DETAIL_PODS_CARD_TITLE" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Related pods card title on the pet set detail page.">Pods</translation>
149+
<translation id="8707615799932704635" key="MSG_PET_SET_DETAIL_EVENTS_TAB" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Events tab label on the pet set detail page.">Events</translation>
150+
<translation id="1061534452415111025" key="MSG_PET_SET_INFO_DETAILS_SECTION" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section name.">Details</translation>
151+
<translation id="5246158437544347926" key="MSG_PET_SET_INFO_NAME_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section name entry.">Name</translation>
152+
<translation id="1965909741930893667" key="MSG_PET_SET_INFO_NAMESPACE_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section namespace entry.">Namespace</translation>
153+
<translation id="6096611116725653973" key="MSG_PET_SET_INFO_LABELS_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section labels entry.">Labels</translation>
154+
<translation id="1079594048788916996" key="MSG_PET_SET_INFO_IMAGES_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section images entry.">Images</translation>
155+
<translation id="3762856444030194375" key="MSG_PET_SET_INFO_STATUS_SECTION" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info status section name.">Status</translation>
156+
<translation id="1744330140020758003" key="MSG_PET_SET_INFO_PODS_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info status section pods entry.">Pods</translation>
157+
<translation id="6654869080140416303" key="MSG_PET_SET_INFO_PODS_STATUS_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info status section pods status entry.">Pods status</translation>
147158
</translationbundle>

i18n/messages-ja.xtb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,15 @@
144144
<translation id="5143266087600531180" key="MSG_NAMESPACE_SELECT_ARIA_LABEL" source="/usr/local/google/home/bryk/src/github.com/dashboard/.tmp/serve/app-dev.js" desc="Text describing what namespace selector is">Selector for namespaces</translation>
145145
<translation id="7612562063769289643" key="MSG_PODS_ARE_FAILED_TOOLTIP" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="tooltip for failed pod card icon">One or more pods have errors.</translation>
146146
<translation id="7471636163011126552" key="MSG_PODS_ARE_PENDING_TOOLTIP" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="tooltip for pending pod card icon">One or more pods are in pending state.</translation>
147+
<translation id="5059203627384479637" key="MSG_PET_SET_DETAIL_OVERVIEW_TAB" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Overview tab label on the pet set detail page.">Overview</translation>
148+
<translation id="6998996832659188031" key="MSG_PET_SET_DETAIL_PODS_CARD_TITLE" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Related pods card title on the pet set detail page.">Pods</translation>
149+
<translation id="8707615799932704635" key="MSG_PET_SET_DETAIL_EVENTS_TAB" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Events tab label on the pet set detail page.">Events</translation>
150+
<translation id="1061534452415111025" key="MSG_PET_SET_INFO_DETAILS_SECTION" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section name.">Details</translation>
151+
<translation id="5246158437544347926" key="MSG_PET_SET_INFO_NAME_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section name entry.">Name</translation>
152+
<translation id="1965909741930893667" key="MSG_PET_SET_INFO_NAMESPACE_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section namespace entry.">Namespace</translation>
153+
<translation id="6096611116725653973" key="MSG_PET_SET_INFO_LABELS_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section labels entry.">Labels</translation>
154+
<translation id="1079594048788916996" key="MSG_PET_SET_INFO_IMAGES_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info details section images entry.">Images</translation>
155+
<translation id="3762856444030194375" key="MSG_PET_SET_INFO_STATUS_SECTION" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info status section name.">Status</translation>
156+
<translation id="1744330140020758003" key="MSG_PET_SET_INFO_PODS_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info status section pods entry.">Pods</translation>
157+
<translation id="6654869080140416303" key="MSG_PET_SET_INFO_PODS_STATUS_ENTRY" source="/home/floreks/Projects/dashboard/.tmp/serve/app-dev.js" desc="Pet set info status section pods status entry.">Pods status</translation>
147158
</translationbundle>

src/app/backend/handler/apihandler.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,15 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient,
282282
apiV1Ws.Route(
283283
apiV1Ws.GET("/petset").
284284
To(apiHandler.handleGetPetSetList).
285-
Writes(resourceService.ServiceList{}))
285+
Writes(petset.PetSetList{}))
286286
apiV1Ws.Route(
287287
apiV1Ws.GET("/petset/{namespace}").
288288
To(apiHandler.handleGetPetSetList).
289-
Writes(resourceService.ServiceList{}))
289+
Writes(petset.PetSetList{}))
290+
apiV1Ws.Route(
291+
apiV1Ws.GET("/petset/{namespace}/{petset}").
292+
To(apiHandler.handleGetPetSetDetail).
293+
Writes(petset.PetSetDetail{}))
290294

291295
apiV1Ws.Route(
292296
apiV1Ws.DELETE("/{kind}/namespace/{namespace}/name/{name}").
@@ -308,6 +312,20 @@ func (apiHandler *ApiHandler) handleGetPetSetList(request *restful.Request,
308312
response.WriteHeaderAndEntity(http.StatusCreated, result)
309313
}
310314

315+
// Handles get pet set detail API call.
316+
func (apiHandler *ApiHandler) handleGetPetSetDetail(request *restful.Request,
317+
response *restful.Response) {
318+
namespace := request.PathParameter("namespace")
319+
service := request.PathParameter("petset")
320+
result, err := petset.GetPetSetDetail(apiHandler.client, apiHandler.heapsterClient,
321+
namespace, service)
322+
if err != nil {
323+
handleInternalError(response, err)
324+
return
325+
}
326+
response.WriteHeaderAndEntity(http.StatusCreated, result)
327+
}
328+
311329
// Handles get service list API call.
312330
func (apiHandler *ApiHandler) handleGetServiceList(request *restful.Request, response *restful.Response) {
313331
namespace := parseNamespacePathParameter(request)

src/app/backend/resource/common/pod.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,19 @@ func FilterPodsBySelector(pods []api.Pod, resourceSelector map[string]string) []
4545
return matchingPods
4646
}
4747

48+
func FilterNamespacedPodsByLabelSelector(pods []api.Pod, namespace string,
49+
labelSelector *unversioned.LabelSelector) []api.Pod {
50+
51+
var matchingPods []api.Pod
52+
for _, pod := range pods {
53+
if pod.ObjectMeta.Namespace == namespace &&
54+
IsLabelSelectorMatching(pod.Labels, labelSelector) {
55+
matchingPods = append(matchingPods, pod)
56+
}
57+
}
58+
return matchingPods
59+
}
60+
4861
func FilterPodsByLabelSelector(pods []api.Pod, labelSelector *unversioned.LabelSelector) []api.Pod {
4962

5063
var matchingPods []api.Pod

src/app/backend/resource/common/types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,12 @@ func IsSelectorMatching(labelSelector map[string]string,
151151
return true
152152
}
153153

154-
// Returns true when a resrouce (Service / Pod) with the given selector targets
155-
// the same Pod (or itself) that a Daemon Set with the given selector.
154+
// Returns true when a resource with the given selector targets the same Resources(or subset)
155+
// that a tested object selector with the given selector.
156156
func IsLabelSelectorMatching(selector map[string]string,
157157
labelSelector *unversioned.LabelSelector) bool {
158158

159-
// If the resrouce has no selectors, then assume it targets different Pods.
159+
// If the resource has no selectors, then assume it targets different Pods.
160160
if len(selector) == 0 {
161161
return false
162162
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2015 Google Inc. All Rights Reserved.
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 petset
16+
17+
import (
18+
"log"
19+
20+
"k8s.io/kubernetes/pkg/api"
21+
"k8s.io/kubernetes/pkg/apis/apps"
22+
k8sClient "k8s.io/kubernetes/pkg/client/unversioned"
23+
24+
"github.com/kubernetes/dashboard/client"
25+
"github.com/kubernetes/dashboard/resource/common"
26+
"github.com/kubernetes/dashboard/resource/pod"
27+
)
28+
29+
// PetSetDetail is a presentation layer view of Kubernetes Pet Set resource. This means
30+
// it is Pet Set plus additional augmented data we can get from other sources
31+
// (like services that target the same pods).
32+
type PetSetDetail struct {
33+
ObjectMeta common.ObjectMeta `json:"objectMeta"`
34+
TypeMeta common.TypeMeta `json:"typeMeta"`
35+
36+
// Aggregate information about pods belonging to this Pet Set.
37+
PodInfo common.PodInfo `json:"podInfo"`
38+
39+
// Detailed information about Pods belonging to this Pet Set.
40+
PodList pod.PodList `json:"podList"`
41+
42+
// Container images of the Pet Set.
43+
ContainerImages []string `json:"containerImages"`
44+
45+
// List of events related to this Pet Set.
46+
EventList common.EventList `json:"eventList"`
47+
}
48+
49+
// GetPetSetDetail gets pet set details.
50+
func GetPetSetDetail(client *k8sClient.Client, heapsterClient client.HeapsterClient,
51+
namespace, name string) (*PetSetDetail, error) {
52+
53+
log.Printf("Getting details of %s service in %s namespace", name, namespace)
54+
55+
// TODO(floreks): Use channels.
56+
petSetData, err := client.Apps().PetSets(namespace).Get(name)
57+
if err != nil {
58+
return nil, err
59+
}
60+
61+
channels := &common.ResourceChannels{
62+
PodList: common.GetPodListChannel(client, common.NewSameNamespaceQuery(namespace), 1),
63+
}
64+
65+
pods := <-channels.PodList.List
66+
if err := <-channels.PodList.Error; err != nil {
67+
return nil, err
68+
}
69+
70+
events, err := GetPetSetEvents(client, petSetData.Namespace, petSetData.Name)
71+
if err != nil {
72+
return nil, err
73+
}
74+
75+
petSet := getPetSetDetail(petSetData, heapsterClient, events, pods.Items)
76+
return &petSet, nil
77+
}
78+
79+
func getPetSetDetail(petSet *apps.PetSet, heapsterClient client.HeapsterClient,
80+
events *common.EventList, pods []api.Pod) PetSetDetail {
81+
82+
matchingPods := common.FilterNamespacedPodsByLabelSelector(pods, petSet.ObjectMeta.Namespace,
83+
petSet.Spec.Selector)
84+
85+
podInfo := common.GetPodInfo(int32(petSet.Status.Replicas), int32(petSet.Spec.Replicas),
86+
matchingPods)
87+
88+
return PetSetDetail{
89+
ObjectMeta: common.NewObjectMeta(petSet.ObjectMeta),
90+
TypeMeta: common.NewTypeMeta(common.ResourceKindPetSet),
91+
ContainerImages: common.GetContainerImages(&petSet.Spec.Template.Spec),
92+
PodInfo: podInfo,
93+
PodList: pod.CreatePodList(matchingPods, heapsterClient),
94+
EventList: *events,
95+
}
96+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright 2015 Google Inc. All Rights Reserved.
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 petset
16+
17+
import (
18+
"log"
19+
20+
"github.com/kubernetes/dashboard/resource/common"
21+
"github.com/kubernetes/dashboard/resource/event"
22+
23+
"k8s.io/kubernetes/pkg/api"
24+
client "k8s.io/kubernetes/pkg/client/unversioned"
25+
)
26+
27+
// GetPetSetEvents gets events associated to pet set.
28+
func GetPetSetEvents(client *client.Client, namespace, petSetName string) (
29+
*common.EventList, error) {
30+
31+
log.Printf("Getting events related to %s pet set in %s namespace", petSetName,
32+
namespace)
33+
34+
// Get events for pet set.
35+
rsEvents, err := event.GetEvents(client, namespace, petSetName)
36+
37+
if err != nil {
38+
return nil, err
39+
}
40+
41+
// Get events for pods in pet set.
42+
podEvents, err := GetPetSetPodsEvents(client, namespace, petSetName)
43+
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
apiEvents := append(rsEvents, podEvents...)
49+
50+
if !event.IsTypeFilled(apiEvents) {
51+
apiEvents = event.FillEventsType(apiEvents)
52+
}
53+
54+
events := event.AppendEvents(apiEvents, common.EventList{
55+
Namespace: namespace,
56+
Events: make([]common.Event, 0),
57+
})
58+
59+
log.Printf("Found %d events related to %s pet set in %s namespace",
60+
len(events.Events), petSetName, namespace)
61+
62+
return &events, nil
63+
}
64+
65+
// GetPetSetPodsEvents gets events associated to pods in pet set.
66+
func GetPetSetPodsEvents(client *client.Client, namespace, petSetName string) (
67+
[]api.Event, error) {
68+
69+
petSet, err := client.Apps().PetSets(namespace).Get(petSetName)
70+
71+
if err != nil {
72+
return nil, err
73+
}
74+
75+
podEvents, err := event.GetPodsEvents(client, namespace, petSet.Spec.Selector.MatchLabels)
76+
77+
if err != nil {
78+
return nil, err
79+
}
80+
81+
return podEvents, nil
82+
}

src/app/backend/resource/replicaset/replicasetdetail.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ func GetReplicaSetDetail(client k8sClient.Interface, heapsterClient client.Heaps
7979
func getReplicaSetDetail(replicaSet *extensions.ReplicaSet, heapsterClient client.HeapsterClient,
8080
events *common.EventList, pods []api.Pod) ReplicaSetDetail {
8181

82-
matchingPods := common.FilterNamespacedPodsBySelector(pods, replicaSet.ObjectMeta.Namespace,
83-
replicaSet.Spec.Selector.MatchLabels)
82+
matchingPods := common.FilterNamespacedPodsByLabelSelector(pods, replicaSet.ObjectMeta.Namespace,
83+
replicaSet.Spec.Selector)
8484

8585
podInfo := getPodInfo(replicaSet, matchingPods)
8686

src/app/externs/backendapi.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,23 @@ backendApi.ReplicaSetList;
201201
* objectMeta: !backendApi.ObjectMeta,
202202
* typeMeta: !backendApi.TypeMeta,
203203
* pods: !backendApi.PodInfo,
204-
* containerImages: !Array<string>,
204+
* containerImages: !Array<string>
205205
* }}
206206
*/
207207
backendApi.PetSet;
208208

209+
/**
210+
* @typedef {{
211+
* objectMeta: !backendApi.ObjectMeta,
212+
* typeMeta: !backendApi.TypeMeta,
213+
* podInfo: !backendApi.PodInfo,
214+
* podList: !backendApi.PodList,
215+
* containerImages: !Array<string>,
216+
* eventList: !backendApi.EventList
217+
* }}
218+
*/
219+
backendApi.PetSetDetail;
220+
209221
/**
210222
* @typedef {{
211223
* petSets: !Array<!backendApi.PetSet>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!--
2+
Copyright 2015 Google Inc. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
<div layout="column">
18+
<md-content>
19+
<md-tabs md-border-bottom md-dynamic-height>
20+
<md-tab label="{{::ctrl.i18n.MSG_PET_SET_DETAIL_OVERVIEW_TAB}}">
21+
<kd-pet-set-info pet-set="::ctrl.petSetDetail"></kd-pet-set-info>
22+
23+
<kd-content-card>
24+
<kd-title>{{::ctrl.i18n.MSG_PET_SET_DETAIL_PODS_CARD_TITLE}}</kd-title>
25+
<kd-content>
26+
<kd-pod-card-list pod-list="::ctrl.petSetDetail.podList"
27+
logs-href-fn="::ctrl.getPodLogsHref(pod)" with-statuses="true">
28+
</kd-pod-card-list>
29+
</kd-content>
30+
</kd-content-card>
31+
</md-tab>
32+
<md-tab label="{{::ctrl.i18n.MSG_PET_SET_DETAIL_EVENTS_TAB}}">
33+
<kd-event-card-list events="::ctrl.petSetDetail.eventList.events"></kd-event-card-list>
34+
</md-tab>
35+
</md-tabs>
36+
</md-content>
37+
</div>

0 commit comments

Comments
 (0)