-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathgateway_diffs.go
123 lines (106 loc) · 5.08 KB
/
gateway_diffs.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
package reconcilers
import (
"context"
"fmt"
"slices"
"github.com/go-logr/logr"
"sigs.k8s.io/controller-runtime/pkg/client"
gatewayapiv1 "sigs.k8s.io/gateway-api/apis/v1"
"github.com/kuadrant/kuadrant-operator/pkg/library/kuadrant"
)
type GatewayDiffs struct {
GatewaysMissingPolicyRef []kuadrant.GatewayWrapper
GatewaysWithValidPolicyRef []kuadrant.GatewayWrapper
GatewaysWithInvalidPolicyRef []kuadrant.GatewayWrapper
}
// ComputeGatewayDiffs computes all the differences to reconcile regarding the gateways whose behaviors should/should not be extended by the policy.
// These include gateways directly referenced by the policy and gateways indirectly referenced through the policy's target network objects.
// * list of gateways to which the policy applies for the first time
// * list of gateways to which the policy no longer applies
// * list of gateways to which the policy still applies
// TODO(@guicassolato): unit test
func ComputeGatewayDiffs(ctx context.Context, k8sClient client.Reader, policy, targetNetworkObject client.Object) (*GatewayDiffs, error) {
logger, _ := logr.FromContext(ctx)
var gwKeys []client.ObjectKey
if policy.GetDeletionTimestamp() == nil {
gwKeys = targetedGatewayKeys(targetNetworkObject)
}
// TODO(rahulanand16nov): maybe think about optimizing it with a label later
allGwList := &gatewayapiv1.GatewayList{}
err := k8sClient.List(ctx, allGwList)
if err != nil {
return nil, err
}
policyKind, ok := policy.(kuadrant.Referrer)
if !ok {
return nil, fmt.Errorf("policy %s is not a referrer", policy.GetObjectKind().GroupVersionKind())
}
gwDiff := &GatewayDiffs{
GatewaysMissingPolicyRef: gatewaysMissingPolicyRef(allGwList, client.ObjectKeyFromObject(policy), gwKeys, policyKind),
GatewaysWithValidPolicyRef: gatewaysWithValidPolicyRef(allGwList, client.ObjectKeyFromObject(policy), gwKeys, policyKind),
GatewaysWithInvalidPolicyRef: gatewaysWithInvalidPolicyRef(allGwList, client.ObjectKeyFromObject(policy), gwKeys, policyKind),
}
logger.V(1).Info("ComputeGatewayDiffs",
"missing-policy-ref", len(gwDiff.GatewaysMissingPolicyRef),
"valid-policy-ref", len(gwDiff.GatewaysWithValidPolicyRef),
"invalid-policy-ref", len(gwDiff.GatewaysWithInvalidPolicyRef),
)
return gwDiff, nil
}
// gatewaysMissingPolicyRef returns gateways referenced by the policy but that miss the reference to it the annotations
func gatewaysMissingPolicyRef(gwList *gatewayapiv1.GatewayList, policyKey client.ObjectKey, policyGwKeys []client.ObjectKey, policyKind kuadrant.Referrer) []kuadrant.GatewayWrapper {
gateways := make([]kuadrant.GatewayWrapper, 0)
for i := range gwList.Items {
gateway := gwList.Items[i]
gw := kuadrant.GatewayWrapper{Gateway: &gateway, Referrer: policyKind}
if slices.Contains(policyGwKeys, client.ObjectKeyFromObject(&gateway)) && !gw.ContainsPolicy(policyKey) {
gateways = append(gateways, gw)
}
}
return gateways
}
// gatewaysWithValidPolicyRef returns gateways referenced by the policy that also have the reference in the annotations
func gatewaysWithValidPolicyRef(gwList *gatewayapiv1.GatewayList, policyKey client.ObjectKey, policyGwKeys []client.ObjectKey, policyKind kuadrant.Referrer) []kuadrant.GatewayWrapper {
gateways := make([]kuadrant.GatewayWrapper, 0)
for i := range gwList.Items {
gateway := gwList.Items[i]
gw := kuadrant.GatewayWrapper{Gateway: &gateway, Referrer: policyKind}
if slices.Contains(policyGwKeys, client.ObjectKeyFromObject(&gateway)) && gw.ContainsPolicy(policyKey) {
gateways = append(gateways, gw)
}
}
return gateways
}
// gatewaysWithInvalidPolicyRef returns gateways not referenced by the policy that still have the reference in the annotations
func gatewaysWithInvalidPolicyRef(gwList *gatewayapiv1.GatewayList, policyKey client.ObjectKey, policyGwKeys []client.ObjectKey, policyKind kuadrant.Referrer) []kuadrant.GatewayWrapper {
gateways := make([]kuadrant.GatewayWrapper, 0)
for i := range gwList.Items {
gateway := gwList.Items[i]
gw := kuadrant.GatewayWrapper{Gateway: &gateway, Referrer: policyKind}
if !slices.Contains(policyGwKeys, client.ObjectKeyFromObject(&gateway)) && gw.ContainsPolicy(policyKey) {
gateways = append(gateways, gw)
}
}
return gateways
}
// targetedGatewayKeys returns the list of gateways in the hierarchy of a target network object
func targetedGatewayKeys(targetNetworkObject client.Object) []client.ObjectKey {
switch obj := targetNetworkObject.(type) {
case *gatewayapiv1.HTTPRoute:
gwKeys := make([]client.ObjectKey, 0)
for _, parentRef := range obj.Spec.CommonRouteSpec.ParentRefs {
gwKey := client.ObjectKey{Name: string(parentRef.Name), Namespace: obj.Namespace}
if parentRef.Namespace != nil {
gwKey.Namespace = string(*parentRef.Namespace)
}
gwKeys = append(gwKeys, gwKey)
}
return gwKeys
case *gatewayapiv1.Gateway:
return []client.ObjectKey{client.ObjectKeyFromObject(targetNetworkObject)}
// If the targetNetworkObject is nil, we don't fail; instead, we return an empty slice of gateway keys.
// This is for supporting a smooth cleanup in cases where the network object has been deleted already
default:
return []client.ObjectKey{}
}
}