Skip to content

Commit 8bd9a3d

Browse files
(Backport v1.0.x)fix: prevent hash collisions while resolving subnets, security groups and AMIs from nodeclass selectors (#8664)
Co-authored-by: Saurav Agarwalla <saurav-agarwalla@users.noreply.github.com>
1 parent a88b5ef commit 8bd9a3d

File tree

17 files changed

+671
-146
lines changed

17 files changed

+671
-146
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-20240805231134-67d0acfb6306
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/jonathan-innis/aws-sdk-go-prometheus v0.1.1-0.20240804232425-54c8227e0bab
1617
github.com/mitchellh/hashstructure/v2 v2.0.2
@@ -65,7 +66,6 @@ require (
6566
github.com/google/go-cmp v0.6.0 // indirect
6667
github.com/google/gofuzz v1.2.0 // indirect
6768
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
68-
github.com/google/uuid v1.6.0 // indirect
6969
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
7070
github.com/hashicorp/golang-lru v1.0.2 // indirect
7171
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
@@ -651,7 +651,7 @@ var _ = Describe("CloudProvider", func() {
651651
},
652652
},
653653
})
654-
awsEnv.EC2API.DescribeSecurityGroupsOutput.Set(&ec2.DescribeSecurityGroupsOutput{
654+
awsEnv.EC2API.DescribeSecurityGroupsBehavior.Output.Set(&ec2.DescribeSecurityGroupsOutput{
655655
SecurityGroups: []*ec2.SecurityGroup{
656656
{
657657
GroupId: aws.String(validSecurityGroup),
@@ -665,7 +665,7 @@ var _ = Describe("CloudProvider", func() {
665665
},
666666
},
667667
})
668-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{
668+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{
669669
Subnets: []*ec2.Subnet{
670670
{
671671
SubnetId: aws.String(validSubnet1),
@@ -1129,7 +1129,7 @@ var _ = Describe("CloudProvider", func() {
11291129
})
11301130
It("should launch instances into subnet with the most available IP addresses", func() {
11311131
awsEnv.SubnetCache.Flush()
1132-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
1132+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
11331133
{SubnetId: aws.String("test-subnet-1"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(10),
11341134
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}}},
11351135
{SubnetId: aws.String("test-subnet-2"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(100),
@@ -1146,7 +1146,7 @@ var _ = Describe("CloudProvider", func() {
11461146
})
11471147
It("should launch instances into subnet with the most available IP addresses in-between cache refreshes", func() {
11481148
awsEnv.SubnetCache.Flush()
1149-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
1149+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
11501150
{SubnetId: aws.String("test-subnet-1"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(10),
11511151
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}}},
11521152
{SubnetId: aws.String("test-subnet-2"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(11),
@@ -1174,7 +1174,7 @@ var _ = Describe("CloudProvider", func() {
11741174
Expect(fake.SubnetsFromFleetRequest(createFleetInput)).To(ConsistOf("test-subnet-1"))
11751175
})
11761176
It("should update in-flight IPs when a CreateFleet error occurs", func() {
1177-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
1177+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
11781178
{SubnetId: aws.String("test-subnet-1"), AvailabilityZone: aws.String("test-zone-1a"), AvailableIpAddressCount: aws.Int64(10),
11791179
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}}},
11801180
}})
@@ -1185,12 +1185,20 @@ var _ = Describe("CloudProvider", func() {
11851185
Expect(len(bindings)).To(Equal(0))
11861186
})
11871187
It("should launch instances into subnets that are excluded by another NodePool", func() {
1188-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
1189-
{SubnetId: aws.String("test-subnet-1"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(10),
1190-
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}}},
1191-
{SubnetId: aws.String("test-subnet-2"), AvailabilityZone: aws.String("test-zone-1b"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(100),
1192-
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-2")}}},
1193-
}})
1188+
awsEnv.EC2API.Subnets.Store("test-zone-1a", &ec2.Subnet{
1189+
SubnetId: aws.String("test-subnet-1"),
1190+
AvailabilityZone: aws.String("test-zone-1a"),
1191+
AvailabilityZoneId: aws.String("tstz1-1a"),
1192+
AvailableIpAddressCount: aws.Int64(10),
1193+
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-1")}},
1194+
})
1195+
awsEnv.EC2API.Subnets.Store("test-zone-1b", &ec2.Subnet{
1196+
SubnetId: aws.String("test-subnet-2"),
1197+
AvailabilityZone: aws.String("test-zone-1b"),
1198+
AvailabilityZoneId: aws.String("tstz1-1a"),
1199+
AvailableIpAddressCount: aws.Int64(100),
1200+
Tags: []*ec2.Tag{{Key: aws.String("Name"), Value: aws.String("test-subnet-2")}},
1201+
})
11941202
nodeClass.Spec.SubnetSelectorTerms = []v1.SubnetSelectorTerm{{Tags: map[string]string{"Name": "test-subnet-1"}}}
11951203
ExpectApplied(ctx, env.Client, nodePool, nodeClass)
11961204
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
@@ -79,7 +79,7 @@ var _ = Describe("NodeClass Subnet Status Controller", func() {
7979
Expect(nodeClass.StatusConditions().IsTrue(v1.ConditionTypeSubnetsReady)).To(BeTrue())
8080
})
8181
It("Should have the correct ordering for the Subnets", func() {
82-
awsEnv.EC2API.DescribeSubnetsOutput.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
82+
awsEnv.EC2API.DescribeSubnetsBehavior.Output.Set(&ec2.DescribeSubnetsOutput{Subnets: []*ec2.Subnet{
8383
{SubnetId: aws.String("subnet-test1"), AvailabilityZone: aws.String("test-zone-1a"), AvailabilityZoneId: aws.String("tstz1-1a"), AvailableIpAddressCount: aws.Int64(20)},
8484
{SubnetId: aws.String("subnet-test2"), AvailabilityZone: aws.String("test-zone-1b"), AvailabilityZoneId: aws.String("tstz1-1b"), AvailableIpAddressCount: aws.Int64(100)},
8585
{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
@@ -29,6 +29,9 @@ import (
2929
v1 "github.com/aws/karpenter-provider-aws/pkg/apis/v1"
3030
"github.com/aws/karpenter-provider-aws/pkg/providers/amifamily"
3131
"github.com/aws/karpenter-provider-aws/pkg/providers/ssm"
32+
33+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34+
"k8s.io/apimachinery/pkg/util/uuid"
3235
)
3336

3437
// The SSM Invalidation controller is responsible for invalidating "latest" SSM parameters when they point to deprecated
@@ -66,6 +69,9 @@ func (c *Controller) Reconcile(ctx context.Context) (reconcile.Result, error) {
6669
amis := []amifamily.AMI{}
6770
for _, nodeClass := range lo.Map(lo.Keys(amiIDsToParameters), func(amiID string, _ int) *v1.EC2NodeClass {
6871
return &v1.EC2NodeClass{
72+
ObjectMeta: metav1.ObjectMeta{
73+
UID: uuid.NewUUID(), // ensures that this doesn't hit the AMI cache.
74+
},
6975
Spec: v1.EC2NodeClassSpec{
7076
AMISelectorTerms: []v1.AMISelectorTerm{{ID: amiID}},
7177
},

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)