/
vhost.go
94 lines (79 loc) · 2.58 KB
/
vhost.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
package converting
import (
"fmt"
"google.golang.org/protobuf/types/known/durationpb"
route "github.com/envoyproxy/go-control-plane/envoy/config/route/v3"
)
type VhostCollection struct {
Vhosts map[string]*route.VirtualHost
usedDomains map[string]*route.VirtualHost
}
func NewVhostCollection() *VhostCollection {
return &VhostCollection{
Vhosts: make(map[string]*route.VirtualHost),
usedDomains: make(map[string]*route.VirtualHost),
}
}
func (w VhostCollection) AddService(clusterIdentifier string, labels *ServiceLabel) (err error) {
primaryDomain := labels.Route.Domain
virtualHost, exist := w.Vhosts[primaryDomain]
if !exist {
if _, exist := w.usedDomains[primaryDomain]; exist {
return fmt.Errorf("domain %s is already used in another vhost", primaryDomain)
}
virtualHost = &route.VirtualHost{
Name: primaryDomain,
Domains: []string{primaryDomain},
Routes: []*route.Route{},
}
}
// Calculate and validate changes to the vhost domains
var extraDomains []string
for _, extraDomain := range labels.Route.ExtraDomains {
if extraDomain == primaryDomain {
continue
}
if v, exist := w.usedDomains[extraDomain]; exist {
if v != virtualHost {
return fmt.Errorf("domain %s is already used in another vhost", extraDomain)
}
continue
}
extraDomains = append(extraDomains, extraDomain)
}
// Validation ended above, applying changes
w.Vhosts[primaryDomain] = virtualHost
w.usedDomains[primaryDomain] = virtualHost
// Order of routes matter, ensure that the default catch-all / comes last
newRoute := w.createRoute(clusterIdentifier, labels)
if labels.Route.PathPrefix == "/" {
virtualHost.Routes = append(virtualHost.Routes, newRoute)
} else {
virtualHost.Routes = append([]*route.Route{newRoute}, virtualHost.Routes...)
}
for i := range extraDomains {
virtualHost.Domains = append(virtualHost.Domains, extraDomains[i])
w.usedDomains[extraDomains[i]] = virtualHost
}
return nil
}
func (w VhostCollection) createRoute(clusterIdentifier string, labels *ServiceLabel) *route.Route {
return &route.Route{
Name: clusterIdentifier + "_route",
Match: &route.RouteMatch{
PathSpecifier: &route.RouteMatch_Prefix{
Prefix: labels.Route.PathPrefix,
},
},
Action: &route.Route_Route{
Route: &route.RouteAction{
ClusterSpecifier: &route.RouteAction_Cluster{
Cluster: clusterIdentifier,
},
// https://github.com/envoyproxy/envoy/issues/8517#issuecomment-540225144
IdleTimeout: durationpb.New(labels.Endpoint.RequestTimeout),
Timeout: durationpb.New(labels.Endpoint.RequestTimeout),
},
},
}
}