Skip to content

Commit 8af7465

Browse files
committed
Merge pull request #320 from maciaszczykm/external-links
External links handling
2 parents 8e0d7e1 + b54f6a2 commit 8af7465

File tree

5 files changed

+389
-34
lines changed

5 files changed

+389
-34
lines changed

src/app/backend/deploy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func DeployApp(spec *AppDeploymentSpec, client client.Interface) error {
208208
if spec.IsExternal {
209209
service.Spec.Type = api.ServiceTypeLoadBalancer
210210
} else {
211-
service.Spec.Type = api.ServiceTypeNodePort
211+
service.Spec.Type = api.ServiceTypeClusterIP
212212
}
213213

214214
for _, portMapping := range spec.PortMappings {

src/app/backend/replicationcontrollerdetail.go

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,19 @@ func GetReplicationControllerDetail(client client.Interface, heapsterClient Heap
158158

159159
matchingServices := getMatchingServices(services.Items, replicationController)
160160

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+
161166
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))
163169
}
164170

165171
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)
167174
}
168175

169176
for _, pod := range pods.Items {
@@ -277,22 +284,15 @@ func UpdateReplicasCount(client client.Interface, namespace, name string,
277284
}
278285

279286
// 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{
288290
Name: service.ObjectMeta.Name,
289291
InternalEndpoint: getInternalEndpoint(service.Name, service.Namespace,
290292
service.Spec.Ports),
291-
ExternalEndpoints: externalEndpoints,
293+
ExternalEndpoints: getExternalEndpoints(replicationController, pods, service, getNodeFn),
292294
Selector: service.Spec.Selector,
293295
}
294-
295-
return serviceDetail
296296
}
297297

298298
// Gets restart count of given pod (total number of its containers restarts).
@@ -322,6 +322,82 @@ func getInternalEndpoint(serviceName, namespace string, ports []api.ServicePort)
322322
}
323323
}
324324

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+
325401
// Returns external endpoint name for the given service properties.
326402
func getExternalEndpoint(ingress api.LoadBalancerIngress, ports []api.ServicePort) Endpoint {
327403
var host string

src/app/backend/replicationcontrollerlist.go

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ import (
2727
// Callback function in order to get the pod status errors
2828
type GetPodsEventWarningsFunc func(pods []api.Pod) ([]PodEvent, error)
2929

30+
// Callback function in order to get node by name.
31+
type GetNodeFunc func(nodeName string) (*api.Node, error)
32+
3033
// ReplicationControllerList contains a list of Replication Controllers in the cluster.
3134
type ReplicationControllerList struct {
3235
// Unordered list of Replication Controllers.
@@ -104,7 +107,13 @@ func GetReplicationControllerList(client *client.Client) (*ReplicationController
104107
return errors, nil
105108
}
106109

107-
result, err := getReplicationControllerList(replicationControllers.Items, services.Items, pods.Items, getPodsEventWarningsFn)
110+
// Anonymous callback function to get nodes by their names.
111+
getNodeFn := func(nodeName string) (*api.Node, error) {
112+
return client.Nodes().Get(nodeName)
113+
}
114+
115+
result, err := getReplicationControllerList(replicationControllers.Items, services.Items,
116+
pods.Items, getPodsEventWarningsFn, getNodeFn)
108117

109118
if err != nil {
110119
return nil, err
@@ -117,8 +126,8 @@ func GetReplicationControllerList(client *client.Client) (*ReplicationController
117126
// Replication Controller and Service API objects.
118127
// The function processes all Replication Controllers API objects and finds matching Services for them.
119128
func getReplicationControllerList(replicationControllers []api.ReplicationController,
120-
services []api.Service, pods []api.Pod, getPodsEventWarningsFn GetPodsEventWarningsFunc) (
121-
*ReplicationControllerList, error) {
129+
services []api.Service, pods []api.Pod, getPodsEventWarningsFn GetPodsEventWarningsFunc,
130+
getNodeFn GetNodeFunc) (*ReplicationControllerList, error) {
122131

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

@@ -134,10 +143,8 @@ func getReplicationControllerList(replicationControllers []api.ReplicationContro
134143
for _, service := range matchingServices {
135144
internalEndpoints = append(internalEndpoints,
136145
getInternalEndpoint(service.Name, service.Namespace, service.Spec.Ports))
137-
for _, externalIP := range service.Status.LoadBalancer.Ingress {
138-
externalEndpoints = append(externalEndpoints,
139-
getExternalEndpoint(externalIP, service.Spec.Ports))
140-
}
146+
externalEndpoints = getExternalEndpoints(replicationController, pods, service,
147+
getNodeFn)
141148
}
142149

143150
matchingPods := make([]api.Pod, 0)
@@ -156,17 +163,18 @@ func getReplicationControllerList(replicationControllers []api.ReplicationContro
156163

157164
podInfo.Warnings = podErrors
158165

159-
replicationControllerList.ReplicationControllers = append(replicationControllerList.ReplicationControllers, ReplicationController{
160-
Name: replicationController.ObjectMeta.Name,
161-
Namespace: replicationController.ObjectMeta.Namespace,
162-
Description: replicationController.Annotations[DescriptionAnnotationKey],
163-
Labels: replicationController.ObjectMeta.Labels,
164-
Pods: podInfo,
165-
ContainerImages: containerImages,
166-
CreationTime: replicationController.ObjectMeta.CreationTimestamp,
167-
InternalEndpoints: internalEndpoints,
168-
ExternalEndpoints: externalEndpoints,
169-
})
166+
replicationControllerList.ReplicationControllers = append(replicationControllerList.ReplicationControllers,
167+
ReplicationController{
168+
Name: replicationController.ObjectMeta.Name,
169+
Namespace: replicationController.ObjectMeta.Namespace,
170+
Description: replicationController.Annotations[DescriptionAnnotationKey],
171+
Labels: replicationController.ObjectMeta.Labels,
172+
Pods: podInfo,
173+
ContainerImages: containerImages,
174+
CreationTime: replicationController.ObjectMeta.CreationTimestamp,
175+
InternalEndpoints: internalEndpoints,
176+
ExternalEndpoints: externalEndpoints,
177+
})
170178
}
171179

172180
return replicationControllerList, nil

0 commit comments

Comments
 (0)