Skip to content

Commit 41f7943

Browse files
committed
fixup(sg-resolver): Allow multiple SGs with the same Name tag
1 parent e5d625f commit 41f7943

File tree

4 files changed

+188
-16
lines changed

4 files changed

+188
-16
lines changed

pkg/algorithm/slices.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package algorithm
2+
3+
import "cmp"
4+
5+
// RemoveSliceDuplicates returns a copy of the slice without duplicate entries.
6+
func RemoveSliceDuplicates[S ~[]E, E cmp.Ordered](s S) []E {
7+
result := make([]E, 0, len(s))
8+
found := make(map[E]struct{}, len(s))
9+
10+
for _, x := range s {
11+
if _, ok := found[x]; !ok {
12+
found[x] = struct{}{}
13+
result = append(result, x)
14+
}
15+
}
16+
17+
return result
18+
}

pkg/algorithm/slices_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package algorithm
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func Test_RemoveSliceDuplicates(t *testing.T) {
10+
type args struct {
11+
data []string
12+
}
13+
tests := []struct {
14+
name string
15+
args args
16+
want []string
17+
}{
18+
{
19+
name: "empty",
20+
args: args{
21+
data: []string{},
22+
},
23+
want: []string{},
24+
},
25+
{
26+
name: "no duplicate entries",
27+
args: args{
28+
data: []string{"a", "b", "c", "d"},
29+
},
30+
want: []string{"a", "b", "c", "d"},
31+
},
32+
{
33+
name: "with duplicates",
34+
args: args{
35+
data: []string{"a", "b", "a", "c", "b"},
36+
},
37+
want: []string{"a", "b", "c"},
38+
},
39+
}
40+
for _, tt := range tests {
41+
t.Run(tt.name, func(t *testing.T) {
42+
got := RemoveSliceDuplicates(tt.args.data)
43+
assert.Equal(t, tt.want, got)
44+
})
45+
}
46+
}

pkg/networking/security_group_resolver.go

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
awssdk "github.com/aws/aws-sdk-go/aws"
88
ec2sdk "github.com/aws/aws-sdk-go/service/ec2"
99
"github.com/pkg/errors"
10+
"sigs.k8s.io/aws-load-balancer-controller/pkg/algorithm"
1011
"sigs.k8s.io/aws-load-balancer-controller/pkg/aws/services"
1112
)
1213

@@ -35,42 +36,60 @@ type defaultSecurityGroupResolver struct {
3536
func (r *defaultSecurityGroupResolver) ResolveViaNameOrID(ctx context.Context, sgNameOrIDs []string) ([]string, error) {
3637
sgIDs, sgNames := r.splitIntoSgNameAndIDs(sgNameOrIDs)
3738
var resolvedSGs []*ec2sdk.SecurityGroup
39+
3840
if len(sgIDs) > 0 {
3941
sgs, err := r.resolveViaGroupID(ctx, sgIDs)
4042
if err != nil {
4143
return nil, err
4244
}
4345
resolvedSGs = append(resolvedSGs, sgs...)
4446
}
47+
4548
if len(sgNames) > 0 {
4649
sgs, err := r.resolveViaGroupName(ctx, sgNames)
4750
if err != nil {
4851
return nil, err
4952
}
5053
resolvedSGs = append(resolvedSGs, sgs...)
5154
}
55+
5256
resolvedSGIDs := make([]string, 0, len(resolvedSGs))
5357
for _, sg := range resolvedSGs {
5458
resolvedSGIDs = append(resolvedSGIDs, awssdk.StringValue(sg.GroupId))
5559
}
56-
if len(resolvedSGIDs) != len(sgNameOrIDs) {
57-
return nil, errors.Errorf("couldn't find all securityGroups, nameOrIDs: %v, found: %v", sgNameOrIDs, resolvedSGIDs)
58-
}
60+
5961
return resolvedSGIDs, nil
6062
}
6163

6264
func (r *defaultSecurityGroupResolver) resolveViaGroupID(ctx context.Context, sgIDs []string) ([]*ec2sdk.SecurityGroup, error) {
6365
req := &ec2sdk.DescribeSecurityGroupsInput{
6466
GroupIds: awssdk.StringSlice(sgIDs),
6567
}
68+
6669
sgs, err := r.ec2Client.DescribeSecurityGroupsAsList(ctx, req)
6770
if err != nil {
6871
return nil, err
6972
}
73+
74+
resolvedSGIDs := make([]string, 0, len(sgs))
75+
for _, sg := range sgs {
76+
resolvedSGIDs = append(resolvedSGIDs, awssdk.StringValue(sg.GroupId))
77+
}
78+
79+
if len(sgIDs) != len(resolvedSGIDs) {
80+
return nil, errors.Errorf(
81+
"couldn't find all securityGroups, requested ids: [%s], found: [%s]",
82+
strings.Join(sgIDs, ", "),
83+
strings.Join(resolvedSGIDs, ", "),
84+
)
85+
}
86+
7087
return sgs, nil
7188
}
7289

7390
func (r *defaultSecurityGroupResolver) resolveViaGroupName(ctx context.Context, sgNames []string) ([]*ec2sdk.SecurityGroup, error) {
91+
sgNames = algorithm.RemoveSliceDuplicates(sgNames)
92+
7493
req := &ec2sdk.DescribeSecurityGroupsInput{
7594
Filters: []*ec2sdk.Filter{
7695
{
@@ -83,10 +102,31 @@ func (r *defaultSecurityGroupResolver) resolveViaGroupName(ctx context.Context,
83102
},
84103
},
85104
}
105+
86106
sgs, err := r.ec2Client.DescribeSecurityGroupsAsList(ctx, req)
87107
if err != nil {
88108
return nil, err
89109
}
110+
111+
resolvedSGNames := make([]string, 0, len(sgs))
112+
for _, sg := range sgs {
113+
for _, tag := range sg.Tags {
114+
if awssdk.StringValue(tag.Key) == "Name" {
115+
resolvedSGNames = append(resolvedSGNames, awssdk.StringValue(tag.Value))
116+
}
117+
}
118+
}
119+
120+
resolvedSGNames = algorithm.RemoveSliceDuplicates(resolvedSGNames)
121+
122+
if len(sgNames) != len(resolvedSGNames) {
123+
return nil, errors.Errorf(
124+
"couldn't find all securityGroups, requested names: [%s], found: [%s]",
125+
strings.Join(sgNames, ", "),
126+
strings.Join(resolvedSGNames, ", "),
127+
)
128+
}
129+
90130
return sgs, nil
91131
}
92132

pkg/networking/security_group_resolver_test.go

Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,15 @@ func Test_defaultSecurityGroupResolver_ResolveViaNameOrID(t *testing.T) {
8888
resp: []*ec2sdk.SecurityGroup{
8989
{
9090
GroupId: awssdk.String("sg-0912f63b"),
91+
Tags: []*ec2sdk.Tag{
92+
{Key: awssdk.String("Name"), Value: awssdk.String("sg group one")},
93+
},
9194
},
9295
{
9396
GroupId: awssdk.String("sg-08982de7"),
97+
Tags: []*ec2sdk.Tag{
98+
{Key: awssdk.String("Name"), Value: awssdk.String("sg group two")},
99+
},
94100
},
95101
},
96102
},
@@ -101,6 +107,50 @@ func Test_defaultSecurityGroupResolver_ResolveViaNameOrID(t *testing.T) {
101107
"sg-0912f63b",
102108
},
103109
},
110+
{
111+
name: "single name multiple ids",
112+
args: args{
113+
nameOrIDs: []string{
114+
"sg group one",
115+
},
116+
describeSGCalls: []describeSecurityGroupsAsListCall{
117+
{
118+
req: &ec2sdk.DescribeSecurityGroupsInput{
119+
Filters: []*ec2sdk.Filter{
120+
{
121+
Name: awssdk.String("tag:Name"),
122+
Values: awssdk.StringSlice([]string{
123+
"sg group one",
124+
}),
125+
},
126+
{
127+
Name: awssdk.String("vpc-id"),
128+
Values: awssdk.StringSlice([]string{defaultVPCID}),
129+
},
130+
},
131+
},
132+
resp: []*ec2sdk.SecurityGroup{
133+
{
134+
GroupId: awssdk.String("sg-id1"),
135+
Tags: []*ec2sdk.Tag{
136+
{Key: awssdk.String("Name"), Value: awssdk.String("sg group one")},
137+
},
138+
},
139+
{
140+
GroupId: awssdk.String("sg-id2"),
141+
Tags: []*ec2sdk.Tag{
142+
{Key: awssdk.String("Name"), Value: awssdk.String("sg group one")},
143+
},
144+
},
145+
},
146+
},
147+
},
148+
},
149+
want: []string{
150+
"sg-id1",
151+
"sg-id2",
152+
},
153+
},
104154
{
105155
name: "mixed group name and id",
106156
args: args{
@@ -127,6 +177,9 @@ func Test_defaultSecurityGroupResolver_ResolveViaNameOrID(t *testing.T) {
127177
resp: []*ec2sdk.SecurityGroup{
128178
{
129179
GroupId: awssdk.String("sg-0912f63b"),
180+
Tags: []*ec2sdk.Tag{
181+
{Key: awssdk.String("Name"), Value: awssdk.String("sg group one")},
182+
},
130183
},
131184
},
132185
},
@@ -205,13 +258,34 @@ func Test_defaultSecurityGroupResolver_ResolveViaNameOrID(t *testing.T) {
205258
wantErr: errors.New("Describe.Error: unable to describe security groups"),
206259
},
207260
{
208-
name: "unable to resolve all security groups",
261+
name: "unable to resolve all security group ids",
209262
args: args{
210263
nameOrIDs: []string{
211-
"sg group one",
212264
"sg-id1",
213265
"sg-id404",
214266
},
267+
describeSGCalls: []describeSecurityGroupsAsListCall{
268+
{
269+
req: &ec2sdk.DescribeSecurityGroupsInput{
270+
GroupIds: awssdk.StringSlice([]string{"sg-id1", "sg-id404"}),
271+
},
272+
resp: []*ec2sdk.SecurityGroup{
273+
{
274+
GroupId: awssdk.String("sg-id1"),
275+
},
276+
},
277+
},
278+
},
279+
},
280+
wantErr: errors.New("couldn't find all securityGroups, requested ids: [sg-id1, sg-id404], found: [sg-id1]"),
281+
},
282+
{
283+
name: "unable to resolve all security groups names",
284+
args: args{
285+
nameOrIDs: []string{
286+
"sg group one",
287+
"sg group two",
288+
},
215289
describeSGCalls: []describeSecurityGroupsAsListCall{
216290
{
217291
req: &ec2sdk.DescribeSecurityGroupsInput{
@@ -220,6 +294,7 @@ func Test_defaultSecurityGroupResolver_ResolveViaNameOrID(t *testing.T) {
220294
Name: awssdk.String("tag:Name"),
221295
Values: awssdk.StringSlice([]string{
222296
"sg group one",
297+
"sg group two",
223298
}),
224299
},
225300
{
@@ -231,22 +306,15 @@ func Test_defaultSecurityGroupResolver_ResolveViaNameOrID(t *testing.T) {
231306
resp: []*ec2sdk.SecurityGroup{
232307
{
233308
GroupId: awssdk.String("sg-0912f63b"),
234-
},
235-
},
236-
},
237-
{
238-
req: &ec2sdk.DescribeSecurityGroupsInput{
239-
GroupIds: awssdk.StringSlice([]string{"sg-id1", "sg-id404"}),
240-
},
241-
resp: []*ec2sdk.SecurityGroup{
242-
{
243-
GroupId: awssdk.String("sg-id1"),
309+
Tags: []*ec2sdk.Tag{
310+
{Key: awssdk.String("Name"), Value: awssdk.String("sg group one")},
311+
},
244312
},
245313
},
246314
},
247315
},
248316
},
249-
wantErr: errors.New("couldn't find all securityGroups, nameOrIDs: [sg group one sg-id1 sg-id404], found: [sg-id1 sg-0912f63b]"),
317+
wantErr: errors.New("couldn't find all securityGroups, requested names: [sg group one, sg group two], found: [sg group one]"),
250318
},
251319
}
252320

0 commit comments

Comments
 (0)