Skip to content

Commit 03ae34e

Browse files
committed
Fix SG deletion (SGs are cluster owned, not provider owned)
1 parent 74c0fb0 commit 03ae34e

File tree

2 files changed

+125
-2
lines changed

2 files changed

+125
-2
lines changed

pkg/cloud/services/securitygroup/securitygroups.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ func (s *Service) describeClusterOwnedSecurityGroups() ([]infrav1.SecurityGroup,
326326
input := &ec2.DescribeSecurityGroupsInput{
327327
Filters: []*ec2.Filter{
328328
filter.EC2.VPC(s.scope.VPC().ID),
329-
filter.EC2.ProviderOwned(s.scope.Name()),
329+
filter.EC2.ClusterOwned(s.scope.Name()),
330330
},
331331
}
332332

pkg/cloud/services/securitygroup/securitygroups_test.go

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@ limitations under the License.
1717
package securitygroup
1818

1919
import (
20-
"github.com/pkg/errors"
20+
"context"
2121
"strings"
2222
"testing"
2323

2424
"github.com/aws/aws-sdk-go/aws"
2525
"github.com/aws/aws-sdk-go/service/ec2"
2626
"github.com/golang/mock/gomock"
27+
"github.com/pkg/errors"
2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+
"k8s.io/apimachinery/pkg/runtime"
2830
"k8s.io/apimachinery/pkg/util/sets"
2931
infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1alpha3"
3032
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope"
3133
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services"
3234
"sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2/mock_ec2iface"
3335
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
36+
"sigs.k8s.io/controller-runtime/pkg/client/fake"
3437
)
3538

3639
func TestReconcileSecurityGroups(t *testing.T) {
@@ -385,3 +388,123 @@ func TestControlPlaneSecurityGroupNotOpenToAnyCIDR(t *testing.T) {
385388
}
386389
}
387390
}
391+
392+
func TestDeleteSecurityGroups(t *testing.T) {
393+
mockCtrl := gomock.NewController(t)
394+
defer mockCtrl.Finish()
395+
396+
testCases := []struct {
397+
name string
398+
input *infrav1.NetworkSpec
399+
expect func(m *mock_ec2iface.MockEC2APIMockRecorder)
400+
err error
401+
}{
402+
{
403+
name: "do not delete overridden security groups, only delete 'owned' SGs",
404+
input: &infrav1.NetworkSpec{
405+
VPC: infrav1.VPCSpec{
406+
ID: "vpc-securitygroups",
407+
InternetGatewayID: aws.String("igw-01"),
408+
},
409+
Subnets: infrav1.Subnets{
410+
&infrav1.SubnetSpec{
411+
ID: "subnet-securitygroups-private",
412+
IsPublic: false,
413+
AvailabilityZone: "us-east-1a",
414+
},
415+
&infrav1.SubnetSpec{
416+
ID: "subnet-securitygroups-public",
417+
IsPublic: true,
418+
NatGatewayID: aws.String("nat-01"),
419+
AvailabilityZone: "us-east-1a",
420+
},
421+
},
422+
SecurityGroupOverrides: map[infrav1.SecurityGroupRole]string{
423+
infrav1.SecurityGroupBastion: "sg-bastion",
424+
infrav1.SecurityGroupAPIServerLB: "sg-apiserver-lb",
425+
infrav1.SecurityGroupLB: "sg-lb",
426+
infrav1.SecurityGroupControlPlane: "sg-control",
427+
infrav1.SecurityGroupNode: "sg-node",
428+
},
429+
},
430+
expect: func(m *mock_ec2iface.MockEC2APIMockRecorder) {
431+
m.DescribeSecurityGroupsPages(gomock.Any(), gomock.Any()).Do(func(_, y interface{}) {
432+
funct := y.(func(output *ec2.DescribeSecurityGroupsOutput, lastPage bool) bool)
433+
funct(&ec2.DescribeSecurityGroupsOutput{
434+
SecurityGroups: []*ec2.SecurityGroup{
435+
{
436+
GroupName: aws.String("sg-bastion"),
437+
GroupId: aws.String("sg-bastion"),
438+
439+
Tags: []*ec2.Tag{
440+
{
441+
Key: aws.String("Name"),
442+
Value: aws.String("test-cluster-nat"),
443+
},
444+
{
445+
Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"),
446+
Value: aws.String("owned"),
447+
},
448+
{
449+
Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"),
450+
Value: aws.String("common"),
451+
},
452+
},
453+
},
454+
},
455+
}, true)
456+
}).Return(nil)
457+
458+
m.DescribeSecurityGroups(gomock.Any()).Return(&ec2.DescribeSecurityGroupsOutput{}, nil)
459+
m.DeleteSecurityGroup(gomock.Any()).Return(nil, nil)
460+
},
461+
},
462+
}
463+
464+
for _, tc := range testCases {
465+
t.Run(tc.name, func(t *testing.T) {
466+
ec2Mock := mock_ec2iface.NewMockEC2API(mockCtrl)
467+
468+
scheme := runtime.NewScheme()
469+
_ = infrav1.AddToScheme(scheme)
470+
awsCluster := &infrav1.AWSCluster{
471+
TypeMeta: metav1.TypeMeta{
472+
APIVersion: infrav1.GroupVersion.String(),
473+
Kind: "AWSCluster",
474+
},
475+
ObjectMeta: metav1.ObjectMeta{Name: "test"},
476+
Spec: infrav1.AWSClusterSpec{
477+
NetworkSpec: *tc.input,
478+
},
479+
}
480+
client := fake.NewFakeClientWithScheme(scheme, awsCluster)
481+
482+
ctx := context.TODO()
483+
client.Create(ctx, awsCluster)
484+
485+
scope, err := scope.NewClusterScope(scope.ClusterScopeParams{
486+
Client: client,
487+
Cluster: &clusterv1.Cluster{
488+
ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"},
489+
},
490+
AWSCluster: awsCluster,
491+
})
492+
if err != nil {
493+
t.Fatalf("Failed to create test context: %v", err)
494+
}
495+
496+
tc.expect(ec2Mock.EXPECT())
497+
498+
s := NewService(scope)
499+
s.EC2Client = ec2Mock
500+
501+
if err := s.DeleteSecurityGroups(); err != nil && tc.err != nil {
502+
if !strings.Contains(err.Error(), tc.err.Error()) {
503+
t.Fatalf("was expecting error to look like '%v', but got '%v'", tc.err, err)
504+
}
505+
} else if err != nil {
506+
t.Fatalf("got an unexpected error: %v", err)
507+
}
508+
})
509+
}
510+
}

0 commit comments

Comments
 (0)