-
Notifications
You must be signed in to change notification settings - Fork 2.8k
/
helpers.go
174 lines (149 loc) · 5.14 KB
/
helpers.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of Cilium
package gateway_api
import (
"context"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
"github.com/cilium/cilium/operator/pkg/model"
)
const (
kindGateway = "Gateway"
kindHTTPRoute = "HTTPRoute"
kindTLSRoute = "TLSRoute"
kindUDPRoute = "UDPRoute"
kindTCPRoute = "TCPRoute"
kindService = "Service"
kindSecret = "Secret"
)
func IsGateway(parent gatewayv1beta1.ParentReference) bool {
return (parent.Kind == nil || *parent.Kind == kindGateway) && (parent.Group == nil || *parent.Group == gatewayv1beta1.GroupName)
}
func IsService(be gatewayv1beta1.BackendObjectReference) bool {
return (be.Kind == nil || *be.Kind == kindService) && (be.Group == nil || *be.Group == corev1.GroupName)
}
func IsSecret(secret gatewayv1beta1.SecretObjectReference) bool {
return (secret.Kind == nil || *secret.Kind == kindSecret) && (secret.Group == nil || *secret.Group == corev1.GroupName)
}
func GatewayAddressTypePtr(addr gatewayv1beta1.AddressType) *gatewayv1beta1.AddressType {
return &addr
}
func GroupPtr(name string) *gatewayv1beta1.Group {
group := gatewayv1beta1.Group(name)
return &group
}
func KindPtr(name string) *gatewayv1beta1.Kind {
kind := gatewayv1beta1.Kind(name)
return &kind
}
func ObjectNamePtr(name string) *gatewayv1beta1.ObjectName {
objectName := gatewayv1beta1.ObjectName(name)
return &objectName
}
func groupDerefOr(group *gatewayv1beta1.Group, defaultGroup string) string {
if group != nil && *group != "" {
return string(*group)
}
return defaultGroup
}
// isAllowed returns true if the provided Route is allowed to attach to given gateway
func isAllowed(ctx context.Context, c client.Client, gw *gatewayv1beta1.Gateway, route metav1.Object) bool {
for _, listener := range gw.Spec.Listeners {
// all routes in the same namespace are allowed for this listener
if listener.AllowedRoutes == nil || listener.AllowedRoutes.Namespaces == nil {
return route.GetNamespace() == gw.GetNamespace()
}
// check if route is kind-allowed
if !isKindAllowed(listener, route) {
continue
}
// check if route is namespace-allowed
switch *listener.AllowedRoutes.Namespaces.From {
case gatewayv1beta1.NamespacesFromAll:
return true
case gatewayv1beta1.NamespacesFromSame:
if route.GetNamespace() == gw.GetNamespace() {
return true
}
case gatewayv1beta1.NamespacesFromSelector:
nsList := &corev1.NamespaceList{}
selector, _ := metav1.LabelSelectorAsSelector(listener.AllowedRoutes.Namespaces.Selector)
if err := c.List(ctx, nsList, client.MatchingLabelsSelector{Selector: selector}); err != nil {
log.WithError(err).Error("Unable to list namespaces")
return false
}
for _, ns := range nsList.Items {
if ns.Name == route.GetNamespace() {
return true
}
}
}
}
return false
}
func isKindAllowed(listener gatewayv1beta1.Listener, route metav1.Object) bool {
if listener.AllowedRoutes.Kinds == nil {
return true
}
routeKind := getGatewayKindForObject(route)
for _, kind := range listener.AllowedRoutes.Kinds {
if (kind.Group == nil || string(*kind.Group) == gatewayv1beta1.GroupName) &&
kind.Kind == kindHTTPRoute && routeKind == kindHTTPRoute {
return true
} else if (kind.Group == nil || string(*kind.Group) == gatewayv1alpha2.GroupName) &&
kind.Kind == kindTLSRoute && routeKind == kindTLSRoute {
return true
}
}
return false
}
func computeHosts[T ~string](gw *gatewayv1beta1.Gateway, hostnames []T) []string {
hosts := make([]string, 0, len(hostnames))
for _, listener := range gw.Spec.Listeners {
hosts = append(hosts, computeHostsForListener(&listener, hostnames)...)
}
return hosts
}
func computeHostsForListener[T ~string](listener *gatewayv1beta1.Listener, hostnames []T) []string {
return model.ComputeHosts(toStringSlice(hostnames), (*string)(listener.Hostname))
}
func toStringSlice[T ~string](s []T) []string {
res := make([]string, 0, len(s))
for _, h := range s {
res = append(res, string(h))
}
return res
}
func getSupportedGroupKind(protocol gatewayv1beta1.ProtocolType) (*gatewayv1beta1.Group, gatewayv1beta1.Kind) {
switch protocol {
case gatewayv1beta1.TLSProtocolType:
return GroupPtr(gatewayv1alpha2.GroupName), kindTLSRoute
case gatewayv1beta1.HTTPSProtocolType:
return GroupPtr(gatewayv1beta1.GroupName), kindHTTPRoute
case gatewayv1beta1.HTTPProtocolType:
return GroupPtr(gatewayv1beta1.GroupName), kindHTTPRoute
case gatewayv1beta1.TCPProtocolType:
return GroupPtr(gatewayv1alpha2.GroupName), kindTCPRoute
case gatewayv1beta1.UDPProtocolType:
return GroupPtr(gatewayv1alpha2.GroupName), kindUDPRoute
default:
return GroupPtr("Unknown"), "Unknown"
}
}
func getGatewayKindForObject(obj metav1.Object) gatewayv1beta1.Kind {
switch obj.(type) {
case *gatewayv1beta1.HTTPRoute:
return kindHTTPRoute
case *gatewayv1alpha2.TLSRoute:
return kindTLSRoute
case *gatewayv1alpha2.UDPRoute:
return kindUDPRoute
case *gatewayv1alpha2.TCPRoute:
return kindTCPRoute
default:
return "Unknown"
}
}