Browse code

oc status must show monopods

Fabiano Franz authored on 2016/03/18 23:24:43
Showing 4 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,39 @@
0
+package graphview
1
+
2
+import (
3
+	osgraph "github.com/openshift/origin/pkg/api/graph"
4
+	kubegraph "github.com/openshift/origin/pkg/api/kubegraph/nodes"
5
+)
6
+
7
+type Pod struct {
8
+	Pod *kubegraph.PodNode
9
+}
10
+
11
+// AllPods returns all Pods and the set of covered NodeIDs
12
+func AllPods(g osgraph.Graph, excludeNodeIDs IntSet) ([]Pod, IntSet) {
13
+	covered := IntSet{}
14
+	pods := []Pod{}
15
+
16
+	for _, uncastNode := range g.NodesByKind(kubegraph.PodNodeKind) {
17
+		if excludeNodeIDs.Has(uncastNode.ID()) {
18
+			continue
19
+		}
20
+
21
+		pod, covers := NewPod(g, uncastNode.(*kubegraph.PodNode))
22
+		covered.Insert(covers.List()...)
23
+		pods = append(pods, pod)
24
+	}
25
+
26
+	return pods, covered
27
+}
28
+
29
+// NewPod returns the Pod and a set of all the NodeIDs covered by the Pod
30
+func NewPod(g osgraph.Graph, podNode *kubegraph.PodNode) (Pod, IntSet) {
31
+	covered := IntSet{}
32
+	covered.Insert(podNode.ID())
33
+
34
+	podView := Pod{}
35
+	podView.Pod = podNode
36
+
37
+	return podView, covered
38
+}
... ...
@@ -97,6 +97,11 @@ func NewServiceGroup(g osgraph.Graph, serviceNode *kubegraph.ServiceNode) (Servi
97 97
 		service.ReplicationControllers = append(service.ReplicationControllers, rcView)
98 98
 	}
99 99
 
100
+	for _, fulfillingPod := range service.FulfillingPods {
101
+		_, podCovers := NewPod(g, fulfillingPod)
102
+		covered.Insert(podCovers.List()...)
103
+	}
104
+
100 105
 	return service, covered
101 106
 }
102 107
 
... ...
@@ -152,6 +152,9 @@ func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error
152 152
 	standaloneImages, coveredByImages := graphview.AllImagePipelinesFromBuildConfig(g, coveredNodes)
153 153
 	coveredNodes.Insert(coveredByImages.List()...)
154 154
 
155
+	standalonePods, coveredByPods := graphview.AllPods(g, coveredNodes)
156
+	coveredNodes.Insert(coveredByPods.List()...)
157
+
155 158
 	return tabbedString(func(out *tabwriter.Writer) error {
156 159
 		indent := "  "
157 160
 		if allNamespaces {
... ...
@@ -218,6 +221,15 @@ func (d *ProjectStatusDescriber) Describe(namespace, name string) (string, error
218 218
 			printLines(out, indent, 0, describeRCInServiceGroup(f, standaloneRC.RC)...)
219 219
 		}
220 220
 
221
+		monopods, err := filterBoringPods(standalonePods)
222
+		if err != nil {
223
+			return err
224
+		}
225
+		for _, monopod := range monopods {
226
+			fmt.Fprintln(out)
227
+			printLines(out, indent, 0, describeMonopod(f, monopod.Pod)...)
228
+		}
229
+
221 230
 		allMarkers := osgraph.Markers{}
222 231
 		allMarkers = append(allMarkers, createForbiddenMarkers(forbiddenResources)...)
223 232
 		for _, scanner := range getMarkerScanners(d.LogsCommandName, d.SecurityPolicyCommandFormat, d.SetProbeCommandName) {
... ...
@@ -502,6 +514,16 @@ func describePodInServiceGroup(f formatter, podNode *kubegraph.PodNode) []string
502 502
 	return lines
503 503
 }
504 504
 
505
+func describeMonopod(f formatter, podNode *kubegraph.PodNode) []string {
506
+	images := []string{}
507
+	for _, container := range podNode.Pod.Spec.Containers {
508
+		images = append(images, container.Image)
509
+	}
510
+
511
+	lines := []string{fmt.Sprintf("%s runs %s", f.ResourceName(podNode), strings.Join(images, ", "))}
512
+	return lines
513
+}
514
+
505 515
 // exposedRoutes orders strings by their leading prefix (https:// -> http:// other prefixes), then by
506 516
 // the shortest distance up to the first space (indicating a break), then alphabetically:
507 517
 //
... ...
@@ -1044,6 +1066,30 @@ func describeServicePorts(spec kapi.ServiceSpec) string {
1044 1044
 	}
1045 1045
 }
1046 1046
 
1047
+func filterBoringPods(pods []graphview.Pod) ([]graphview.Pod, error) {
1048
+	monopods := []graphview.Pod{}
1049
+
1050
+	for _, pod := range pods {
1051
+		actualPod, ok := pod.Pod.Object().(*kapi.Pod)
1052
+		if !ok {
1053
+			continue
1054
+		}
1055
+		meta, err := kapi.ObjectMetaFor(actualPod)
1056
+		if err != nil {
1057
+			return nil, err
1058
+		}
1059
+		_, isDeployerPod := meta.Labels[deployapi.DeployerPodForDeploymentLabel]
1060
+		_, isBuilderPod := meta.Annotations[buildapi.BuildAnnotation]
1061
+		isFinished := actualPod.Status.Phase == kapi.PodSucceeded || actualPod.Status.Phase == kapi.PodFailed
1062
+		if isDeployerPod || isBuilderPod || isFinished {
1063
+			continue
1064
+		}
1065
+		monopods = append(monopods, pod)
1066
+	}
1067
+
1068
+	return monopods, nil
1069
+}
1070
+
1047 1071
 // GraphLoader is a stateful interface that provides methods for building the nodes of a graph
1048 1072
 type GraphLoader interface {
1049 1073
 	// Load is responsible for gathering and saving the objects this GraphLoader should AddToGraph
... ...
@@ -293,6 +293,20 @@ func TestProjectStatus(t *testing.T) {
293 293
 				`View details with 'oc describe <resource>/<name>' or list everything with 'oc get all'.`,
294 294
 			},
295 295
 		},
296
+		"monopod": {
297
+			Path: "../../../../test/fixtures/app-scenarios/k8s-lonely-pod.json",
298
+			Extra: []runtime.Object{
299
+				&projectapi.Project{
300
+					ObjectMeta: kapi.ObjectMeta{Name: "example", Namespace: ""},
301
+				},
302
+			},
303
+			ErrFn: func(err error) bool { return err == nil },
304
+			Contains: []string{
305
+				"In project example on server https://example.com:8443\n",
306
+				"pod/lonely-pod runs openshift/hello-openshift",
307
+				"You have no services, deployment configs, or build configs.",
308
+			},
309
+		},
296 310
 	}
297 311
 	oldTimeFn := timeNowFn
298 312
 	defer func() { timeNowFn = oldTimeFn }()