Repository: kubernetes-sigs/cluster-api-provider-aws
Pull request #4518 (2023-09-26 14:10:51)

🌱 Tag S3 bucket as owned by cluster
**What type of PR is this?**

/kind feature

**What this PR does / why we need it**:

I noticed that the S3 bucket isn't tagged. Some companies use AWS tags for grouping resources, calculating costs, or to clean up accidental remainders of clusters that CAPI/CAPA couldn't delete after a misconfiguration. With this change, the bucket is tagged as belonging to the cluster.

I'm not entirely sure if there's a use case where people provide a shared S3 bucket. In the S3 service code, there's such a hint in a `TODO`. For that case, we would need to introduce `AWSCluster.spec.s3Bucket.additionalTags` where users can set `sigs.k8s.io/cluster-api-provider-aws/cluster/...=shared`. And the implementation should be changed to only upsert tags instead of overwriting them, given that multiple `AWSCluster` objects could reconcile the same bucket. Let me know if that's a supported use case.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:

n/a

**Checklist**:
<!-- Put an "X" character inside the brackets of each completed task. Some may be optional depending on the PR in which case these can be deleted -->

- [x] squashed commits
- [ ] includes documentation
- [x] adds unit tests
- [ ] adds or updates e2e tests

**Release note**:
<!--  Write your release note:
1. Enter your extended release note in the below block. If the PR requires additional action from users switching to the new release, include the string "action required".
2. If no release note is required, just write "NONE".
-->
```release-note
Tag S3 bucket as owned by the cluster
```



Patch:
diff --git a/cmd/clusterawsadm/cloudformation/bootstrap/cluster_api_controller.go b/cmd/clusterawsadm/cloudformation/bootstrap/cluster_api_controller.go
index be5342628..616e60d16 100644
--- a/cmd/clusterawsadm/cloudformation/bootstrap/cluster_api_controller.go
+++ b/cmd/clusterawsadm/cloudformation/bootstrap/cluster_api_controller.go
@@ -283,6 +283,7 @@ func (t Template) ControllersPolicy() *iamv1.PolicyDocument {
 				"s3:PutObject",
 				"s3:DeleteObject",
 				"s3:PutBucketPolicy",
+				"s3:PutBucketTagging",
 			},
 		})
 	}
diff --git a/cmd/clusterawsadm/cloudformation/bootstrap/fixtures/with_s3_bucket.yaml b/cmd/clusterawsadm/cloudformation/bootstrap/fixtures/with_s3_bucket.yaml
index d4c881789..a045a10bf 100644
--- a/cmd/clusterawsadm/cloudformation/bootstrap/fixtures/with_s3_bucket.yaml
+++ b/cmd/clusterawsadm/cloudformation/bootstrap/fixtures/with_s3_bucket.yaml
@@ -288,6 +288,7 @@ Resources:
           - s3:PutObject
           - s3:DeleteObject
           - s3:PutBucketPolicy
+          - s3:PutBucketTagging
           Effect: Allow
           Resource:
           - arn:*:s3:::cluster-api-provider-aws-*
diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml
index 127a0baf2..f49fa9af8 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml
@@ -533,14 +533,6 @@ spec:
                 description: AdditionalTags is an optional set of tags to add to an
                   instance, in addition to the ones added by default by the AWS provider.
                 type: object
-              availabilityZoneSubnetType:
-                description: AvailabilityZoneSubnetType specifies which type of subnets
-                  to use when an availability zone is specified.
-                enum:
-                - public
-                - private
-                - all
-                type: string
               availabilityZones:
                 description: AvailabilityZones is an array of availability zones instances
                   can run in
diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml
index 14e588c1b..0ddc44155 100644
--- a/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml
+++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml
@@ -519,14 +519,6 @@ spec:
                   version will be used
                 minLength: 2
                 type: string
-              availabilityZoneSubnetType:
-                description: AvailabilityZoneSubnetType specifies which type of subnets
-                  to use when an availability zone is specified.
-                enum:
-                - public
-                - private
-                - all
-                type: string
               availabilityZones:
                 description: AvailabilityZones is an array of availability zones instances
                   can run in
diff --git a/exp/api/v1beta1/conversion.go b/exp/api/v1beta1/conversion.go
index db54099fd..1e4304eb1 100644
--- a/exp/api/v1beta1/conversion.go
+++ b/exp/api/v1beta1/conversion.go
@@ -47,9 +47,6 @@ func (src *AWSMachinePool) ConvertTo(dstRaw conversion.Hub) error {
 	if restored.Spec.AWSLaunchTemplate.InstanceMetadataOptions != nil {
 		dst.Spec.AWSLaunchTemplate.InstanceMetadataOptions = restored.Spec.AWSLaunchTemplate.InstanceMetadataOptions
 	}
-	if restored.Spec.AvailabilityZoneSubnetType != nil {
-		dst.Spec.AvailabilityZoneSubnetType = restored.Spec.AvailabilityZoneSubnetType
-	}
 
 	return nil
 }
@@ -96,9 +93,6 @@ func (src *AWSManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error {
 		}
 		dst.Spec.AWSLaunchTemplate.InstanceMetadataOptions = restored.Spec.AWSLaunchTemplate.InstanceMetadataOptions
 	}
-	if restored.Spec.AvailabilityZoneSubnetType != nil {
-		dst.Spec.AvailabilityZoneSubnetType = restored.Spec.AvailabilityZoneSubnetType
-	}
 
 	return nil
 }
diff --git a/exp/api/v1beta1/zz_generated.conversion.go b/exp/api/v1beta1/zz_generated.conversion.go
index fe8b85def..1e924b46c 100644
--- a/exp/api/v1beta1/zz_generated.conversion.go
+++ b/exp/api/v1beta1/zz_generated.conversion.go
@@ -537,7 +537,6 @@ func autoConvert_v1beta2_AWSMachinePoolSpec_To_v1beta1_AWSMachinePoolSpec(in *v1
 	out.MinSize = in.MinSize
 	out.MaxSize = in.MaxSize
 	out.AvailabilityZones = *(*[]string)(unsafe.Pointer(&in.AvailabilityZones))
-	// WARNING: in.AvailabilityZoneSubnetType requires manual conversion: does not exist in peer-type
 	out.Subnets = *(*[]apiv1beta2.AWSResourceReference)(unsafe.Pointer(&in.Subnets))
 	out.AdditionalTags = *(*apiv1beta2.Tags)(unsafe.Pointer(&in.AdditionalTags))
 	if err := Convert_v1beta2_AWSLaunchTemplate_To_v1beta1_AWSLaunchTemplate(&in.AWSLaunchTemplate, &out.AWSLaunchTemplate, s); err != nil {
@@ -708,7 +707,6 @@ func Convert_v1beta1_AWSManagedMachinePoolSpec_To_v1beta2_AWSManagedMachinePoolS
 func autoConvert_v1beta2_AWSManagedMachinePoolSpec_To_v1beta1_AWSManagedMachinePoolSpec(in *v1beta2.AWSManagedMachinePoolSpec, out *AWSManagedMachinePoolSpec, s conversion.Scope) error {
 	out.EKSNodegroupName = in.EKSNodegroupName
 	out.AvailabilityZones = *(*[]string)(unsafe.Pointer(&in.AvailabilityZones))
-	// WARNING: in.AvailabilityZoneSubnetType requires manual conversion: does not exist in peer-type
 	out.SubnetIDs = *(*[]string)(unsafe.Pointer(&in.SubnetIDs))
 	out.AdditionalTags = *(*apiv1beta2.Tags)(unsafe.Pointer(&in.AdditionalTags))
 	out.RoleAdditionalPolicies = *(*[]string)(unsafe.Pointer(&in.RoleAdditionalPolicies))
diff --git a/exp/api/v1beta2/awsmachinepool_types.go b/exp/api/v1beta2/awsmachinepool_types.go
index 5d0103919..6173f3514 100644
--- a/exp/api/v1beta2/awsmachinepool_types.go
+++ b/exp/api/v1beta2/awsmachinepool_types.go
@@ -52,11 +52,6 @@ type AWSMachinePoolSpec struct {
 	// AvailabilityZones is an array of availability zones instances can run in
 	AvailabilityZones []string `json:"availabilityZones,omitempty"`
 
-	// AvailabilityZoneSubnetType specifies which type of subnets to use when an availability zone is specified.
-	// +kubebuilder:validation:Enum:=public;private;all
-	// +optional
-	AvailabilityZoneSubnetType *AZSubnetType `json:"availabilityZoneSubnetType,omitempty"`
-
 	// Subnets is an array of subnet configurations
 	// +optional
 	Subnets []infrav1.AWSResourceReference `json:"subnets,omitempty"`
diff --git a/exp/api/v1beta2/awsmanagedmachinepool_types.go b/exp/api/v1beta2/awsmanagedmachinepool_types.go
index a9fd346ba..d6ef952db 100644
--- a/exp/api/v1beta2/awsmanagedmachinepool_types.go
+++ b/exp/api/v1beta2/awsmanagedmachinepool_types.go
@@ -68,11 +68,6 @@ type AWSManagedMachinePoolSpec struct {
 	// AvailabilityZones is an array of availability zones instances can run in
 	AvailabilityZones []string `json:"availabilityZones,omitempty"`
 
-	// AvailabilityZoneSubnetType specifies which type of subnets to use when an availability zone is specified.
-	// +kubebuilder:validation:Enum:=public;private;all
-	// +optional
-	AvailabilityZoneSubnetType *AZSubnetType `json:"availabilityZoneSubnetType,omitempty"`
-
 	// SubnetIDs specifies which subnets are used for the
 	// auto scaling group of this nodegroup
 	// +optional
diff --git a/exp/api/v1beta2/awsmanagedmachinepool_webhook.go b/exp/api/v1beta2/awsmanagedmachinepool_webhook.go
index 7f0e782b0..00aeaec6e 100644
--- a/exp/api/v1beta2/awsmanagedmachinepool_webhook.go
+++ b/exp/api/v1beta2/awsmanagedmachinepool_webhook.go
@@ -243,8 +243,6 @@ func (r *AWSManagedMachinePool) validateImmutable(old *AWSManagedMachinePool) fi
 	appendErrorIfMutated(old.Spec.AMIType, r.Spec.AMIType, "amiType")
 	appendErrorIfMutated(old.Spec.RemoteAccess, r.Spec.RemoteAccess, "remoteAccess")
 	appendErrorIfSetAndMutated(old.Spec.CapacityType, r.Spec.CapacityType, "capacityType")
-	appendErrorIfMutated(old.Spec.AvailabilityZones, r.Spec.AvailabilityZones, "availabilityZones")
-	appendErrorIfMutated(old.Spec.AvailabilityZoneSubnetType, r.Spec.AvailabilityZoneSubnetType, "availabilityZoneSubnetType")
 	if (old.Spec.AWSLaunchTemplate != nil && r.Spec.AWSLaunchTemplate == nil) ||
 		(old.Spec.AWSLaunchTemplate == nil && r.Spec.AWSLaunchTemplate != nil) {
 		allErrs = append(
diff --git a/exp/api/v1beta2/types.go b/exp/api/v1beta2/types.go
index 04c824a41..d0fe328ce 100644
--- a/exp/api/v1beta2/types.go
+++ b/exp/api/v1beta2/types.go
@@ -290,20 +290,3 @@ type UpdateConfig struct {
 	// +kubebuilder:validation:Minimum=1
 	MaxUnavailablePercentage *int `json:"maxUnavailablePercentage,omitempty"`
 }
-
-// AZSubnetType is the type of subnet to use when an availability zone is specified.
-type AZSubnetType string
-
-const (
-	// AZSubnetTypePublic is a public subnet.
-	AZSubnetTypePublic AZSubnetType = "public"
-	// AZSubnetTypePrivate is a private subnet.
-	AZSubnetTypePrivate AZSubnetType = "private"
-	// AZSubnetTypeAll is all subnets in an availability zone.
-	AZSubnetTypeAll AZSubnetType = "all"
-)
-
-// NewAZSubnetType returns a pointer to an AZSubnetType.
-func NewAZSubnetType(t AZSubnetType) *AZSubnetType {
-	return &t
-}
diff --git a/exp/api/v1beta2/zz_generated.deepcopy.go b/exp/api/v1beta2/zz_generated.deepcopy.go
index 8dd77518f..0c71e13d5 100644
--- a/exp/api/v1beta2/zz_generated.deepcopy.go
+++ b/exp/api/v1beta2/zz_generated.deepcopy.go
@@ -222,11 +222,6 @@ func (in *AWSMachinePoolSpec) DeepCopyInto(out *AWSMachinePoolSpec) {
 		*out = make([]string, len(*in))
 		copy(*out, *in)
 	}
-	if in.AvailabilityZoneSubnetType != nil {
-		in, out := &in.AvailabilityZoneSubnetType, &out.AvailabilityZoneSubnetType
-		*out = new(AZSubnetType)
-		**out = **in
-	}
 	if in.Subnets != nil {
 		in, out := &in.Subnets, &out.Subnets
 		*out = make([]apiv1beta2.AWSResourceReference, len(*in))
@@ -391,11 +386,6 @@ func (in *AWSManagedMachinePoolSpec) DeepCopyInto(out *AWSManagedMachinePoolSpec
 		*out = make([]string, len(*in))
 		copy(*out, *in)
 	}
-	if in.AvailabilityZoneSubnetType != nil {
-		in, out := &in.AvailabilityZoneSubnetType, &out.AvailabilityZoneSubnetType
-		*out = new(AZSubnetType)
-		**out = **in
-	}
 	if in.SubnetIDs != nil {
 		in, out := &in.SubnetIDs, &out.SubnetIDs
 		*out = make([]string, len(*in))
diff --git a/pkg/cloud/scope/machinepool.go b/pkg/cloud/scope/machinepool.go
index 9a6f9c736..9d2d2935b 100644
--- a/pkg/cloud/scope/machinepool.go
+++ b/pkg/cloud/scope/machinepool.go
@@ -302,7 +302,6 @@ func (m *MachinePoolScope) SubnetIDs(subnetIDs []string) ([]string, error) {
 		SpecAvailabilityZones:   m.AWSMachinePool.Spec.AvailabilityZones,
 		ParentAvailabilityZones: m.MachinePool.Spec.FailureDomains,
 		ControlplaneSubnets:     m.InfraCluster.Subnets(),
-		SubnetPlacementType:     m.AWSMachinePool.Spec.AvailabilityZoneSubnetType,
 	})
 }
 
diff --git a/pkg/cloud/scope/managednodegroup.go b/pkg/cloud/scope/managednodegroup.go
index 448a0eee9..84df59582 100644
--- a/pkg/cloud/scope/managednodegroup.go
+++ b/pkg/cloud/scope/managednodegroup.go
@@ -216,7 +216,6 @@ func (s *ManagedMachinePoolScope) SubnetIDs() ([]string, error) {
 		SpecAvailabilityZones:   s.ManagedMachinePool.Spec.AvailabilityZones,
 		ParentAvailabilityZones: s.MachinePool.Spec.FailureDomains,
 		ControlplaneSubnets:     s.ControlPlaneSubnets(),
-		SubnetPlacementType:     s.ManagedMachinePool.Spec.AvailabilityZoneSubnetType,
 	})
 }
 
diff --git a/pkg/cloud/scope/shared.go b/pkg/cloud/scope/shared.go
index 76e1ec91d..2a472c779 100644
--- a/pkg/cloud/scope/shared.go
+++ b/pkg/cloud/scope/shared.go
@@ -22,7 +22,6 @@ import (
 	"github.com/pkg/errors"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
-	expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/exp/api/v1beta2"
 	"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/logger"
 )
 
@@ -41,7 +40,6 @@ type placementInput struct {
 	SpecAvailabilityZones   []string
 	ParentAvailabilityZones []string
 	ControlplaneSubnets     infrav1.Subnets
-	SubnetPlacementType     *expinfrav1.AZSubnetType
 }
 
 type subnetsPlacementStratgey interface {
@@ -77,7 +75,7 @@ func (p *defaultSubnetPlacementStrategy) Place(input *placementInput) ([]string,
 
 	if len(input.SpecAvailabilityZones) > 0 {
 		p.logger.Debug("determining subnets to use from the spec availability zones")
-		subnetIDs, err := p.getSubnetsForAZs(input.SpecAvailabilityZones, input.ControlplaneSubnets, input.SubnetPlacementType)
+		subnetIDs, err := p.getSubnetsForAZs(input.SpecAvailabilityZones, input.ControlplaneSubnets)
 		if err != nil {
 			return nil, fmt.Errorf("getting subnets for spec azs: %w", err)
 		}
@@ -87,7 +85,7 @@ func (p *defaultSubnetPlacementStrategy) Place(input *placementInput) ([]string,
 
 	if len(input.ParentAvailabilityZones) > 0 {
 		p.logger.Debug("determining subnets to use from the parents availability zones")
-		subnetIDs, err := p.getSubnetsForAZs(input.ParentAvailabilityZones, input.ControlplaneSubnets, input.SubnetPlacementType)
+		subnetIDs, err := p.getSubnetsForAZs(input.ParentAvailabilityZones, input.ControlplaneSubnets)
 		if err != nil {
 			return nil, fmt.Errorf("getting subnets for parent azs: %w", err)
 		}
@@ -104,21 +102,11 @@ func (p *defaultSubnetPlacementStrategy) Place(input *placementInput) ([]string,
 	return nil, ErrNotPlaced
 }
 
-func (p *defaultSubnetPlacementStrategy) getSubnetsForAZs(azs []string, controlPlaneSubnets infrav1.Subnets, placementType *expinfrav1.AZSubnetType) ([]string, error) {
+func (p *defaultSubnetPlacementStrategy) getSubnetsForAZs(azs []string, controlPlaneSubnets infrav1.Subnets) ([]string, error) {
 	subnetIDs := []string{}
 
 	for _, zone := range azs {
 		subnets := controlPlaneSubnets.FilterByZone(zone)
-		if placementType != nil {
-			switch *placementType {
-			case expinfrav1.AZSubnetTypeAll:
-				// no-op
-			case expinfrav1.AZSubnetTypePublic:
-				subnets = subnets.FilterPublic()
-			case expinfrav1.AZSubnetTypePrivate:
-				subnets = subnets.FilterPrivate()
-			}
-		}
 		if len(subnets) == 0 {
 			return nil, fmt.Errorf("getting subnets for availability zone %s: %w", zone, ErrAZSubnetsNotFound)
 		}
diff --git a/pkg/cloud/services/s3/s3.go b/pkg/cloud/services/s3/s3.go
index 96a39f8bc..8940eda38 100644
--- a/pkg/cloud/services/s3/s3.go
+++ b/pkg/cloud/services/s3/s3.go
@@ -31,6 +31,7 @@ import (
 	"github.com/aws/aws-sdk-go/service/sts/stsiface"
 	"github.com/pkg/errors"
 
+	infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
 	iam "sigs.k8s.io/cluster-api-provider-aws/v2/iam/api/v1beta1"
 	"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/scope"
 	"sigs.k8s.io/cluster-api-provider-aws/v2/util/system"
@@ -68,6 +69,10 @@ func (s *Service) ReconcileBucket() error {
 		return errors.Wrap(err, "ensuring bucket exists")
 	}
 
+	if err := s.tagBucket(bucketName); err != nil {
+		return errors.Wrap(err, "tagging bucket")
+	}
+
 	if err := s.ensureBucketPolicy(bucketName); err != nil {
 		return errors.Wrap(err, "ensuring bucket policy")
 	}
@@ -230,6 +235,39 @@ func (s *Service) ensureBucketPolicy(bucketName string) error {
 	return nil
 }
 
+func (s *Service) tagBucket(bucketName string) error {
+	taggingInput := &s3.PutBucketTaggingInput{
+		Bucket: aws.String(bucketName),
+		Tagging: &s3.Tagging{
+			TagSet: nil,
+		},
+	}
+
+	tags := infrav1.Build(infrav1.BuildParams{
+		ClusterName: s.scope.Name(),
+		Lifecycle:   infrav1.ResourceLifecycleOwned,
+		Name:        nil,
+		Role:        aws.String("node"),
+		Additional:  nil,
+	})
+
+	for key, value := range tags {
+		taggingInput.Tagging.TagSet = append(taggingInput.Tagging.TagSet, &s3.Tag{
+			Key:   aws.String(key),
+			Value: aws.String(value),
+		})
+	}
+
+	_, err := s.S3Client.PutBucketTagging(taggingInput)
+	if err != nil {
+		return err
+	}
+
+	s.scope.Trace("Tagged bucket", "bucket_name", bucketName)
+
+	return nil
+}
+
 func (s *Service) bucketPolicy(bucketName string) (string, error) {
 	accountID, err := s.STSClient.GetCallerIdentity(&sts.GetCallerIdentityInput{})
 	if err != nil {


Test patch:
diff --git a/exp/api/v1beta2/awsmanagedmachinepool_webhook_test.go b/exp/api/v1beta2/awsmanagedmachinepool_webhook_test.go
index 69e28b7ef..f123d32a5 100644
--- a/exp/api/v1beta2/awsmanagedmachinepool_webhook_test.go
+++ b/exp/api/v1beta2/awsmanagedmachinepool_webhook_test.go
@@ -29,17 +29,6 @@ import (
 	utildefaulting "sigs.k8s.io/cluster-api/util/defaulting"
 )
 
-var (
-	oldDiskSize                   = int32(50)
-	newDiskSize                   = int32(100)
-	oldAmiType                    = Al2x86_64
-	newAmiType                    = Al2x86_64GPU
-	oldCapacityType               = ManagedMachinePoolCapacityTypeOnDemand
-	newCapacityType               = ManagedMachinePoolCapacityTypeSpot
-	oldAvailabilityZoneSubnetType = AZSubnetTypePublic
-	newAvailabilityZoneSubnetType = AZSubnetTypePrivate
-)
-
 func TestAWSManagedMachinePoolDefault(t *testing.T) {
 	fargate := &AWSManagedMachinePool{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}}
 	t.Run("for AWSManagedMachinePool", utildefaulting.DefaultValidateTest(fargate))
@@ -264,428 +253,6 @@ func TestAWSManagedMachinePoolValidateUpdate(t *testing.T) {
 			},
 			wantErr: false,
 		},
-		{
-			name: "adding subnet id is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					SubnetIDs:        []string{"subnet-1"},
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing subnet id is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					SubnetIDs:        []string{"subnet-1"},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing subnet id is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					SubnetIDs:        []string{"subnet-1"},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					SubnetIDs:        []string{"subnet-2"},
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing role name is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					RoleName:         "role-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing role name is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					RoleName:         "role-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					RoleName:         "role-2",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "adding disk size is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					DiskSize:         &newDiskSize,
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing disk size is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					DiskSize:         &oldDiskSize,
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing disk size is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					DiskSize:         &oldDiskSize,
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					DiskSize:         &newDiskSize,
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "adding ami type is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AMIType:          &newAmiType,
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing ami type is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AMIType:          &oldAmiType,
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing ami type is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AMIType:          &oldAmiType,
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AMIType:          &newAmiType,
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "adding remote access is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					RemoteAccess: &ManagedRemoteAccess{
-						Public: false,
-					},
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing remote access is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					RemoteAccess: &ManagedRemoteAccess{
-						Public: false,
-					},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing remote access is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					RemoteAccess: &ManagedRemoteAccess{
-						Public: false,
-					},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					RemoteAccess: &ManagedRemoteAccess{
-						Public: true,
-					},
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing capacity type is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					CapacityType:     &oldCapacityType,
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing capacity type is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					CapacityType:     &oldCapacityType,
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					CapacityType:     &newCapacityType,
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "adding availability zones is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName:  "eks-node-group-1",
-					AvailabilityZones: []string{"us-east-1a"},
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing availability zones is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName:  "eks-node-group-1",
-					AvailabilityZones: []string{"us-east-1a"},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing availability zones is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName:  "eks-node-group-1",
-					AvailabilityZones: []string{"us-east-1a"},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName:  "eks-node-group-1",
-					AvailabilityZones: []string{"us-east-1a", "us-east-1b"},
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "adding availability zone subnet type is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName:           "eks-node-group-1",
-					AvailabilityZoneSubnetType: &newAvailabilityZoneSubnetType,
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing availability zone subnet type is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName:           "eks-node-group-1",
-					AvailabilityZoneSubnetType: &oldAvailabilityZoneSubnetType,
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing availability zone subnet type is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName:           "eks-node-group-1",
-					AvailabilityZoneSubnetType: &oldAvailabilityZoneSubnetType,
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName:           "eks-node-group-1",
-					AvailabilityZoneSubnetType: &newAvailabilityZoneSubnetType,
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "adding launch template is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AWSLaunchTemplate: &AWSLaunchTemplate{
-						Name: "test",
-					},
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "removing launch template is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AWSLaunchTemplate: &AWSLaunchTemplate{
-						Name: "test",
-					},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing launch template name is rejected",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AWSLaunchTemplate: &AWSLaunchTemplate{
-						Name: "test",
-					},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AWSLaunchTemplate: &AWSLaunchTemplate{
-						Name: "test2",
-					},
-				},
-			},
-			wantErr: true,
-		},
-		{
-			name: "changing launch template fields other than name is accepted",
-			old: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AWSLaunchTemplate: &AWSLaunchTemplate{
-						Name:              "test",
-						ImageLookupFormat: "test",
-					},
-				},
-			},
-			new: &AWSManagedMachinePool{
-				Spec: AWSManagedMachinePoolSpec{
-					EKSNodegroupName: "eks-node-group-1",
-					AWSLaunchTemplate: &AWSLaunchTemplate{
-						Name:              "test",
-						ImageLookupFormat: "test2",
-					},
-				},
-			},
-			wantErr: false,
-		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
diff --git a/pkg/cloud/scope/shared_test.go b/pkg/cloud/scope/shared_test.go
index 9f7956357..04627f512 100644
--- a/pkg/cloud/scope/shared_test.go
+++ b/pkg/cloud/scope/shared_test.go
@@ -23,7 +23,6 @@ import (
 	"k8s.io/klog/v2"
 
 	infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
-	expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/exp/api/v1beta2"
 	"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/logger"
 )
 
@@ -33,43 +32,28 @@ func TestSubnetPlacement(t *testing.T) {
 		specSubnetIDs       []string
 		specAZs             []string
 		parentAZs           []string
-		subnetPlacementType *expinfrav1.AZSubnetType
 		controlPlaneSubnets infrav1.Subnets
 		logger              *logger.Logger
 		expectedSubnetIDs   []string
 		expectError         bool
 	}{
 		{
-			name:                "spec subnets expected",
-			specSubnetIDs:       []string{"az1"},
-			specAZs:             []string{"eu-west-1b"},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: nil,
+			name:          "spec subnets expected",
+			specSubnetIDs: []string{"az1"},
+			specAZs:       []string{"eu-west-1b"},
+			parentAZs:     []string{"eu-west-1c"},
 			controlPlaneSubnets: infrav1.Subnets{
 				infrav1.SubnetSpec{
 					ID:               "az1",
 					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
 				},
 				infrav1.SubnetSpec{
 					ID:               "az2",
 					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
 				},
 				infrav1.SubnetSpec{
 					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
 					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
 				},
 			},
 			logger:            logger.NewLogger(klog.Background()),
@@ -77,147 +61,22 @@ func TestSubnetPlacement(t *testing.T) {
 			expectError:       false,
 		},
 		{
-			name:                "spec azs expected",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{"eu-west-1b"},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: nil,
-			controlPlaneSubnets: infrav1.Subnets{
-				infrav1.SubnetSpec{
-					ID:               "az1",
-					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az2",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
-				},
-			},
-			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{"az2", "az3"},
-			expectError:       false,
-		},
-		{
-			name:                "parent azs expected",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: nil,
-			controlPlaneSubnets: infrav1.Subnets{
-				infrav1.SubnetSpec{
-					ID:               "az1",
-					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az2",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
-				},
-			},
-			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{"az4", "az5"},
-			expectError:       false,
-		},
-		{
-			name:                "spec private azs expected",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{"eu-west-1b"},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: expinfrav1.NewAZSubnetType(expinfrav1.AZSubnetTypePrivate),
-			controlPlaneSubnets: infrav1.Subnets{
-				infrav1.SubnetSpec{
-					ID:               "az1",
-					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az2",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
-				},
-			},
-			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{"az3"},
-			expectError:       false,
-		},
-		{
-			name:                "spec public azs expected",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{"eu-west-1b"},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: expinfrav1.NewAZSubnetType(expinfrav1.AZSubnetTypePublic),
+			name:          "spec azs expected",
+			specSubnetIDs: []string{},
+			specAZs:       []string{"eu-west-1b"},
+			parentAZs:     []string{"eu-west-1c"},
 			controlPlaneSubnets: infrav1.Subnets{
 				infrav1.SubnetSpec{
 					ID:               "az1",
 					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
 				},
 				infrav1.SubnetSpec{
 					ID:               "az2",
 					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
 				},
 				infrav1.SubnetSpec{
 					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
 					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
 				},
 			},
 			logger:            logger.NewLogger(klog.Background()),
@@ -225,188 +84,26 @@ func TestSubnetPlacement(t *testing.T) {
 			expectError:       false,
 		},
 		{
-			name:                "spec all azs expected",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{"eu-west-1b"},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: expinfrav1.NewAZSubnetType(expinfrav1.AZSubnetTypeAll),
-			controlPlaneSubnets: infrav1.Subnets{
-				infrav1.SubnetSpec{
-					ID:               "az1",
-					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az2",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
-				},
-			},
-			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{"az2", "az3"},
-			expectError:       false,
-		},
-		{
-			name:                "spec public no azs found",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{"eu-west-1a"},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: expinfrav1.NewAZSubnetType(expinfrav1.AZSubnetTypePublic),
-			controlPlaneSubnets: infrav1.Subnets{
-				infrav1.SubnetSpec{
-					ID:               "az1",
-					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az2",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
-				},
-			},
-			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{},
-			expectError:       true,
-		},
-		{
-			name:                "parent private azs expected",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: expinfrav1.NewAZSubnetType(expinfrav1.AZSubnetTypePrivate),
-			controlPlaneSubnets: infrav1.Subnets{
-				infrav1.SubnetSpec{
-					ID:               "az1",
-					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az2",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
-				},
-			},
-			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{"az5"},
-			expectError:       false,
-		},
-		{
-			name:                "parent public azs expected",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: expinfrav1.NewAZSubnetType(expinfrav1.AZSubnetTypePublic),
-			controlPlaneSubnets: infrav1.Subnets{
-				infrav1.SubnetSpec{
-					ID:               "az1",
-					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az2",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
-				},
-			},
-			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{"az4"},
-			expectError:       false,
-		},
-		{
-			name:                "parent all azs expected",
-			specSubnetIDs:       []string{},
-			specAZs:             []string{},
-			parentAZs:           []string{"eu-west-1c"},
-			subnetPlacementType: expinfrav1.NewAZSubnetType(expinfrav1.AZSubnetTypeAll),
+			name:          "parent azs expected",
+			specSubnetIDs: []string{},
+			specAZs:       []string{},
+			parentAZs:     []string{"eu-west-1c"},
 			controlPlaneSubnets: infrav1.Subnets{
 				infrav1.SubnetSpec{
 					ID:               "az1",
 					AvailabilityZone: "eu-west-1a",
-					IsPublic:         false,
 				},
 				infrav1.SubnetSpec{
 					ID:               "az2",
 					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
 				},
 				infrav1.SubnetSpec{
 					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
-					IsPublic:         false,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az4",
 					AvailabilityZone: "eu-west-1c",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
 				},
 			},
 			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{"az4", "az5"},
+			expectedSubnetIDs: []string{"az3"},
 			expectError:       false,
 		},
 		{
@@ -423,26 +120,16 @@ func TestSubnetPlacement(t *testing.T) {
 				infrav1.SubnetSpec{
 					ID:               "az2",
 					AvailabilityZone: "eu-west-1b",
-					IsPublic:         true,
-				},
-				infrav1.SubnetSpec{
-					ID:               "az3",
-					AvailabilityZone: "eu-west-1b",
 					IsPublic:         false,
 				},
 				infrav1.SubnetSpec{
-					ID:               "az4",
+					ID:               "az3",
 					AvailabilityZone: "eu-west-1c",
 					IsPublic:         true,
 				},
-				infrav1.SubnetSpec{
-					ID:               "az5",
-					AvailabilityZone: "eu-west-1c",
-					IsPublic:         false,
-				},
 			},
 			logger:            logger.NewLogger(klog.Background()),
-			expectedSubnetIDs: []string{"az1", "az3", "az5"},
+			expectedSubnetIDs: []string{"az1", "az2"},
 			expectError:       false,
 		},
 		{
@@ -469,7 +156,6 @@ func TestSubnetPlacement(t *testing.T) {
 				SpecAvailabilityZones:   tc.specAZs,
 				ParentAvailabilityZones: tc.parentAZs,
 				ControlplaneSubnets:     tc.controlPlaneSubnets,
-				SubnetPlacementType:     tc.subnetPlacementType,
 			})
 
 			if tc.expectError {
diff --git a/pkg/cloud/services/s3/s3_test.go b/pkg/cloud/services/s3/s3_test.go
index 700dcc3ae..f3753b24a 100644
--- a/pkg/cloud/services/s3/s3_test.go
+++ b/pkg/cloud/services/s3/s3_test.go
@@ -75,6 +75,25 @@ func TestReconcileBucket(t *testing.T) {
 		}
 
 		s3Mock.EXPECT().CreateBucket(gomock.Eq(input)).Return(nil, nil).Times(1)
+
+		taggingInput := &s3svc.PutBucketTaggingInput{
+			Bucket: aws.String(expectedBucketName),
+			Tagging: &s3svc.Tagging{
+				TagSet: []*s3svc.Tag{
+					{
+						Key:   aws.String("sigs.k8s.io/cluster-api-provider-aws/cluster/test-cluster"),
+						Value: aws.String("owned"),
+					},
+					{
+						Key:   aws.String("sigs.k8s.io/cluster-api-provider-aws/role"),
+						Value: aws.String("node"),
+					},
+				},
+			},
+		}
+
+		s3Mock.EXPECT().PutBucketTagging(gomock.Eq(taggingInput)).Return(nil, nil).Times(1)
+
 		s3Mock.EXPECT().PutBucketPolicy(gomock.Any()).Return(nil, nil).Times(1)
 
 		if err := svc.ReconcileBucket(); err != nil {
@@ -129,6 +148,7 @@ func TestReconcileBucket(t *testing.T) {
 			}
 		}).Return(nil, nil).Times(1)
 
+		s3Mock.EXPECT().PutBucketTagging(gomock.Any()).Return(nil, nil).Times(1)
 		s3Mock.EXPECT().PutBucketPolicy(gomock.Any()).Return(nil, nil).Times(1)
 
 		if err := svc.ReconcileBucket(); err != nil {
@@ -150,6 +170,7 @@ func TestReconcileBucket(t *testing.T) {
 		})
 
 		s3Mock.EXPECT().CreateBucket(gomock.Any()).Return(nil, nil).Times(1)
+		s3Mock.EXPECT().PutBucketTagging(gomock.Any()).Return(nil, nil).Times(1)
 		s3Mock.EXPECT().PutBucketPolicy(gomock.Any()).Do(func(input *s3svc.PutBucketPolicyInput) {
 			if input.Policy == nil {
 				t.Fatalf("Policy must be defined")
@@ -189,6 +210,7 @@ func TestReconcileBucket(t *testing.T) {
 		svc, s3Mock := testService(t, &infrav1.S3Bucket{})
 
 		s3Mock.EXPECT().CreateBucket(gomock.Any()).Return(nil, nil).Times(2)
+		s3Mock.EXPECT().PutBucketTagging(gomock.Any()).Return(nil, nil).Times(2)
 		s3Mock.EXPECT().PutBucketPolicy(gomock.Any()).Return(nil, nil).Times(2)
 
 		if err := svc.ReconcileBucket(); err != nil {
@@ -208,6 +230,7 @@ func TestReconcileBucket(t *testing.T) {
 		err := awserr.New(s3svc.ErrCodeBucketAlreadyOwnedByYou, "err", errors.New("err"))
 
 		s3Mock.EXPECT().CreateBucket(gomock.Any()).Return(nil, err).Times(1)
+		s3Mock.EXPECT().PutBucketTagging(gomock.Any()).Return(nil, nil).Times(1)
 		s3Mock.EXPECT().PutBucketPolicy(gomock.Any()).Return(nil, nil).Times(1)
 
 		if err := svc.ReconcileBucket(); err != nil {
@@ -248,6 +271,7 @@ func TestReconcileBucket(t *testing.T) {
 			svc, s3Mock := testService(t, &infrav1.S3Bucket{})
 
 			s3Mock.EXPECT().CreateBucket(gomock.Any()).Return(nil, nil).Times(1)
+			s3Mock.EXPECT().PutBucketTagging(gomock.Any()).Return(nil, nil).Times(1)
 
 			mockCtrl := gomock.NewController(t)
 			stsMock := mock_stsiface.NewMockSTSAPI(mockCtrl)
@@ -265,6 +289,7 @@ func TestReconcileBucket(t *testing.T) {
 			svc, s3Mock := testService(t, &infrav1.S3Bucket{})
 
 			s3Mock.EXPECT().CreateBucket(gomock.Any()).Return(nil, nil).Times(1)
+			s3Mock.EXPECT().PutBucketTagging(gomock.Any()).Return(nil, nil).Times(1)
 			s3Mock.EXPECT().PutBucketPolicy(gomock.Any()).Return(nil, errors.New("error")).Times(1)
 
 			if err := svc.ReconcileBucket(); err == nil {