sigs.k8s.io/cluster-api-provider-aws@v1.5.5/controllers/awscluster_controller_test.go (about) 1 /* 2 Copyright 2019 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 package controllers 17 18 import ( 19 "context" 20 "fmt" 21 "testing" 22 "time" 23 24 "github.com/aws/aws-sdk-go/aws" 25 "github.com/aws/aws-sdk-go/service/ec2" 26 "github.com/golang/mock/gomock" 27 . "github.com/onsi/gomega" 28 "github.com/pkg/errors" 29 corev1 "k8s.io/api/core/v1" 30 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 "k8s.io/client-go/tools/record" 32 "sigs.k8s.io/controller-runtime/pkg/client" 33 34 infrav1 "sigs.k8s.io/cluster-api-provider-aws/api/v1beta1" 35 "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" 36 "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services" 37 ec2Service "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2" 38 elbService "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb" 39 "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/network" 40 "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/securitygroup" 41 "sigs.k8s.io/cluster-api-provider-aws/test/mocks" 42 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 43 "sigs.k8s.io/cluster-api/util" 44 ) 45 46 func TestAWSClusterReconciler_IntegrationTests(t *testing.T) { 47 var ( 48 reconciler AWSClusterReconciler 49 mockCtrl *gomock.Controller 50 recorder *record.FakeRecorder 51 ctx context.Context 52 ) 53 54 setup := func(t *testing.T) { 55 t.Helper() 56 mockCtrl = gomock.NewController(t) 57 recorder = record.NewFakeRecorder(10) 58 reconciler = AWSClusterReconciler{ 59 Client: testEnv.Client, 60 Recorder: recorder, 61 } 62 ctx = context.TODO() 63 } 64 65 teardown := func() { 66 mockCtrl.Finish() 67 } 68 69 t.Run("Should successfully reconcile AWSCluster creation with unmanaged VPC", func(t *testing.T) { 70 g := NewWithT(t) 71 mockCtrl = gomock.NewController(t) 72 ec2Mock := mocks.NewMockEC2API(mockCtrl) 73 elbMock := mocks.NewMockELBAPI(mockCtrl) 74 expect := func(m *mocks.MockEC2APIMockRecorder, e *mocks.MockELBAPIMockRecorder) { 75 mockedCreateVPCCalls(m) 76 mockedCreateSGCalls(m) 77 mockedCreateLBCalls(t, e) 78 mockedDescribeInstanceCall(m) 79 } 80 expect(ec2Mock.EXPECT(), elbMock.EXPECT()) 81 82 setup(t) 83 controllerIdentity := createControllerIdentity(g) 84 ns, err := testEnv.CreateNamespace(ctx, fmt.Sprintf("integ-test-%s", util.RandomString(5))) 85 g.Expect(err).To(BeNil()) 86 87 awsCluster := getAWSCluster("test", ns.Name) 88 89 g.Expect(testEnv.Create(ctx, &awsCluster)).To(Succeed()) 90 g.Eventually(func() bool { 91 cluster := &infrav1.AWSCluster{} 92 key := client.ObjectKey{ 93 Name: awsCluster.Name, 94 Namespace: ns.Name, 95 } 96 err := testEnv.Get(ctx, key, cluster) 97 return err == nil 98 }, 10*time.Second).Should(Equal(true)) 99 100 defer teardown() 101 defer t.Cleanup(func() { 102 g.Expect(testEnv.Cleanup(ctx, &awsCluster, controllerIdentity, ns)).To(Succeed()) 103 }) 104 105 cs, err := getClusterScope(awsCluster) 106 g.Expect(err).To(BeNil()) 107 networkSvc := network.NewService(cs) 108 networkSvc.EC2Client = ec2Mock 109 reconciler.networkServiceFactory = func(clusterScope scope.ClusterScope) services.NetworkInterface { 110 return networkSvc 111 } 112 113 ec2Svc := ec2Service.NewService(cs) 114 ec2Svc.EC2Client = ec2Mock 115 reconciler.ec2ServiceFactory = func(scope scope.EC2Scope) services.EC2Interface { 116 return ec2Svc 117 } 118 testSecurityGroupRoles := []infrav1.SecurityGroupRole{ 119 infrav1.SecurityGroupBastion, 120 infrav1.SecurityGroupAPIServerLB, 121 infrav1.SecurityGroupLB, 122 infrav1.SecurityGroupControlPlane, 123 infrav1.SecurityGroupNode, 124 } 125 sgSvc := securitygroup.NewService(cs, testSecurityGroupRoles) 126 sgSvc.EC2Client = ec2Mock 127 128 reconciler.securityGroupFactory = func(clusterScope scope.ClusterScope) services.SecurityGroupInterface { 129 return sgSvc 130 } 131 elbSvc := elbService.NewService(cs) 132 elbSvc.EC2Client = ec2Mock 133 elbSvc.ELBClient = elbMock 134 135 reconciler.elbServiceFactory = func(elbScope scope.ELBScope) services.ELBInterface { 136 return elbSvc 137 } 138 cs.SetSubnets([]infrav1.SubnetSpec{ 139 { 140 ID: "subnet-2", 141 AvailabilityZone: "us-east-1c", 142 IsPublic: true, 143 CidrBlock: "10.0.11.0/24", 144 }, 145 { 146 ID: "subnet-1", 147 AvailabilityZone: "us-east-1a", 148 CidrBlock: "10.0.10.0/24", 149 IsPublic: false, 150 }, 151 }) 152 _, err = reconciler.reconcileNormal(cs) 153 g.Expect(err).To(BeNil()) 154 g.Expect(cs.VPC().ID).To(Equal("vpc-exists")) 155 expectAWSClusterConditions(g, cs.AWSCluster, []conditionAssertion{ 156 {conditionType: infrav1.ClusterSecurityGroupsReadyCondition, status: corev1.ConditionTrue, severity: "", reason: ""}, 157 {conditionType: infrav1.BastionHostReadyCondition, status: corev1.ConditionTrue, severity: "", reason: ""}, 158 {conditionType: infrav1.VpcReadyCondition, status: corev1.ConditionTrue, severity: "", reason: ""}, 159 {conditionType: infrav1.SubnetsReadyCondition, status: corev1.ConditionTrue, severity: "", reason: ""}, 160 }) 161 }) 162 t.Run("Should fail on AWSCluster reconciliation if VPC limit exceeded", func(t *testing.T) { 163 // Assuming the max VPC limit is 2 and when two VPCs are created, the creation of 3rd VPC throws mocked error from EC2 API 164 g := NewWithT(t) 165 mockCtrl = gomock.NewController(t) 166 ec2Mock := mocks.NewMockEC2API(mockCtrl) 167 expect := func(m *mocks.MockEC2APIMockRecorder) { 168 mockedCreateMaximumVPCCalls(m) 169 } 170 expect(ec2Mock.EXPECT()) 171 172 setup(t) 173 controllerIdentity := createControllerIdentity(g) 174 ns, err := testEnv.CreateNamespace(ctx, fmt.Sprintf("integ-test-%s", util.RandomString(5))) 175 g.Expect(err).To(BeNil()) 176 awsCluster := infrav1.AWSCluster{ 177 ObjectMeta: metav1.ObjectMeta{ 178 Name: "test", 179 Namespace: ns.Name, 180 }, 181 Spec: infrav1.AWSClusterSpec{ 182 Region: "us-east-1", 183 }, 184 } 185 g.Expect(testEnv.Create(ctx, &awsCluster)).To(Succeed()) 186 187 defer teardown() 188 g.Eventually(func() bool { 189 cluster := &infrav1.AWSCluster{} 190 key := client.ObjectKey{ 191 Name: awsCluster.Name, 192 Namespace: ns.Name, 193 } 194 err := testEnv.Get(ctx, key, cluster) 195 return err == nil 196 }, 10*time.Second).Should(Equal(true)) 197 defer t.Cleanup(func() { 198 g.Expect(testEnv.Cleanup(ctx, &awsCluster, controllerIdentity, ns)).To(Succeed()) 199 }) 200 cs, err := getClusterScope(awsCluster) 201 g.Expect(err).To(BeNil()) 202 s := network.NewService(cs) 203 s.EC2Client = ec2Mock 204 205 reconciler.networkServiceFactory = func(clusterScope scope.ClusterScope) services.NetworkInterface { 206 return s 207 } 208 _, err = reconciler.reconcileNormal(cs) 209 g.Expect(err.Error()).To(ContainSubstring("The maximum number of VPCs has been reached")) 210 }) 211 t.Run("Should successfully delete AWSCluster with managed VPC", func(t *testing.T) { 212 g := NewWithT(t) 213 214 mockCtrl = gomock.NewController(t) 215 ec2Mock := mocks.NewMockEC2API(mockCtrl) 216 elbMock := mocks.NewMockELBAPI(mockCtrl) 217 expect := func(m *mocks.MockEC2APIMockRecorder, e *mocks.MockELBAPIMockRecorder) { 218 mockedDeleteVPCCalls(m) 219 mockedDescribeInstanceCall(m) 220 mockedDeleteLBCalls(e) 221 mockedDeleteInstanceCalls(m) 222 mockedDeleteSGCalls(m) 223 } 224 expect(ec2Mock.EXPECT(), elbMock.EXPECT()) 225 226 setup(t) 227 controllerIdentity := createControllerIdentity(g) 228 ns, err := testEnv.CreateNamespace(ctx, fmt.Sprintf("integ-test-%s", util.RandomString(5))) 229 g.Expect(err).To(BeNil()) 230 awsCluster := getAWSCluster("test", ns.Name) 231 232 g.Expect(testEnv.Create(ctx, &awsCluster)).To(Succeed()) 233 defer teardown() 234 g.Eventually(func() bool { 235 cluster := &infrav1.AWSCluster{} 236 key := client.ObjectKey{ 237 Name: awsCluster.Name, 238 Namespace: ns.Name, 239 } 240 err := testEnv.Get(ctx, key, cluster) 241 return err == nil 242 }, 10*time.Second).Should(Equal(true)) 243 244 defer t.Cleanup(func() { 245 g.Expect(testEnv.Cleanup(ctx, &awsCluster, controllerIdentity, ns)).To(Succeed()) 246 }) 247 248 cs, err := getClusterScope(awsCluster) 249 g.Expect(err).To(BeNil()) 250 251 networkSvc := network.NewService(cs) 252 networkSvc.EC2Client = ec2Mock 253 reconciler.networkServiceFactory = func(clusterScope scope.ClusterScope) services.NetworkInterface { 254 return networkSvc 255 } 256 257 ec2Svc := ec2Service.NewService(cs) 258 ec2Svc.EC2Client = ec2Mock 259 reconciler.ec2ServiceFactory = func(ec2Scope scope.EC2Scope) services.EC2Interface { 260 return ec2Svc 261 } 262 263 elbSvc := elbService.NewService(cs) 264 elbSvc.EC2Client = ec2Mock 265 elbSvc.ELBClient = elbMock 266 reconciler.elbServiceFactory = func(elbScope scope.ELBScope) services.ELBInterface { 267 return elbSvc 268 } 269 270 testSecurityGroupRoles := []infrav1.SecurityGroupRole{ 271 infrav1.SecurityGroupBastion, 272 infrav1.SecurityGroupAPIServerLB, 273 infrav1.SecurityGroupLB, 274 infrav1.SecurityGroupControlPlane, 275 infrav1.SecurityGroupNode, 276 } 277 sgSvc := securitygroup.NewService(cs, testSecurityGroupRoles) 278 sgSvc.EC2Client = ec2Mock 279 reconciler.securityGroupFactory = func(clusterScope scope.ClusterScope) services.SecurityGroupInterface { 280 return sgSvc 281 } 282 283 _, err = reconciler.reconcileDelete(ctx, cs) 284 g.Expect(err).To(BeNil()) 285 expectAWSClusterConditions(g, cs.AWSCluster, []conditionAssertion{{infrav1.LoadBalancerReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}, 286 {infrav1.BastionHostReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}, 287 {infrav1.SecondaryCidrsReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletingReason}, 288 {infrav1.RouteTablesReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}, 289 {infrav1.NatGatewaysReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}, 290 {infrav1.InternetGatewayReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}, 291 {infrav1.SubnetsReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}, 292 {infrav1.VpcReadyCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, clusterv1.DeletedReason}, 293 }) 294 }) 295 } 296 297 func mockedDeleteSGCalls(m *mocks.MockEC2APIMockRecorder) { 298 m.DescribeSecurityGroupsPages(gomock.Any(), gomock.Any()).Return(nil) 299 } 300 301 func createControllerIdentity(g *WithT) *infrav1.AWSClusterControllerIdentity { 302 controllerIdentity := &infrav1.AWSClusterControllerIdentity{ 303 TypeMeta: metav1.TypeMeta{ 304 Kind: string(infrav1.ControllerIdentityKind), 305 }, 306 ObjectMeta: metav1.ObjectMeta{ 307 Name: "default", 308 }, 309 Spec: infrav1.AWSClusterControllerIdentitySpec{ 310 AWSClusterIdentitySpec: infrav1.AWSClusterIdentitySpec{ 311 AllowedNamespaces: &infrav1.AllowedNamespaces{}, 312 }, 313 }, 314 } 315 g.Expect(testEnv.Create(ctx, controllerIdentity)).To(Succeed()) 316 return controllerIdentity 317 } 318 319 func mockedDescribeInstanceCall(m *mocks.MockEC2APIMockRecorder) { 320 m.DescribeInstances(gomock.Eq(&ec2.DescribeInstancesInput{ 321 Filters: []*ec2.Filter{ 322 { 323 Name: aws.String("tag:sigs.k8s.io/cluster-api-provider-aws/role"), 324 Values: aws.StringSlice([]string{"bastion"}), 325 }, 326 { 327 Name: aws.String("tag-key"), 328 Values: aws.StringSlice([]string{"sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"}), 329 }, 330 { 331 Name: aws.String("instance-state-name"), 332 Values: aws.StringSlice([]string{"pending", "running", "stopping", "stopped"}), 333 }, 334 }, 335 })).Return(&ec2.DescribeInstancesOutput{ 336 Reservations: []*ec2.Reservation{ 337 { 338 Instances: []*ec2.Instance{ 339 { 340 InstanceId: aws.String("id-1"), 341 InstanceType: aws.String("m5.large"), 342 SubnetId: aws.String("subnet-1"), 343 ImageId: aws.String("ami-1"), 344 IamInstanceProfile: &ec2.IamInstanceProfile{ 345 Arn: aws.String("arn:aws:iam::123456789012:instance-profile/foo"), 346 }, 347 State: &ec2.InstanceState{ 348 Code: aws.Int64(16), 349 Name: aws.String(ec2.StateAvailable), 350 }, 351 RootDeviceName: aws.String("device-1"), 352 BlockDeviceMappings: []*ec2.InstanceBlockDeviceMapping{ 353 { 354 DeviceName: aws.String("device-1"), 355 Ebs: &ec2.EbsInstanceBlockDevice{ 356 VolumeId: aws.String("volume-1"), 357 }, 358 }, 359 }, 360 Placement: &ec2.Placement{ 361 AvailabilityZone: aws.String("us-east-1a"), 362 }, 363 }, 364 }, 365 }, 366 }, 367 }, nil) 368 } 369 370 func mockedDeleteInstanceCalls(m *mocks.MockEC2APIMockRecorder) { 371 m.TerminateInstances( 372 gomock.Eq(&ec2.TerminateInstancesInput{ 373 InstanceIds: aws.StringSlice([]string{"id-1"}), 374 }), 375 ). 376 Return(nil, nil) 377 m.WaitUntilInstanceTerminated( 378 gomock.Eq(&ec2.DescribeInstancesInput{ 379 InstanceIds: aws.StringSlice([]string{"id-1"}), 380 }), 381 ). 382 Return(nil) 383 } 384 385 func mockedCreateVPCCalls(m *mocks.MockEC2APIMockRecorder) { 386 m.CreateTags(gomock.Eq(&ec2.CreateTagsInput{ 387 Resources: aws.StringSlice([]string{"subnet-1"}), 388 Tags: []*ec2.Tag{ 389 { 390 Key: aws.String("kubernetes.io/cluster/test-cluster"), 391 Value: aws.String("shared"), 392 }, 393 { 394 Key: aws.String("kubernetes.io/role/internal-elb"), 395 Value: aws.String("1"), 396 }, 397 }, 398 })).Return(&ec2.CreateTagsOutput{}, nil) 399 m.CreateTags(gomock.Eq(&ec2.CreateTagsInput{ 400 Resources: aws.StringSlice([]string{"subnet-2"}), 401 Tags: []*ec2.Tag{ 402 { 403 Key: aws.String("kubernetes.io/cluster/test-cluster"), 404 Value: aws.String("shared"), 405 }, 406 { 407 Key: aws.String("kubernetes.io/role/elb"), 408 Value: aws.String("1"), 409 }, 410 }, 411 })).Return(&ec2.CreateTagsOutput{}, nil).AnyTimes() 412 m.CreateTags(gomock.Eq(&ec2.CreateTagsInput{ 413 Resources: aws.StringSlice([]string{"subnet-2"}), 414 Tags: []*ec2.Tag{ 415 { 416 Key: aws.String("Name"), 417 Value: aws.String("test-cluster-subnet-public-us-east-1c"), 418 }, 419 { 420 Key: aws.String("kubernetes.io/cluster/test-cluster"), 421 Value: aws.String("shared"), 422 }, 423 { 424 Key: aws.String("kubernetes.io/role/internal-elb"), 425 Value: aws.String("1"), 426 }, 427 { 428 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 429 Value: aws.String("owned"), 430 }, 431 { 432 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 433 Value: aws.String("public"), 434 }, 435 }, 436 })).Return(&ec2.CreateTagsOutput{}, nil).AnyTimes() 437 m.CreateSubnet(gomock.Eq(&ec2.CreateSubnetInput{ 438 VpcId: aws.String("vpc-exists"), 439 CidrBlock: aws.String("10.0.11.0/24"), 440 AvailabilityZone: aws.String("us-east-1c"), 441 TagSpecifications: []*ec2.TagSpecification{ 442 { 443 ResourceType: aws.String("subnet"), 444 Tags: []*ec2.Tag{ 445 { 446 Key: aws.String("Name"), 447 Value: aws.String("test-cluster-subnet-public-us-east-1c"), 448 }, 449 { 450 Key: aws.String("kubernetes.io/cluster/test-cluster"), 451 Value: aws.String("shared"), 452 }, 453 { 454 Key: aws.String("kubernetes.io/role/internal-elb"), 455 Value: aws.String("1"), 456 }, 457 { 458 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 459 Value: aws.String("owned"), 460 }, 461 { 462 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 463 Value: aws.String("public"), 464 }, 465 }, 466 }, 467 }, 468 })).Return(&ec2.CreateSubnetOutput{ 469 Subnet: &ec2.Subnet{ 470 VpcId: aws.String("vpc-exists"), 471 SubnetId: aws.String("subnet-2"), 472 CidrBlock: aws.String("10.0.11.0/24"), 473 AvailabilityZone: aws.String("us-east-1c"), 474 MapPublicIpOnLaunch: aws.Bool(false), 475 Tags: []*ec2.Tag{ 476 { 477 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 478 Value: aws.String("owned"), 479 }, 480 { 481 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 482 Value: aws.String("public"), 483 }, 484 { 485 Key: aws.String("Name"), 486 Value: aws.String("test-cluster-subnet-public"), 487 }, 488 { 489 Key: aws.String("kubernetes.io/cluster/test-cluster"), 490 Value: aws.String("shared"), 491 }, 492 }, 493 }, 494 }, nil).AnyTimes() 495 m.DescribeSubnets(gomock.Eq(&ec2.DescribeSubnetsInput{ 496 Filters: []*ec2.Filter{ 497 { 498 Name: aws.String("state"), 499 Values: aws.StringSlice([]string{ec2.VpcStatePending, ec2.VpcStateAvailable}), 500 }, 501 { 502 Name: aws.String("vpc-id"), 503 Values: aws.StringSlice([]string{"vpc-exists"}), 504 }, 505 }})).Return(&ec2.DescribeSubnetsOutput{ 506 Subnets: []*ec2.Subnet{ 507 { 508 VpcId: aws.String("vpc-exists"), 509 SubnetId: aws.String("subnet-1"), 510 AvailabilityZone: aws.String("us-east-1a"), 511 CidrBlock: aws.String("10.0.10.0/24"), 512 MapPublicIpOnLaunch: aws.Bool(false), 513 }, 514 { 515 VpcId: aws.String("vpc-exists"), 516 SubnetId: aws.String("subnet-2"), 517 AvailabilityZone: aws.String("us-east-1c"), 518 CidrBlock: aws.String("10.0.11.0/24"), 519 MapPublicIpOnLaunch: aws.Bool(false), 520 Tags: []*ec2.Tag{ 521 { 522 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 523 Value: aws.String("owned"), 524 }, 525 { 526 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 527 Value: aws.String("public"), 528 }, 529 { 530 Key: aws.String("Name"), 531 Value: aws.String("test-cluster-subnet-public"), 532 }, 533 { 534 Key: aws.String("kubernetes.io/cluster/test-cluster"), 535 Value: aws.String("shared"), 536 }, 537 }, 538 }, 539 }, 540 }, nil) 541 m.DescribeRouteTables(gomock.Eq(&ec2.DescribeRouteTablesInput{ 542 Filters: []*ec2.Filter{ 543 { 544 Name: aws.String("vpc-id"), 545 Values: aws.StringSlice([]string{"vpc-exists"}), 546 }, 547 }})).Return(&ec2.DescribeRouteTablesOutput{ 548 RouteTables: []*ec2.RouteTable{ 549 { 550 Routes: []*ec2.Route{ 551 { 552 GatewayId: aws.String("igw-12345"), 553 }, 554 }, 555 }, 556 }, 557 }, nil) 558 m.DescribeNatGatewaysPages(gomock.Eq(&ec2.DescribeNatGatewaysInput{ 559 Filter: []*ec2.Filter{ 560 { 561 Name: aws.String("vpc-id"), 562 Values: []*string{aws.String("vpc-exists")}, 563 }, 564 { 565 Name: aws.String("state"), 566 Values: aws.StringSlice([]string{ec2.VpcStatePending, ec2.VpcStateAvailable}), 567 }, 568 }}), gomock.Any()).Return(nil) 569 m.DescribeVpcs(gomock.Eq(&ec2.DescribeVpcsInput{ 570 VpcIds: []*string{ 571 aws.String("vpc-exists"), 572 }, 573 Filters: []*ec2.Filter{ 574 { 575 Name: aws.String("state"), 576 Values: aws.StringSlice([]string{ec2.VpcStatePending, ec2.VpcStateAvailable}), 577 }, 578 }, 579 })). 580 Return(&ec2.DescribeVpcsOutput{ 581 Vpcs: []*ec2.Vpc{ 582 { 583 State: aws.String("available"), 584 VpcId: aws.String("vpc-exists"), 585 CidrBlock: aws.String("10.0.0.0/8"), 586 Tags: []*ec2.Tag{ 587 { 588 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 589 Value: aws.String("common"), 590 }, 591 { 592 Key: aws.String("Name"), 593 Value: aws.String("test-cluster"), 594 }, 595 }, 596 }, 597 }, 598 }, nil) 599 } 600 601 func mockedCreateMaximumVPCCalls(m *mocks.MockEC2APIMockRecorder) { 602 m.CreateVpc(gomock.AssignableToTypeOf(&ec2.CreateVpcInput{})).Return(nil, errors.New("The maximum number of VPCs has been reached")) 603 } 604 605 func mockedDeleteVPCCalls(m *mocks.MockEC2APIMockRecorder) { 606 m.DescribeSubnets(gomock.Eq(&ec2.DescribeSubnetsInput{ 607 Filters: []*ec2.Filter{ 608 { 609 Name: aws.String("state"), 610 Values: aws.StringSlice([]string{ec2.VpcStatePending, ec2.VpcStateAvailable}), 611 }, 612 { 613 Name: aws.String("vpc-id"), 614 Values: aws.StringSlice([]string{"vpc-exists"}), 615 }, 616 }})).Return(&ec2.DescribeSubnetsOutput{ 617 Subnets: []*ec2.Subnet{ 618 { 619 VpcId: aws.String("vpc-exists"), 620 SubnetId: aws.String("subnet-1"), 621 AvailabilityZone: aws.String("us-east-1a"), 622 CidrBlock: aws.String("10.0.10.0/24"), 623 MapPublicIpOnLaunch: aws.Bool(false), 624 }, 625 }, 626 }, nil).AnyTimes() 627 m.DescribeRouteTables(gomock.Eq(&ec2.DescribeRouteTablesInput{ 628 Filters: []*ec2.Filter{ 629 { 630 Name: aws.String("vpc-id"), 631 Values: aws.StringSlice([]string{"vpc-exists"}), 632 }, 633 { 634 Name: aws.String("tag-key"), 635 Values: aws.StringSlice([]string{"sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"}), 636 }, 637 }})).Return(&ec2.DescribeRouteTablesOutput{ 638 RouteTables: []*ec2.RouteTable{ 639 { 640 Routes: []*ec2.Route{ 641 { 642 GatewayId: aws.String("igw-12345"), 643 }, 644 }, 645 RouteTableId: aws.String("rt-12345"), 646 }, 647 }, 648 }, nil).AnyTimes() 649 m.DeleteRouteTable(gomock.Eq(&ec2.DeleteRouteTableInput{ 650 RouteTableId: aws.String("rt-12345"), 651 })) 652 m.DescribeInternetGateways(gomock.Eq(&ec2.DescribeInternetGatewaysInput{ 653 Filters: []*ec2.Filter{ 654 { 655 Name: aws.String("attachment.vpc-id"), 656 Values: aws.StringSlice([]string{"vpc-exists"}), 657 }, 658 }, 659 })).Return(&ec2.DescribeInternetGatewaysOutput{ 660 InternetGateways: []*ec2.InternetGateway{ 661 { 662 Attachments: nil, 663 InternetGatewayId: aws.String("ig-12345"), 664 }, 665 }, 666 }, nil) 667 m.DetachInternetGateway(gomock.Eq(&ec2.DetachInternetGatewayInput{ 668 VpcId: aws.String("vpc-exists"), 669 InternetGatewayId: aws.String("ig-12345"), 670 })) 671 m.DeleteInternetGateway(gomock.Eq(&ec2.DeleteInternetGatewayInput{ 672 InternetGatewayId: aws.String("ig-12345"), 673 })) 674 m.DescribeNatGatewaysPages(gomock.Eq(&ec2.DescribeNatGatewaysInput{ 675 Filter: []*ec2.Filter{ 676 { 677 Name: aws.String("vpc-id"), 678 Values: []*string{aws.String("vpc-exists")}, 679 }, 680 { 681 Name: aws.String("state"), 682 Values: aws.StringSlice([]string{ec2.VpcStatePending, ec2.VpcStateAvailable}), 683 }, 684 }}), gomock.Any()).Return(nil).AnyTimes() 685 m.DescribeAddresses(gomock.Eq(&ec2.DescribeAddressesInput{ 686 Filters: []*ec2.Filter{ 687 { 688 Name: aws.String("tag-key"), 689 Values: aws.StringSlice([]string{"sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"}), 690 }}, 691 })).Return(&ec2.DescribeAddressesOutput{ 692 Addresses: []*ec2.Address{ 693 { 694 AssociationId: aws.String("1234"), 695 AllocationId: aws.String("1234"), 696 PublicIp: aws.String("1.2.3.4"), 697 }, 698 }, 699 }, nil) 700 m.DisassociateAddress(&ec2.DisassociateAddressInput{ 701 AssociationId: aws.String("1234"), 702 }) 703 m.ReleaseAddress(&ec2.ReleaseAddressInput{ 704 AllocationId: aws.String("1234"), 705 }) 706 m.DescribeVpcs(gomock.Eq(&ec2.DescribeVpcsInput{ 707 VpcIds: []*string{ 708 aws.String("vpc-exists"), 709 }, 710 Filters: []*ec2.Filter{ 711 { 712 Name: aws.String("state"), 713 Values: aws.StringSlice([]string{ec2.VpcStatePending, ec2.VpcStateAvailable}), 714 }, 715 }, 716 })). 717 Return(&ec2.DescribeVpcsOutput{ 718 Vpcs: []*ec2.Vpc{ 719 { 720 State: aws.String("available"), 721 VpcId: aws.String("vpc-exists"), 722 CidrBlock: aws.String("10.0.0.0/8"), 723 Tags: []*ec2.Tag{ 724 { 725 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 726 Value: aws.String("common"), 727 }, 728 { 729 Key: aws.String("Name"), 730 Value: aws.String("test-cluster"), 731 }, 732 { 733 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 734 Value: aws.String("owned"), 735 }, 736 }, 737 }, 738 }, 739 }, nil) 740 m.DeleteSubnet(gomock.Eq(&ec2.DeleteSubnetInput{ 741 SubnetId: aws.String("subnet-1"), 742 })) 743 m.DeleteVpc(gomock.Eq(&ec2.DeleteVpcInput{ 744 VpcId: aws.String("vpc-exists"), 745 })) 746 } 747 748 func mockedCreateSGCalls(m *mocks.MockEC2APIMockRecorder) { 749 m.DescribeSecurityGroups(gomock.Eq(&ec2.DescribeSecurityGroupsInput{ 750 Filters: []*ec2.Filter{ 751 { 752 Name: aws.String("vpc-id"), 753 Values: aws.StringSlice([]string{"vpc-exists"}), 754 }, 755 { 756 Name: aws.String("tag-key"), 757 Values: aws.StringSlice([]string{"sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"}), 758 }, 759 }, 760 })).Return( 761 &ec2.DescribeSecurityGroupsOutput{ 762 SecurityGroups: []*ec2.SecurityGroup{ 763 { 764 GroupId: aws.String("1"), 765 GroupName: aws.String("test-sg"), 766 }, 767 }, 768 }, nil) 769 m.CreateSecurityGroup(gomock.Eq(&ec2.CreateSecurityGroupInput{ 770 VpcId: aws.String("vpc-exists"), 771 GroupName: aws.String("test-cluster-bastion"), 772 Description: aws.String("Kubernetes cluster test-cluster: bastion"), 773 TagSpecifications: []*ec2.TagSpecification{ 774 { 775 ResourceType: aws.String("security-group"), 776 Tags: []*ec2.Tag{ 777 { 778 Key: aws.String("Name"), 779 Value: aws.String("test-cluster-bastion"), 780 }, 781 { 782 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 783 Value: aws.String("owned"), 784 }, 785 { 786 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 787 Value: aws.String("bastion"), 788 }, 789 }, 790 }, 791 }, 792 })). 793 Return(&ec2.CreateSecurityGroupOutput{GroupId: aws.String("sg-bastion")}, nil) 794 m.CreateSecurityGroup(gomock.Eq(&ec2.CreateSecurityGroupInput{ 795 VpcId: aws.String("vpc-exists"), 796 GroupName: aws.String("test-cluster-apiserver-lb"), 797 Description: aws.String("Kubernetes cluster test-cluster: apiserver-lb"), 798 TagSpecifications: []*ec2.TagSpecification{ 799 { 800 ResourceType: aws.String("security-group"), 801 Tags: []*ec2.Tag{ 802 { 803 Key: aws.String("Name"), 804 Value: aws.String("test-cluster-apiserver-lb"), 805 }, 806 { 807 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 808 Value: aws.String("owned"), 809 }, 810 { 811 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 812 Value: aws.String("apiserver-lb"), 813 }, 814 }, 815 }, 816 }, 817 })). 818 Return(&ec2.CreateSecurityGroupOutput{GroupId: aws.String("sg-apiserver-lb")}, nil) 819 m.CreateSecurityGroup(gomock.Eq(&ec2.CreateSecurityGroupInput{ 820 VpcId: aws.String("vpc-exists"), 821 GroupName: aws.String("test-cluster-lb"), 822 Description: aws.String("Kubernetes cluster test-cluster: lb"), 823 TagSpecifications: []*ec2.TagSpecification{ 824 { 825 ResourceType: aws.String("security-group"), 826 Tags: []*ec2.Tag{ 827 { 828 Key: aws.String("Name"), 829 Value: aws.String("test-cluster-lb"), 830 }, 831 { 832 Key: aws.String("kubernetes.io/cluster/test-cluster"), 833 Value: aws.String("owned"), 834 }, 835 { 836 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 837 Value: aws.String("owned"), 838 }, 839 { 840 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 841 Value: aws.String("lb"), 842 }, 843 }, 844 }, 845 }, 846 })). 847 Return(&ec2.CreateSecurityGroupOutput{GroupId: aws.String("sg-lb")}, nil) 848 securityGroupControl := m.CreateSecurityGroup(gomock.Eq(&ec2.CreateSecurityGroupInput{ 849 VpcId: aws.String("vpc-exists"), 850 GroupName: aws.String("test-cluster-controlplane"), 851 Description: aws.String("Kubernetes cluster test-cluster: controlplane"), 852 TagSpecifications: []*ec2.TagSpecification{ 853 { 854 ResourceType: aws.String("security-group"), 855 Tags: []*ec2.Tag{ 856 { 857 Key: aws.String("Name"), 858 Value: aws.String("test-cluster-controlplane"), 859 }, 860 { 861 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 862 Value: aws.String("owned"), 863 }, 864 { 865 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 866 Value: aws.String("controlplane"), 867 }, 868 }, 869 }, 870 }, 871 })). 872 Return(&ec2.CreateSecurityGroupOutput{GroupId: aws.String("sg-controlplane")}, nil) 873 securityGroupNode := m.CreateSecurityGroup(gomock.Eq(&ec2.CreateSecurityGroupInput{ 874 VpcId: aws.String("vpc-exists"), 875 GroupName: aws.String("test-cluster-node"), 876 Description: aws.String("Kubernetes cluster test-cluster: node"), 877 TagSpecifications: []*ec2.TagSpecification{ 878 { 879 ResourceType: aws.String("security-group"), 880 Tags: []*ec2.Tag{ 881 { 882 Key: aws.String("Name"), 883 Value: aws.String("test-cluster-node"), 884 }, 885 { 886 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"), 887 Value: aws.String("owned"), 888 }, 889 { 890 Key: aws.String("sigs.k8s.io/cluster-api-provider-aws/role"), 891 Value: aws.String("node"), 892 }, 893 }, 894 }, 895 }, 896 })). 897 Return(&ec2.CreateSecurityGroupOutput{GroupId: aws.String("sg-node")}, nil) 898 m.AuthorizeSecurityGroupIngress(gomock.AssignableToTypeOf(&ec2.AuthorizeSecurityGroupIngressInput{ 899 GroupId: aws.String("sg-controlplane"), 900 })). 901 Return(&ec2.AuthorizeSecurityGroupIngressOutput{}, nil). 902 After(securityGroupControl).Times(2) 903 m.AuthorizeSecurityGroupIngress(gomock.AssignableToTypeOf(&ec2.AuthorizeSecurityGroupIngressInput{ 904 GroupId: aws.String("sg-node"), 905 })). 906 Return(&ec2.AuthorizeSecurityGroupIngressOutput{}, nil). 907 After(securityGroupNode).Times(2) 908 }