forked from kubernetes-sigs/aws-load-balancer-controller
-
Notifications
You must be signed in to change notification settings - Fork 0
/
listener_synthesizer.go
145 lines (130 loc) · 4.42 KB
/
listener_synthesizer.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
package elbv2
import (
"context"
awssdk "github.com/aws/aws-sdk-go/aws"
"github.com/go-logr/logr"
"k8s.io/apimachinery/pkg/util/sets"
"github.com/sonal-chauhan/aws-load-balancer-controller/pkg/aws/services"
"github.com/sonal-chauhan/aws-load-balancer-controller/pkg/model/core"
elbv2model "github.com/sonal-chauhan/aws-load-balancer-controller/pkg/model/elbv2"
)
func NewListenerSynthesizer(elbv2Client services.ELBV2, taggingManager TaggingManager,
lsManager ListenerManager, logger logr.Logger, stack core.Stack) *listenerSynthesizer {
return &listenerSynthesizer{
elbv2Client: elbv2Client,
lsManager: lsManager,
logger: logger,
taggingManager: taggingManager,
stack: stack,
}
}
type listenerSynthesizer struct {
elbv2Client services.ELBV2
lsManager ListenerManager
logger logr.Logger
taggingManager TaggingManager
stack core.Stack
}
func (s *listenerSynthesizer) Synthesize(ctx context.Context) error {
var resLSs []*elbv2model.Listener
s.stack.ListResources(&resLSs)
resLSsByLBARN, err := mapResListenerByLoadBalancerARN(resLSs)
if err != nil {
return err
}
for lbARN, resLSs := range resLSsByLBARN {
if err := s.synthesizeListenersOnLB(ctx, lbARN, resLSs); err != nil {
return err
}
}
return nil
}
func (s *listenerSynthesizer) PostSynthesize(ctx context.Context) error {
// nothing to do here.
return nil
}
func (s *listenerSynthesizer) synthesizeListenersOnLB(ctx context.Context, lbARN string, resLSs []*elbv2model.Listener) error {
sdkLSs, err := s.findSDKListenersOnLB(ctx, lbARN)
if err != nil {
return err
}
matchedResAndSDKLSs, unmatchedResLSs, unmatchedSDKLSs := matchResAndSDKListeners(resLSs, sdkLSs)
for _, sdkLS := range unmatchedSDKLSs {
if err := s.lsManager.Delete(ctx, sdkLS); err != nil {
return err
}
}
for _, resLS := range unmatchedResLSs {
lsStatus, err := s.lsManager.Create(ctx, resLS)
if err != nil {
return err
}
resLS.SetStatus(lsStatus)
}
for _, resAndSDKLS := range matchedResAndSDKLSs {
lsStatus, err := s.lsManager.Update(ctx, resAndSDKLS.resLS, resAndSDKLS.sdkLS)
if err != nil {
return err
}
resAndSDKLS.resLS.SetStatus(lsStatus)
}
return nil
}
// findSDKListenersOnLB returns the listeners configured on LoadBalancer.
func (s *listenerSynthesizer) findSDKListenersOnLB(ctx context.Context, lbARN string) ([]ListenerWithTags, error) {
return s.taggingManager.ListListeners(ctx, lbARN)
}
type resAndSDKListenerPair struct {
resLS *elbv2model.Listener
sdkLS ListenerWithTags
}
func matchResAndSDKListeners(resLSs []*elbv2model.Listener, sdkLSs []ListenerWithTags) ([]resAndSDKListenerPair, []*elbv2model.Listener, []ListenerWithTags) {
var matchedResAndSDKLSs []resAndSDKListenerPair
var unmatchedResLSs []*elbv2model.Listener
var unmatchedSDKLSs []ListenerWithTags
resLSByPort := mapResListenerByPort(resLSs)
sdkLSByPort := mapSDKListenerByPort(sdkLSs)
resLSPorts := sets.Int64KeySet(resLSByPort)
sdkLSPorts := sets.Int64KeySet(sdkLSByPort)
for _, port := range resLSPorts.Intersection(sdkLSPorts).List() {
resLS := resLSByPort[port]
sdkLS := sdkLSByPort[port]
matchedResAndSDKLSs = append(matchedResAndSDKLSs, resAndSDKListenerPair{
resLS: resLS,
sdkLS: sdkLS,
})
}
for _, port := range resLSPorts.Difference(sdkLSPorts).List() {
unmatchedResLSs = append(unmatchedResLSs, resLSByPort[port])
}
for _, port := range sdkLSPorts.Difference(resLSPorts).List() {
unmatchedSDKLSs = append(unmatchedSDKLSs, sdkLSByPort[port])
}
return matchedResAndSDKLSs, unmatchedResLSs, unmatchedSDKLSs
}
func mapResListenerByPort(resLSs []*elbv2model.Listener) map[int64]*elbv2model.Listener {
resLSByPort := make(map[int64]*elbv2model.Listener, len(resLSs))
for _, ls := range resLSs {
resLSByPort[ls.Spec.Port] = ls
}
return resLSByPort
}
func mapSDKListenerByPort(sdkLSs []ListenerWithTags) map[int64]ListenerWithTags {
sdkLSByPort := make(map[int64]ListenerWithTags, len(sdkLSs))
for _, ls := range sdkLSs {
sdkLSByPort[awssdk.Int64Value(ls.Listener.Port)] = ls
}
return sdkLSByPort
}
func mapResListenerByLoadBalancerARN(resLSs []*elbv2model.Listener) (map[string][]*elbv2model.Listener, error) {
resLSsByLBARN := make(map[string][]*elbv2model.Listener, len(resLSs))
ctx := context.Background()
for _, ls := range resLSs {
lbARN, err := ls.Spec.LoadBalancerARN.Resolve(ctx)
if err != nil {
return nil, err
}
resLSsByLBARN[lbARN] = append(resLSsByLBARN[lbARN], ls)
}
return resLSsByLBARN, nil
}