Skip to content

Commit a8fc753

Browse files
(Backport v0.37.x)fix: prevent hash collisions while resolving subnets, security groups and AMIs from nodeclass selectors (#8665)
Co-authored-by: Saurav Agarwalla <[email protected]>
1 parent 31fd259 commit a8fc753

File tree

18 files changed

+675
-150
lines changed

18 files changed

+675
-150
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20240229193347-cfab22a10647
1212
github.com/awslabs/operatorpkg v0.0.0-20240518001059-1e35978ba21b
1313
github.com/go-logr/zapr v1.3.0
14+
github.com/google/uuid v1.6.0
1415
github.com/imdario/mergo v0.3.16
1516
github.com/mitchellh/hashstructure/v2 v2.0.2
1617
github.com/onsi/ginkgo/v2 v2.20.0
@@ -64,7 +65,6 @@ require (
6465
github.com/google/go-cmp v0.6.0 // indirect
6566
github.com/google/gofuzz v1.2.0 // indirect
6667
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
67-
github.com/google/uuid v1.6.0 // indirect
6868
github.com/grpc-ecosystem/grpc-gateway/v2 v2.21.0 // indirect
6969
github.com/hashicorp/golang-lru v1.0.2 // indirect
7070
github.com/inconshreveable/mousetrap v1.1.0 // indirect

pkg/cloudprovider/suite_test.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ var _ = Describe("CloudProvider", func() {
618618
},
619619
},
620620
})
621-
awsEnv.EC2API.DescribeSecurityGroupsOutput.Set(&ec2.DescribeSecurityGroupsOutput{
621+
awsEnv.EC2API.DescribeSecurityGroupsBehavior.Output.Set(&ec2.DescribeSecurityGroupsOutput{
622622
SecurityGroups: []*ec2.SecurityGroup{
623623
{
624624
GroupId: aws.String(validSecurityGroup),
@@ -632,7 +632,7 @@ var _ = Describe("CloudProvider", func() {
632632
},
633633
},
634634
})
635-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{
635+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{
636636
Subnets: []*ec2.Subnet{
637637
{
638638
SubnetId: aws.String(validSubnet1),
@@ -1084,7 +1084,7 @@ var _ = Describe("CloudProvider", func() {
10841084
})
10851085
It("should launch instances into subnet with the most available IP addresses", func() {
10861086
awsEnv.SubnetCache.Flush()
1087-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
1087+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
10881088
{SubnetId: aws.String("test-subnet-1"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(10),
10891089
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}}},
10901090
{SubnetId: aws.String("test-subnet-2"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(100),
@@ -1101,7 +1101,7 @@ var _ = Describe("CloudProvider", func() {
11011101
})
11021102
It("should launch instances into subnet with the most available IP addresses in-between cache refreshes", func() {
11031103
awsEnv.SubnetCache.Flush()
1104-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
1104+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
11051105
{SubnetId: aws.String("test-subnet-1"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(10),
11061106
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}}},
11071107
{SubnetId: aws.String("test-subnet-2"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(11),
@@ -1126,7 +1126,7 @@ var _ = Describe("CloudProvider", func() {
11261126
Expect(fake.SubnetsFromFleetRequest(createFleetInput)).To(ConsistOf("test-subnet-1"))
11271127
})
11281128
It("should update in-flight IPs when a CreateFleet error occurs", func() {
1129-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
1129+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
11301130
{SubnetId: aws.String("test-subnet-1"), AvailabilityZone: aws.String("test-zone-1a"), AvailableIpAddressCount: aws.Int64(10),
11311131
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}}},
11321132
}})
@@ -1137,12 +1137,20 @@ var _ = Describe("CloudProvider", func() {
11371137
Expect(len(bindings)).To(Equal(0))
11381138
})
11391139
It("should launch instances into subnets that are excluded by another NodePool", func() {
1140-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
1141-
{SubnetId: aws.String("test-subnet-1"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(10),
1142-
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}}},
1143-
{SubnetId: aws.String("test-subnet-2"), AvailabilityZone: aws.String("test-zone-1b"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(100),
1144-
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-2")}}},
1145-
}})
1140+
awsEnv.EC2API.Subnets.Store("test-zone-1a", &ec2.Subnet{
1141+
SubnetId: aws.String("test-subnet-1"),
1142+
AvailabilityZone: aws.String("test-zone-1a"),
1143+
AvailabilityZoneId: aws.String("tstz1-1a"),
1144+
AvailableIpAddressCount: aws.Int64(10),
1145+
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}},
1146+
})
1147+
awsEnv.EC2API.Subnets.Store("test-zone-1b", &ec2.Subnet{
1148+
SubnetId: aws.String("test-subnet-2"),
1149+
AvailabilityZone: aws.String("test-zone-1b"),
1150+
AvailabilityZoneId: aws.String("tstz1-1a"),
1151+
AvailableIpAddressCount: aws.Int64(100),
1152+
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-2")}},
1153+
})
11461154
nodeClass.Spec.SubnetSelectorTerms = []v1beta1.SubnetSelectorTerm{{Tags: map[string]string{"Name": "test-subnet-1"}}}
11471155
ExpectApplied(ctx, env.Client, nodePool, nodeClass)
11481156
controller := status.NewController(env.Client, awsEnv.SubnetProvider, awsEnv.SecurityGroupProvider, awsEnv.AMIProvider, awsEnv.InstanceProfileProvider, awsEnv.LaunchTemplateProvider)

pkg/controllers/nodeclass/status/subnet_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ var _ = Describe("NodeClass Subnet Status Controller", func() {
7777
}))
7878
})
7979
It("Should have the correct ordering for the Subnets", func() {
80-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
80+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
8181
{SubnetId: aws.String("subnet-test1"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(20)},
8282
{SubnetId: aws.String("subnet-test2"), AvailabilityZone: aws.String("test-zone-1b"), AvailabilityZoneId: aws.String("tstz1-1b"), AvailableIpAddressCount: aws.Int64(100)},
8383
{SubnetId: aws.String("subnet-test3"), AvailabilityZone: aws.String("test-zone-1c"), AvailabilityZoneId: aws.String("tstz1-1c"), AvailableIpAddressCount: aws.Int64(50)},

pkg/controllers/providers/ssm/invalidation/controller.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import (
2525
"sigs.k8s.io/karpenter/pkg/operator/controller"
2626
"sigs.k8s.io/karpenter/pkg/operator/injection"
2727

28+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+
"k8s.io/apimachinery/pkg/util/uuid"
30+
2831
"github.com/aws/karpenter-provider-aws/pkg/apis/v1beta1"
2932
"github.com/aws/karpenter-provider-aws/pkg/providers/amifamily"
3033
"github.com/aws/karpenter-provider-aws/pkg/providers/ssm"
@@ -65,6 +68,9 @@ func (c *Controller) Reconcile(ctx context.Context, _ reconcile.Request) (reconc
6568
amis := []amifamily.AMI{}
6669
for _, nodeClass := range lo.Map(lo.Keys(amiIDsToParameters), func(amiID string, _ int) *v1beta1.EC2NodeClass {
6770
return &v1beta1.EC2NodeClass{
71+
ObjectMeta: metav1.ObjectMeta{
72+
UID: uuid.NewUUID(), // ensures that this doesn't hit the AMI cache.
73+
},
6874
Spec: v1beta1.EC2NodeClassSpec{
6975
AMISelectorTerms: []v1beta1.AMISelectorTerm{{ID: amiID}},
7076
},

pkg/controllers/providers/ssm/invalidation/suite_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ var _ = Describe("SSM Invalidation Controller", func() {
8787
Expect(err).To(BeNil())
8888
currentEntries := getSSMCacheEntries()
8989
Expect(len(currentEntries)).To(Equal(2))
90-
awsEnv.EC2Cache.Flush()
90+
awsEnv.AMICache.Flush()
9191
ExpectReconcileSucceeded(ctx, invalidationController, client.ObjectKey{})
9292
awsEnv.SSMAPI.Reset()
9393
_, err = awsEnv.AMIProvider.List(ctx, nodeClass)
@@ -106,7 +106,7 @@ var _ = Describe("SSM Invalidation Controller", func() {
106106
currentEntries := getSSMCacheEntries()
107107
deprecateAMIs(lo.Values(currentEntries)...)
108108
Expect(len(currentEntries)).To(Equal(2))
109-
awsEnv.EC2Cache.Flush()
109+
awsEnv.AMICache.Flush()
110110
ExpectReconcileSucceeded(ctx, invalidationController, client.ObjectKey{})
111111
awsEnv.SSMAPI.Reset()
112112
_, err = awsEnv.AMIProvider.List(ctx, nodeClass)

pkg/fake/atomic.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@ func (a *AtomicPtrSlice[T]) Pop() *T {
161161
return last
162162
}
163163

164+
func (a *AtomicPtrSlice[T]) At(index int) *T {
165+
a.mu.Lock()
166+
defer a.mu.Unlock()
167+
168+
return clone(a.values[index])
169+
}
170+
164171
func (a *AtomicPtrSlice[T]) ForEach(fn func(*T)) {
165172
a.mu.RLock()
166173
defer a.mu.RUnlock()

pkg/fake/ec2api.go

Lines changed: 98 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ type CapacityPool struct {
4848
type EC2Behavior struct {
4949
DescribeImagesOutput AtomicPtr[ec2.DescribeImagesOutput]
5050
DescribeLaunchTemplatesOutput AtomicPtr[ec2.DescribeLaunchTemplatesOutput]
51-
DescribeSubnetsOutput AtomicPtr[ec2.DescribeSubnetsOutput]
52-
DescribeSecurityGroupsOutput AtomicPtr[ec2.DescribeSecurityGroupsOutput]
51+
DescribeSubnetsBehavior MockedFunction[ec2.DescribeSubnetsInput, ec2.DescribeSubnetsOutput]
52+
DescribeSecurityGroupsBehavior MockedFunction[ec2.DescribeSecurityGroupsInput, ec2.DescribeSecurityGroupsOutput]
5353
DescribeInstanceTypesOutput AtomicPtr[ec2.DescribeInstanceTypesOutput]
5454
DescribeInstanceTypeOfferingsOutput AtomicPtr[ec2.DescribeInstanceTypeOfferingsOutput]
5555
DescribeAvailabilityZonesOutput AtomicPtr[ec2.DescribeAvailabilityZonesOutput]
@@ -61,6 +61,7 @@ type EC2Behavior struct {
6161
CreateTagsBehavior MockedFunction[ec2.CreateTagsInput, ec2.CreateTagsOutput]
6262
CalledWithCreateLaunchTemplateInput AtomicPtrSlice[ec2.CreateLaunchTemplateInput]
6363
CalledWithDescribeImagesInput AtomicPtrSlice[ec2.DescribeImagesInput]
64+
Subnets sync.Map
6465
Instances sync.Map
6566
LaunchTemplates sync.Map
6667
InsufficientCapacityPools atomic.Slice[CapacityPool]
@@ -84,8 +85,8 @@ var DefaultSupportedUsageClasses = aws.StringSlice([]string{"on-demand", "spot"}
8485
func (e *EC2API) Reset() {
8586
e.DescribeImagesOutput.Reset()
8687
e.DescribeLaunchTemplatesOutput.Reset()
87-
e.DescribeSubnetsOutput.Reset()
88-
e.DescribeSecurityGroupsOutput.Reset()
88+
e.DescribeSubnetsBehavior.Reset()
89+
e.DescribeSecurityGroupsBehavior.Reset()
8990
e.DescribeInstanceTypesOutput.Reset()
9091
e.DescribeInstanceTypeOfferingsOutput.Reset()
9192
e.DescribeAvailabilityZonesOutput.Reset()
@@ -405,107 +406,109 @@ func (e *EC2API) DeleteLaunchTemplateWithContext(_ context.Context, input *ec2.D
405406
}
406407

407408
func (e *EC2API) DescribeSubnetsWithContext(_ context.Context, input *ec2.DescribeSubnetsInput, _ ...request.Option) (*ec2.DescribeSubnetsOutput, error) {
408-
if !e.NextError.IsNil() {
409-
defer e.NextError.Reset()
410-
return nil, e.NextError.Get()
411-
}
412-
if !e.DescribeSubnetsOutput.IsNil() {
413-
describeSubnetsOutput := e.DescribeSubnetsOutput.Clone()
414-
describeSubnetsOutput.Subnets = FilterDescribeSubnets(describeSubnetsOutput.Subnets, input.Filters)
415-
return describeSubnetsOutput, nil
416-
}
417-
subnets := []*ec2.Subnet{
418-
{
419-
SubnetId: aws.String("subnet-test1"),
420-
AvailabilityZone: aws.String("test-zone-1a"),
421-
AvailabilityZoneId: aws.String("tstz1-1a"),
422-
AvailableIpAddressCount: aws.Int64(100),
423-
MapPublicIpOnLaunch: aws.Bool(false),
424-
Tags: []*ec2.Tag{
425-
{Key: aws.String("Name"), Value: aws.String("test-subnet-1")},
426-
{Key: aws.String("foo"), Value: aws.String("bar")},
409+
return e.DescribeSubnetsBehavior.Invoke(input, func(input *ec2.DescribeSubnetsInput) (*ec2.DescribeSubnetsOutput, error) {
410+
output := &ec2.DescribeSubnetsOutput{}
411+
e.Subnets.Range(func(key, value any) bool {
412+
subnet := value.(*ec2.Subnet)
413+
if lo.Contains(lo.Map(input.SubnetIds, func(s *string, _ int) string { return lo.FromPtr(s) }), lo.FromPtr(subnet.SubnetId)) || len(input.Filters) != 0 && len(FilterDescribeSubnets([]*ec2.Subnet{subnet}, input.Filters)) != 0 {
414+
output.Subnets = append(output.Subnets, subnet)
415+
}
416+
return true
417+
})
418+
if len(output.Subnets) != 0 {
419+
return output, nil
420+
}
421+
422+
defaultSubnets := []*ec2.Subnet{
423+
{
424+
SubnetId: aws.String("subnet-test1"),
425+
AvailabilityZone: aws.String("test-zone-1a"),
426+
AvailabilityZoneId: aws.String("tstz1-1a"),
427+
AvailableIpAddressCount: aws.Int64(100),
428+
MapPublicIpOnLaunch: aws.Bool(false),
429+
Tags: []*ec2.Tag{
430+
{Key: aws.String("Name"), Value: aws.String("test-subnet-1")},
431+
{Key: aws.String("foo"), Value: aws.String("bar")},
432+
},
433+
VpcId: aws.String("vpc-test1"),
427434
},
428-
},
429-
{
430-
SubnetId: aws.String("subnet-test2"),
431-
AvailabilityZone: aws.String("test-zone-1b"),
432-
AvailabilityZoneId: aws.String("tstz1-1b"),
433-
AvailableIpAddressCount: aws.Int64(100),
434-
MapPublicIpOnLaunch: aws.Bool(true),
435-
Tags: []*ec2.Tag{
436-
{Key: aws.String("Name"), Value: aws.String("test-subnet-2")},
437-
{Key: aws.String("foo"), Value: aws.String("bar")},
435+
{
436+
SubnetId: aws.String("subnet-test2"),
437+
AvailabilityZone: aws.String("test-zone-1b"),
438+
AvailabilityZoneId: aws.String("tstz1-1b"),
439+
AvailableIpAddressCount: aws.Int64(100),
440+
MapPublicIpOnLaunch: aws.Bool(true),
441+
Tags: []*ec2.Tag{
442+
{Key: aws.String("Name"), Value: aws.String("test-subnet-2")},
443+
{Key: aws.String("foo"), Value: aws.String("bar")},
444+
},
445+
VpcId: aws.String("vpc-test1"),
438446
},
439-
},
440-
{
441-
SubnetId: aws.String("subnet-test3"),
442-
AvailabilityZone: aws.String("test-zone-1c"),
443-
AvailabilityZoneId: aws.String("tstz1-1c"),
444-
AvailableIpAddressCount: aws.Int64(100),
445-
Tags: []*ec2.Tag{
446-
{Key: aws.String("Name"), Value: aws.String("test-subnet-3")},
447-
{Key: aws.String("TestTag")},
448-
{Key: aws.String("foo"), Value: aws.String("bar")},
447+
{
448+
SubnetId: aws.String("subnet-test3"),
449+
AvailabilityZone: aws.String("test-zone-1c"),
450+
AvailabilityZoneId: aws.String("tstz1-1c"),
451+
AvailableIpAddressCount: aws.Int64(100),
452+
Tags: []*ec2.Tag{
453+
{Key: aws.String("Name"), Value: aws.String("test-subnet-3")},
454+
{Key: aws.String("TestTag")},
455+
{Key: aws.String("foo"), Value: aws.String("bar")},
456+
},
457+
VpcId: aws.String("vpc-test1"),
449458
},
450-
},
451-
{
452-
SubnetId: aws.String("subnet-test4"),
453-
AvailabilityZone: aws.String("test-zone-1a-local"),
454-
AvailabilityZoneId: aws.String("tstz1-1alocal"),
455-
AvailableIpAddressCount: aws.Int64(100),
456-
MapPublicIpOnLaunch: aws.Bool(true),
457-
Tags: []*ec2.Tag{
458-
{Key: aws.String("Name"), Value: aws.String("test-subnet-4")},
459+
{
460+
SubnetId: aws.String("subnet-test4"),
461+
AvailabilityZone: aws.String("test-zone-1a-local"),
462+
AvailabilityZoneId: aws.String("tstz1-1alocal"),
463+
AvailableIpAddressCount: aws.Int64(100),
464+
MapPublicIpOnLaunch: aws.Bool(true),
465+
Tags: []*ec2.Tag{
466+
{Key: aws.String("Name"), Value: aws.String("test-subnet-4")},
467+
},
468+
VpcId: aws.String("vpc-test1"),
459469
},
460-
},
461-
}
462-
if len(input.Filters) == 0 {
463-
return nil, fmt.Errorf("InvalidParameterValue: The filter 'null' is invalid")
464-
}
465-
return &ec2.DescribeSubnetsOutput{Subnets: FilterDescribeSubnets(subnets, input.Filters)}, nil
470+
}
471+
if len(input.Filters) == 0 {
472+
return nil, fmt.Errorf("InvalidParameterValue: The filter 'null' is invalid")
473+
}
474+
return &ec2.DescribeSubnetsOutput{Subnets: FilterDescribeSubnets(defaultSubnets, input.Filters)}, nil
475+
})
466476
}
467477

468478
func (e *EC2API) DescribeSecurityGroupsWithContext(_ context.Context, input *ec2.DescribeSecurityGroupsInput, _ ...request.Option) (*ec2.DescribeSecurityGroupsOutput, error) {
469-
if !e.NextError.IsNil() {
470-
defer e.NextError.Reset()
471-
return nil, e.NextError.Get()
472-
}
473-
if !e.DescribeSecurityGroupsOutput.IsNil() {
474-
describeSecurityGroupsOutput := e.DescribeSecurityGroupsOutput.Clone()
475-
describeSecurityGroupsOutput.SecurityGroups = FilterDescribeSecurtyGroups(describeSecurityGroupsOutput.SecurityGroups, input.Filters)
476-
return e.DescribeSecurityGroupsOutput.Clone(), nil
477-
}
478-
sgs := []*ec2.SecurityGroup{
479-
{
480-
GroupId: aws.String("sg-test1"),
481-
GroupName: aws.String("securityGroup-test1"),
482-
Tags: []*ec2.Tag{
483-
{Key: aws.String("Name"), Value: aws.String("test-security-group-1")},
484-
{Key: aws.String("foo"), Value: aws.String("bar")},
479+
return e.DescribeSecurityGroupsBehavior.Invoke(input, func(input *ec2.DescribeSecurityGroupsInput) (*ec2.DescribeSecurityGroupsOutput, error) {
480+
defaultSecurityGroups := []*ec2.SecurityGroup{
481+
{
482+
GroupId: aws.String("sg-test1"),
483+
GroupName: aws.String("securityGroup-test1"),
484+
Tags: []*ec2.Tag{
485+
{Key: aws.String("Name"), Value: aws.String("test-security-group-1")},
486+
{Key: aws.String("foo"), Value: aws.String("bar")},
487+
},
485488
},
486-
},
487-
{
488-
GroupId: aws.String("sg-test2"),
489-
GroupName: aws.String("securityGroup-test2"),
490-
Tags: []*ec2.Tag{
491-
{Key: aws.String("Name"), Value: aws.String("test-security-group-2")},
492-
{Key: aws.String("foo"), Value: aws.String("bar")},
489+
{
490+
GroupId: aws.String("sg-test2"),
491+
GroupName: aws.String("securityGroup-test2"),
492+
Tags: []*ec2.Tag{
493+
{Key: aws.String("Name"), Value: aws.String("test-security-group-2")},
494+
{Key: aws.String("foo"), Value: aws.String("bar")},
495+
},
493496
},
494-
},
495-
{
496-
GroupId: aws.String("sg-test3"),
497-
GroupName: aws.String("securityGroup-test3"),
498-
Tags: []*ec2.Tag{
499-
{Key: aws.String("Name"), Value: aws.String("test-security-group-3")},
500-
{Key: aws.String("TestTag")},
501-
{Key: aws.String("foo"), Value: aws.String("bar")},
497+
{
498+
GroupId: aws.String("sg-test3"),
499+
GroupName: aws.String("securityGroup-test3"),
500+
Tags: []*ec2.Tag{
501+
{Key: aws.String("Name"), Value: aws.String("test-security-group-3")},
502+
{Key: aws.String("TestTag")},
503+
{Key: aws.String("foo"), Value: aws.String("bar")},
504+
},
502505
},
503-
},
504-
}
505-
if len(input.Filters) == 0 {
506-
return nil, fmt.Errorf("InvalidParameterValue: The filter 'null' is invalid")
507-
}
508-
return &ec2.DescribeSecurityGroupsOutput{SecurityGroups: FilterDescribeSecurtyGroups(sgs, input.Filters)}, nil
506+
}
507+
if len(input.Filters) == 0 {
508+
return nil, fmt.Errorf("InvalidParameterValue: The filter 'null' is invalid")
509+
}
510+
return &ec2.DescribeSecurityGroupsOutput{SecurityGroups: FilterDescribeSecurtyGroups(defaultSecurityGroups, input.Filters)}, nil
511+
})
509512
}
510513

511514
func (e *EC2API) DescribeAvailabilityZonesWithContext(context.Context, *ec2.DescribeAvailabilityZonesInput, ...request.Option) (*ec2.DescribeAvailabilityZonesOutput, error) {

0 commit comments

Comments
 (0)