Skip to content

Commit 0f17f00

Browse files
authored
add ELBV2 tagging operations (#1387)
add LoadBalancer attribute reconciler add resource status operations
1 parent c88d423 commit 0f17f00

13 files changed

+1752
-16
lines changed

pkg/algorithm/maps.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,25 @@ func MergeStringMap(maps ...map[string]string) map[string]string {
2525
}
2626
return ret
2727
}
28+
29+
// DiffStringMap will diff desired with current.
30+
// Returns the k/v that need to be add/updated and k/v that need to be deleted to make current match desired.
31+
func DiffStringMap(desired map[string]string, current map[string]string) (map[string]string, map[string]string) {
32+
modify := make(map[string]string)
33+
remove := make(map[string]string)
34+
35+
for key, desiredVal := range desired {
36+
currentVal, ok := current[key]
37+
if !ok || currentVal != desiredVal {
38+
modify[key] = desiredVal
39+
}
40+
}
41+
42+
for key, currentVal := range current {
43+
if _, ok := desired[key]; !ok {
44+
remove[key] = currentVal
45+
}
46+
}
47+
48+
return modify, remove
49+
}

pkg/algorithm/maps_test.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,99 @@ func TestMergeStringMap(t *testing.T) {
179179
})
180180
}
181181
}
182+
183+
func TestDiffStringMap(t *testing.T) {
184+
type args struct {
185+
desired map[string]string
186+
current map[string]string
187+
}
188+
tests := []struct {
189+
name string
190+
args args
191+
wantUpdate map[string]string
192+
wantRemove map[string]string
193+
}{
194+
{
195+
name: "standard case",
196+
args: args{
197+
desired: map[string]string{
198+
"a": "a1",
199+
"b": "b1",
200+
"c": "c1",
201+
},
202+
current: map[string]string{
203+
"a": "a1",
204+
"b": "b2",
205+
"d": "d1",
206+
},
207+
},
208+
wantUpdate: map[string]string{
209+
"b": "b1",
210+
"c": "c1",
211+
},
212+
wantRemove: map[string]string{
213+
"d": "d1",
214+
},
215+
},
216+
{
217+
name: "only need to update",
218+
args: args{
219+
desired: map[string]string{
220+
"a": "a1",
221+
"b": "b1",
222+
"c": "c1",
223+
},
224+
current: map[string]string{
225+
"a": "a1",
226+
"b": "b1",
227+
},
228+
},
229+
wantUpdate: map[string]string{
230+
"c": "c1",
231+
},
232+
wantRemove: map[string]string{},
233+
},
234+
{
235+
name: "only need to remove",
236+
args: args{
237+
desired: map[string]string{
238+
"a": "a1",
239+
"b": "b1",
240+
},
241+
current: map[string]string{
242+
"a": "a1",
243+
"b": "b1",
244+
"c": "c1",
245+
},
246+
},
247+
wantUpdate: map[string]string{},
248+
wantRemove: map[string]string{
249+
"c": "c1",
250+
},
251+
},
252+
{
253+
name: "both map are equal",
254+
args: args{
255+
desired: map[string]string{
256+
"a": "a1",
257+
"b": "b1",
258+
"c": "c1",
259+
},
260+
current: map[string]string{
261+
"a": "a1",
262+
"b": "b1",
263+
"c": "c1",
264+
},
265+
},
266+
wantUpdate: map[string]string{},
267+
wantRemove: map[string]string{},
268+
},
269+
}
270+
for _, tt := range tests {
271+
t.Run(tt.name, func(t *testing.T) {
272+
gotUpdate, gotRemove := DiffStringMap(tt.args.desired, tt.args.current)
273+
assert.Equal(t, tt.wantUpdate, gotUpdate)
274+
assert.Equal(t, tt.wantRemove, gotRemove)
275+
})
276+
}
277+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package elbv2
2+
3+
import (
4+
"context"
5+
awssdk "github.com/aws/aws-sdk-go/aws"
6+
elbv2sdk "github.com/aws/aws-sdk-go/service/elbv2"
7+
"github.com/go-logr/logr"
8+
"k8s.io/apimachinery/pkg/util/sets"
9+
"sigs.k8s.io/aws-alb-ingress-controller/pkg/algorithm"
10+
"sigs.k8s.io/aws-alb-ingress-controller/pkg/aws/services"
11+
elbv2model "sigs.k8s.io/aws-alb-ingress-controller/pkg/model/elbv2"
12+
)
13+
14+
// reconciler for LoadBalancer attributes
15+
type LoadBalancerAttributeReconciler interface {
16+
// Reconcile loadBalancer attributes
17+
Reconcile(ctx context.Context, sdkLB LoadBalancerWithTags, resLB *elbv2model.LoadBalancer) error
18+
}
19+
20+
var _ LoadBalancerAttributeReconciler = &defaultLoadBalancerAttributeReconciler{}
21+
22+
// default implementation for LoadBalancerAttributeReconciler
23+
type defaultLoadBalancerAttributeReconciler struct {
24+
elbv2Client services.ELBV2
25+
logger logr.Logger
26+
}
27+
28+
func (r *defaultLoadBalancerAttributeReconciler) Reconcile(ctx context.Context, sdkLB LoadBalancerWithTags, resLB *elbv2model.LoadBalancer) error {
29+
desiredAttrs := r.getDesiredLoadBalancerAttributes(ctx, resLB)
30+
currentAttrs, err := r.getCurrentLoadBalancerAttributes(ctx, sdkLB)
31+
if err != nil {
32+
return err
33+
}
34+
35+
attributesToUpdate, _ := algorithm.DiffStringMap(desiredAttrs, currentAttrs)
36+
if len(attributesToUpdate) > 0 {
37+
req := &elbv2sdk.ModifyLoadBalancerAttributesInput{
38+
LoadBalancerArn: sdkLB.LoadBalancer.LoadBalancerArn,
39+
Attributes: nil,
40+
}
41+
for _, attrKey := range sets.StringKeySet(attributesToUpdate).List() {
42+
req.Attributes = append(req.Attributes, &elbv2sdk.LoadBalancerAttribute{
43+
Key: awssdk.String(attrKey),
44+
Value: awssdk.String(attributesToUpdate[attrKey]),
45+
})
46+
}
47+
48+
r.logger.Info("modifying loadBalancer attributes",
49+
"resourceID", resLB.ID(),
50+
"arn", awssdk.StringValue(sdkLB.LoadBalancer.LoadBalancerArn),
51+
"change", attributesToUpdate)
52+
if _, err := r.elbv2Client.ModifyLoadBalancerAttributesWithContext(ctx, req); err != nil {
53+
return err
54+
}
55+
r.logger.Info("modified loadBalancer attributes",
56+
"resourceID", resLB.ID(),
57+
"arn", awssdk.StringValue(sdkLB.LoadBalancer.LoadBalancerArn))
58+
}
59+
return nil
60+
}
61+
62+
func (r *defaultLoadBalancerAttributeReconciler) getDesiredLoadBalancerAttributes(ctx context.Context, resLB *elbv2model.LoadBalancer) map[string]string {
63+
lbAttributes := make(map[string]string, len(resLB.Spec.LoadBalancerAttributes))
64+
for _, attr := range resLB.Spec.LoadBalancerAttributes {
65+
lbAttributes[attr.Key] = attr.Value
66+
}
67+
return lbAttributes
68+
}
69+
70+
func (r *defaultLoadBalancerAttributeReconciler) getCurrentLoadBalancerAttributes(ctx context.Context, sdkLB LoadBalancerWithTags) (map[string]string, error) {
71+
req := &elbv2sdk.DescribeLoadBalancerAttributesInput{
72+
LoadBalancerArn: sdkLB.LoadBalancer.LoadBalancerArn,
73+
}
74+
resp, err := r.elbv2Client.DescribeLoadBalancerAttributesWithContext(ctx, req)
75+
if err != nil {
76+
return nil, err
77+
}
78+
79+
lbAttributes := make(map[string]string, len(resp.Attributes))
80+
for _, attr := range resp.Attributes {
81+
lbAttributes[awssdk.StringValue(attr.Key)] = awssdk.StringValue(attr.Value)
82+
}
83+
return lbAttributes, nil
84+
}

0 commit comments

Comments
 (0)