This repository has been archived by the owner on Nov 5, 2019. It is now read-only.
forked from cloudfoundry-incubator/kubo-deployment
-
Notifications
You must be signed in to change notification settings - Fork 4
/
source.go
129 lines (114 loc) · 3.23 KB
/
source.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package kubernetes
import (
"route-sync/route"
"strconv"
k8s "k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/api/v1"
)
type endpoint struct {
clientset k8s.Interface
cfDomain string
}
// New creates a route.Source for a given Kubernetes instance
func NewSource(clientset k8s.Interface, cfDomain string) route.Source {
return &endpoint{clientset: clientset, cfDomain: cfDomain}
}
func (e *endpoint) TCP() ([]*route.TCP, error) {
namespaces, err := e.clientset.CoreV1().Namespaces().List(v1.ListOptions{})
if err != nil {
return nil, err
}
ips, err := getIPs(e.clientset)
if err != nil {
return nil, err
}
routes := []*route.TCP{}
for _, namespace := range namespaces.Items {
services, err := e.clientset.CoreV1().Services(namespace.ObjectMeta.GetName()).List(v1.ListOptions{LabelSelector: "tcp-route-sync"})
if err != nil {
return nil, err
}
for _, service := range services.Items {
for _, port := range service.Spec.Ports {
if !isValidPort(port) {
continue
}
portLabel, _ := strconv.Atoi(service.ObjectMeta.Labels["tcp-route-sync"])
if portLabel == 0 {
continue
}
frontendPort := route.Port(portLabel)
nodePort := route.Port(port.NodePort)
backends := getBackends(ips, nodePort)
tcp := &route.TCP{Frontend: frontendPort, Backends: backends}
routes = append(routes, tcp)
}
}
}
return routes, nil
}
func (e *endpoint) HTTP() ([]*route.HTTP, error) {
namespaces, err := e.clientset.CoreV1().Namespaces().List(v1.ListOptions{})
if err != nil {
return nil, err
}
ips, err := getIPs(e.clientset)
if err != nil {
return nil, err
}
routes := []*route.HTTP{}
for _, namespace := range namespaces.Items {
services, err := e.clientset.CoreV1().Services(namespace.ObjectMeta.GetName()).List(v1.ListOptions{LabelSelector: "http-route-sync"})
if err != nil {
return nil, err
}
for _, service := range services.Items {
for _, port := range service.Spec.Ports {
if !isValidPort(port) {
continue
}
nodePort := route.Port(port.NodePort)
backends := getBackends(ips, nodePort)
routeName := service.ObjectMeta.Labels["http-route-sync"]
fullName := routeName + "." + e.cfDomain
http := &route.HTTP{Name: fullName, Backends: backends}
routes = append(routes, http)
}
}
}
return routes, nil
}
// isValidPort returns true if this is a port we want to route to
func isValidPort(port v1.ServicePort) bool {
if port.Protocol == "UDP" {
return false
}
if route.Port(port.NodePort) <= 0 {
return false
}
return true
}
// getIPs returns the IP of all minions
func getIPs(clientset k8s.Interface) ([]string, error) {
nodes, err := clientset.CoreV1().Nodes().List(v1.ListOptions{})
if err != nil {
return nil, err
}
ips := []string{}
for _, node := range nodes.Items {
for _, address := range node.Status.Addresses {
if address.Type == "InternalIP" {
ips = append(ips, address.Address)
}
}
}
return ips, nil
}
// getBackends returns a list of route.Endpoints for a set of backend IPs and a given nodePort
func getBackends(ips []string, nodePort route.Port) []route.Endpoint {
backends := []route.Endpoint{}
for _, ip := range ips {
backends = append(backends, route.Endpoint{IP: ip, Port: nodePort})
}
return backends
}