@@ -158,12 +158,19 @@ func GetReplicationControllerDetail(client client.Interface, heapsterClient Heap
158
158
159
159
matchingServices := getMatchingServices (services .Items , replicationController )
160
160
161
+ // Anonymous callback function to get nodes by their names.
162
+ getNodeFn := func (nodeName string ) (* api.Node , error ) {
163
+ return client .Nodes ().Get (nodeName )
164
+ }
165
+
161
166
for _ , service := range matchingServices {
162
- replicationControllerDetail .Services = append (replicationControllerDetail .Services , getServiceDetail (service ))
167
+ replicationControllerDetail .Services = append (replicationControllerDetail .Services ,
168
+ getServiceDetail (service , * replicationController , pods .Items , getNodeFn ))
163
169
}
164
170
165
171
for _ , container := range replicationController .Spec .Template .Spec .Containers {
166
- replicationControllerDetail .ContainerImages = append (replicationControllerDetail .ContainerImages , container .Image )
172
+ replicationControllerDetail .ContainerImages = append (replicationControllerDetail .ContainerImages ,
173
+ container .Image )
167
174
}
168
175
169
176
for _ , pod := range pods .Items {
@@ -277,22 +284,15 @@ func UpdateReplicasCount(client client.Interface, namespace, name string,
277
284
}
278
285
279
286
// Returns detailed information about service from given service
280
- func getServiceDetail (service api.Service ) ServiceDetail {
281
- var externalEndpoints []Endpoint
282
- for _ , externalIp := range service .Status .LoadBalancer .Ingress {
283
- externalEndpoints = append (externalEndpoints ,
284
- getExternalEndpoint (externalIp , service .Spec .Ports ))
285
- }
286
-
287
- serviceDetail := ServiceDetail {
287
+ func getServiceDetail (service api.Service , replicationController api.ReplicationController ,
288
+ pods []api.Pod , getNodeFn GetNodeFunc ) ServiceDetail {
289
+ return ServiceDetail {
288
290
Name : service .ObjectMeta .Name ,
289
291
InternalEndpoint : getInternalEndpoint (service .Name , service .Namespace ,
290
292
service .Spec .Ports ),
291
- ExternalEndpoints : externalEndpoints ,
293
+ ExternalEndpoints : getExternalEndpoints ( replicationController , pods , service , getNodeFn ) ,
292
294
Selector : service .Spec .Selector ,
293
295
}
294
-
295
- return serviceDetail
296
296
}
297
297
298
298
// Gets restart count of given pod (total number of its containers restarts).
@@ -322,6 +322,82 @@ func getInternalEndpoint(serviceName, namespace string, ports []api.ServicePort)
322
322
}
323
323
}
324
324
325
+ // Returns array of external endpoints for a replication controller.
326
+ func getExternalEndpoints (replicationController api.ReplicationController , pods []api.Pod ,
327
+ service api.Service , getNodeFn GetNodeFunc ) []Endpoint {
328
+ var externalEndpoints []Endpoint
329
+ replicationControllerPods := filterReplicationControllerPods (replicationController , pods )
330
+
331
+ if service .Spec .Type == api .ServiceTypeNodePort {
332
+ externalEndpoints = getNodePortEndpoints (replicationControllerPods , service , getNodeFn )
333
+ }
334
+
335
+ if service .Spec .Type == api .ServiceTypeLoadBalancer {
336
+ for _ , ingress := range service .Status .LoadBalancer .Ingress {
337
+ externalEndpoints = append (externalEndpoints , getExternalEndpoint (ingress ,
338
+ service .Spec .Ports ))
339
+ }
340
+
341
+ if len (externalEndpoints ) == 0 {
342
+ externalEndpoints = getNodePortEndpoints (replicationControllerPods , service , getNodeFn )
343
+ }
344
+ }
345
+
346
+ return externalEndpoints
347
+ }
348
+
349
+ // Returns pods that belong to specified replication controller.
350
+ func filterReplicationControllerPods (replicationController api.ReplicationController ,
351
+ allPods []api.Pod ) []api.Pod {
352
+ var pods []api.Pod
353
+ for _ , pod := range allPods {
354
+ if isLabelSelectorMatching (replicationController .Spec .Selector , pod .Labels ) {
355
+ pods = append (pods , pod )
356
+ }
357
+ }
358
+ return pods
359
+ }
360
+
361
+ // Returns array of external endpoints for specified pods.
362
+ func getNodePortEndpoints (pods []api.Pod , service api.Service , getNodeFn GetNodeFunc ) []Endpoint {
363
+ var externalEndpoints []Endpoint
364
+ var externalIPs []string
365
+ for _ , pod := range pods {
366
+ node , err := getNodeFn (pod .Spec .NodeName )
367
+ if err != nil {
368
+ continue
369
+ }
370
+ for _ , adress := range node .Status .Addresses {
371
+ if adress .Type == api .NodeExternalIP && len (adress .Address ) > 0 &&
372
+ isExternalIPUniqe (externalIPs , adress .Address ) {
373
+ externalIPs = append (externalIPs , adress .Address )
374
+ for _ , port := range service .Spec .Ports {
375
+ externalEndpoints = append (externalEndpoints , Endpoint {
376
+ Host : adress .Address ,
377
+ Ports : []ServicePort {
378
+ {
379
+ Protocol : port .Protocol ,
380
+ Port : port .NodePort ,
381
+ },
382
+ },
383
+ })
384
+ }
385
+ }
386
+ }
387
+ }
388
+ return externalEndpoints
389
+ }
390
+
391
+ // Returns true if given external IP is not part of given array.
392
+ func isExternalIPUniqe (externalIPs []string , externalIP string ) bool {
393
+ for _ , h := range externalIPs {
394
+ if h == externalIP {
395
+ return false
396
+ }
397
+ }
398
+ return true
399
+ }
400
+
325
401
// Returns external endpoint name for the given service properties.
326
402
func getExternalEndpoint (ingress api.LoadBalancerIngress , ports []api.ServicePort ) Endpoint {
327
403
var host string
0 commit comments