Skip to content

Commit c25dd5b

Browse files
committed
Merge pull request #319 from floreks/card-status
Added replica set card status messages
2 parents 340a729 + 68c7c96 commit c25dd5b

15 files changed

+788
-44
lines changed

src/app/backend/deploy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ func DeployApp(spec *AppDeploymentSpec, client client.Interface) error {
159159
Containers: []api.Container{containerSpec},
160160
}
161161
if spec.ImagePullSecret != nil {
162-
podSpec.ImagePullSecrets = []api.LocalObjectReference{api.LocalObjectReference{Name: *spec.ImagePullSecret}}
162+
podSpec.ImagePullSecrets = []api.LocalObjectReference{{Name: *spec.ImagePullSecret}}
163163
}
164164

165165
podTemplate := &api.PodTemplateSpec{

src/app/backend/events.go

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,22 @@ func GetReplicationControllerPodsEvents(client *client.Client, namespace, replic
137137
return nil, err
138138
}
139139

140-
events := make([]api.Event, 0, 0)
140+
events, err := GetPodsEvents(client, pods)
141141

142-
for _, pod := range pods.Items {
143-
fieldSelector, err := fields.ParseSelector("involvedObject.name=" + pod.Name)
142+
if err != nil {
143+
return nil, err
144+
}
144145

145-
if err != nil {
146-
return nil, err
147-
}
146+
return events, nil
147+
}
148148

149-
list, err := client.Events(namespace).List(unversioned.ListOptions{
150-
LabelSelector: unversioned.LabelSelector{labels.Everything()},
151-
FieldSelector: unversioned.FieldSelector{fieldSelector},
152-
})
149+
// Gets events associated to given list of pods
150+
// TODO(floreks): refactor this to make single API call instead of N api calls
151+
func GetPodsEvents(client *client.Client, pods *api.PodList) ([]api.Event, error) {
152+
events := make([]api.Event, 0, 0)
153+
154+
for _, pod := range pods.Items {
155+
list, err := GetPodEvents(client, pod)
153156

154157
if err != nil {
155158
return nil, err
@@ -164,6 +167,26 @@ func GetReplicationControllerPodsEvents(client *client.Client, namespace, replic
164167
return events, nil
165168
}
166169

170+
// Gets events associated to given pod
171+
func GetPodEvents(client client.Interface, pod api.Pod) (*api.EventList, error) {
172+
fieldSelector, err := fields.ParseSelector("involvedObject.name=" + pod.Name)
173+
174+
if err != nil {
175+
return nil, err
176+
}
177+
178+
list, err := client.Events(pod.Namespace).List(unversioned.ListOptions{
179+
LabelSelector: unversioned.LabelSelector{labels.Everything()},
180+
FieldSelector: unversioned.FieldSelector{fieldSelector},
181+
})
182+
183+
if err != nil {
184+
return nil, err
185+
}
186+
187+
return list, nil
188+
}
189+
167190
// Appends events from source slice to target events representation.
168191
func AppendEvents(source []api.Event, target Events) Events {
169192
for _, event := range source {

src/app/backend/eventscommon.go

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
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 main
16+
17+
import (
18+
"k8s.io/kubernetes/pkg/api"
19+
client "k8s.io/kubernetes/pkg/client/unversioned"
20+
"log"
21+
"strings"
22+
)
23+
24+
// Partial string to correctly filter warning events.
25+
// Has to be lower case for correct case insensitive comparison.
26+
const FAILED_REASON_PARTIAL = "failed"
27+
28+
// Contains basic information about event related to a pod
29+
type PodEvent struct {
30+
// Short, machine understandable string that gives the reason
31+
// for this event being generated.
32+
Reason string `json:"reason"`
33+
34+
// A human-readable description of the status of related pod.
35+
Message string `json:"message"`
36+
}
37+
38+
// Returns warning pod events based on given list of pods.
39+
// TODO(floreks) : Import and use Set instead of custom function to get rid of duplicates
40+
func GetPodsEventWarnings(client client.Interface, pods []api.Pod) (result []PodEvent, err error) {
41+
for _, pod := range pods {
42+
if !isRunningOrSucceeded(pod) {
43+
log.Printf("Getting warning events from pod: %s", pod.Name)
44+
events, err := GetPodEvents(client, pod)
45+
46+
if err != nil {
47+
return nil, err
48+
}
49+
50+
result = getPodsEventWarnings(events)
51+
}
52+
}
53+
54+
return removeDuplicates(result), nil
55+
}
56+
57+
// Returns list of Pod Event model objects based on kubernetes API event list object
58+
// Event list object is filtered to get only warning events.
59+
func getPodsEventWarnings(eventList *api.EventList) []PodEvent {
60+
result := make([]PodEvent, 0)
61+
62+
var events []api.Event
63+
if isTypeFilled(eventList.Items) {
64+
events = filterEventsByType(eventList.Items, api.EventTypeWarning)
65+
} else {
66+
events = filterEventsByReason(eventList.Items, FAILED_REASON_PARTIAL)
67+
}
68+
69+
for _, event := range events {
70+
result = append(result, PodEvent{
71+
Message: event.Message,
72+
Reason: event.Reason,
73+
})
74+
}
75+
76+
return result
77+
}
78+
79+
// Filters kubernetes API event objects based on event type.
80+
// Empty string will return all events.
81+
func filterEventsByType(events []api.Event, eventType string) []api.Event {
82+
if len(eventType) == 0 || len(events) == 0 {
83+
return events
84+
}
85+
86+
result := make([]api.Event, 0)
87+
for _, event := range events {
88+
if event.Type == eventType {
89+
result = append(result, event)
90+
}
91+
}
92+
93+
return result
94+
}
95+
96+
// Filters kubernetes API event objects based on reason property.
97+
// Empty string will return all events.
98+
func filterEventsByReason(events []api.Event, partial string) []api.Event {
99+
if len(partial) == 0 || len(events) == 0 {
100+
return events
101+
}
102+
103+
result := make([]api.Event, 0)
104+
for _, event := range events {
105+
if strings.Contains(strings.ToLower(event.Reason), partial) {
106+
result = append(result, event)
107+
}
108+
}
109+
110+
return result
111+
}
112+
113+
// Returns true if all given events type is filled, false otherwise.
114+
// This is needed as some older versions of kubernetes do not have Type property filled.
115+
func isTypeFilled(events []api.Event) bool {
116+
if len(events) == 0 {
117+
return false
118+
}
119+
120+
for _, event := range events {
121+
if len(event.Type) == 0 {
122+
return false
123+
}
124+
}
125+
126+
return true
127+
}
128+
129+
// Removes duplicate strings from the slice
130+
func removeDuplicates(slice []PodEvent) []PodEvent {
131+
visited := make(map[string]bool, 0)
132+
result := make([]PodEvent, 0)
133+
134+
for _, elem := range slice {
135+
if !visited[elem.Reason] {
136+
visited[elem.Reason] = true
137+
result = append(result, elem)
138+
}
139+
}
140+
141+
return result
142+
}
143+
144+
// Returns true if given pod is in state running or succeeded, false otherwise
145+
func isRunningOrSucceeded(pod api.Pod) bool {
146+
switch pod.Status.Phase {
147+
case api.PodRunning, api.PodSucceeded:
148+
return true
149+
}
150+
151+
return false
152+
}

src/app/backend/replicationcontrollercommon.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424

2525
type ReplicationControllerWithPods struct {
2626
ReplicationController *api.ReplicationController
27-
Pods *api.PodList
27+
Pods *api.PodList
2828
}
2929

3030
// ReplicationControllerPodInfo represents aggregate information about replication controller pods.
@@ -43,6 +43,9 @@ type ReplicationControllerPodInfo struct {
4343

4444
// Number of pods that are failed.
4545
Failed int `json:"failed"`
46+
47+
// Unique warning messages related to pods in this Replication Controller.
48+
Warnings []PodEvent `json:"warnings"`
4649
}
4750

4851
// Returns structure containing ReplicationController and Pods for the given replication controller.
@@ -66,7 +69,7 @@ func getRawReplicationControllerWithPods(client client.Interface, namespace, nam
6669

6770
replicationControllerAndPods := &ReplicationControllerWithPods{
6871
ReplicationController: replicationController,
69-
Pods: pods,
72+
Pods: pods,
7073
}
7174
return replicationControllerAndPods, nil
7275
}

src/app/backend/replicationcontrollerlist.go

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ import (
2424
"k8s.io/kubernetes/pkg/labels"
2525
)
2626

27+
// Callback function in order to get the pod status errors
28+
type GetPodsEventWarningsFunc func(pods []api.Pod) ([]PodEvent, error)
29+
2730
// ReplicationControllerList contains a list of Replication Controllers in the cluster.
2831
type ReplicationControllerList struct {
2932
// Unordered list of Replication Controllers.
@@ -45,7 +48,7 @@ type ReplicationController struct {
4548
// Label of this Replication Controller.
4649
Labels map[string]string `json:"labels"`
4750

48-
// Aggergate information about pods belonging to this repolica set.
51+
// Aggregate information about pods belonging to this repolica set.
4952
Pods ReplicationControllerPodInfo `json:"pods"`
5053

5154
// Container images of the Replication Controller.
@@ -88,14 +91,34 @@ func GetReplicationControllerList(client *client.Client) (*ReplicationController
8891
return nil, err
8992
}
9093

91-
return getReplicationControllerList(replicationControllers.Items, services.Items, pods.Items), nil
94+
// Anonymous callback function to get pods warnings.
95+
// Function fulfils GetPodsEventWarningsFunc type contract.
96+
// Based on list of api pods returns list of pod related warning events
97+
getPodsEventWarningsFn := func(pods []api.Pod) ([]PodEvent, error) {
98+
errors, err := GetPodsEventWarnings(client, pods)
99+
100+
if err != nil {
101+
return nil, err
102+
}
103+
104+
return errors, nil
105+
}
106+
107+
result, err := getReplicationControllerList(replicationControllers.Items, services.Items, pods.Items, getPodsEventWarningsFn)
108+
109+
if err != nil {
110+
return nil, err
111+
}
112+
113+
return result, nil
92114
}
93115

94116
// Returns a list of all Replication Controller model objects in the cluster, based on all Kubernetes
95117
// Replication Controller and Service API objects.
96118
// The function processes all Replication Controllers API objects and finds matching Services for them.
97-
func getReplicationControllerList(replicationControllers []api.ReplicationController, services []api.Service,
98-
pods []api.Pod) *ReplicationControllerList {
119+
func getReplicationControllerList(replicationControllers []api.ReplicationController,
120+
services []api.Service, pods []api.Pod, getPodsEventWarningsFn GetPodsEventWarningsFunc) (
121+
*ReplicationControllerList, error) {
99122

100123
replicationControllerList := &ReplicationControllerList{ReplicationControllers: make([]ReplicationController, 0)}
101124

@@ -125,6 +148,13 @@ func getReplicationControllerList(replicationControllers []api.ReplicationContro
125148
}
126149
}
127150
podInfo := getReplicationControllerPodInfo(&replicationController, matchingPods)
151+
podErrors, err := getPodsEventWarningsFn(matchingPods)
152+
153+
if err != nil {
154+
return nil, err
155+
}
156+
157+
podInfo.Warnings = podErrors
128158

129159
replicationControllerList.ReplicationControllers = append(replicationControllerList.ReplicationControllers, ReplicationController{
130160
Name: replicationController.ObjectMeta.Name,
@@ -139,7 +169,7 @@ func getReplicationControllerList(replicationControllers []api.ReplicationContro
139169
})
140170
}
141171

142-
return replicationControllerList
172+
return replicationControllerList, nil
143173
}
144174

145175
// Returns all services that target the same Pods (or subset) as the given Replication Controller.

src/app/externs/backendapi.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,22 @@ backendApi.Event;
9898
*/
9999
backendApi.ReplicationControllerList;
100100

101+
/**
102+
* @typedef {{
103+
* reason: string,
104+
* message: string
105+
* }}
106+
*/
107+
backendApi.PodEvent;
108+
101109
/**
102110
* @typedef {{
103111
* current: number,
104112
* desired: number,
105113
* running: number,
106114
* pending: number,
107-
* failed: number
115+
* failed: number,
116+
* warnings: !Array<!backendApi.PodEvent>
108117
* }}
109118
*/
110119
backendApi.ReplicationControllerPodInfo;

0 commit comments

Comments
 (0)