forked from joeholley/supergloo
/
upstream_list.go
136 lines (124 loc) · 3.26 KB
/
upstream_list.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
130
131
132
133
134
135
136
package utils
import (
"reflect"
"sort"
"github.com/solo-io/go-utils/stringutils"
gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1"
"github.com/solo-io/go-utils/errors"
)
// one (kube) service that maps to multiple upstreams
type UpstreamService struct {
Host string
LabelSets []map[string]string
Ports []uint32
Upstreams gloov1.UpstreamList // the upstreams this service was created from
}
func UpstreamServicesByHost(upstreams gloov1.UpstreamList) (map[string]*UpstreamService, error) {
services := make(map[string]*UpstreamService)
for _, us := range upstreams {
host, err := GetHostForUpstream(us)
if err != nil {
return nil, err
}
if service, ok := services[host]; ok {
service.Upstreams = append(service.Upstreams, us)
continue
}
service, err := ServiceFromHost(host, upstreams)
if err != nil {
return nil, err
}
services[host] = service
}
return services, nil
}
func GetUpstreamHostPortsLabels(us *gloov1.Upstream) (string, uint32, map[string]string, error) {
labels := GetLabelsForUpstream(us)
host, err := GetHostForUpstream(us)
if err != nil {
return "", 0, nil, errors.Wrapf(err, "getting host for upstream")
}
port, err := GetPortForUpstream(us)
if err != nil {
return "", 0, nil, errors.Wrapf(err, "getting port for upstream")
}
return host, port, labels, nil
}
// only selects the first upstream in each list with a unique host, drop the others
func ServiceFromHost(host string, upstreams gloov1.UpstreamList) (*UpstreamService, error) {
service := &UpstreamService{Host: host}
for _, us := range upstreams {
usHost, port, labels, err := GetUpstreamHostPortsLabels(us)
if err != nil {
return nil, err
}
if host != usHost {
continue
}
var duplicateLabels, duplicatePort bool
for _, foundLabels := range service.LabelSets {
if reflect.DeepEqual(labels, foundLabels) {
duplicateLabels = true
break
}
}
for _, foundPort := range service.Ports {
if port == foundPort {
duplicatePort = true
break
}
}
if !duplicatePort {
service.Ports = append(service.Ports, port)
}
if !duplicateLabels {
service.LabelSets = append(service.LabelSets, labels)
}
service.Upstreams = append(service.Upstreams, us)
}
return service, nil
}
func HostsForUpstreams(upstreams gloov1.UpstreamList) ([]string, error) {
var hosts []string
for _, us := range upstreams {
host, err := GetHostForUpstream(us)
if err != nil {
return nil, errors.Wrapf(err, "getting host for upstream")
}
hosts = append(hosts, host)
}
hosts = stringutils.Unique(hosts)
sort.Strings(hosts)
return hosts, nil
}
func PortsFromUpstreams(upstreams gloov1.UpstreamList) ([]uint32, error) {
var ports []uint32
addPorts:
for _, us := range upstreams {
port, err := GetPortForUpstream(us)
if err != nil {
return nil, err
}
for _, p := range ports {
if p == port {
continue addPorts
}
}
ports = append(ports, port)
}
return ports, nil
}
func LabelsFromUpstreams(upstreams gloov1.UpstreamList) ([]map[string]string, error) {
var labels []map[string]string
addLabels:
for _, us := range upstreams {
label := GetLabelsForUpstream(us)
for _, p := range labels {
if reflect.DeepEqual(p, label) {
continue addLabels
}
}
labels = append(labels, label)
}
return labels, nil
}