Skip to content

Commit bf50223

Browse files
authored
Adapt Ignition user data S3 support to upstream PR (#614)
See changes made in kubernetes-sigs#5172
1 parent 5ffc044 commit bf50223

File tree

11 files changed

+85
-42
lines changed

11 files changed

+85
-42
lines changed

api/v1beta2/awsmachine_types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ const (
3030

3131
// DefaultIgnitionVersion represents default Ignition version generated for machine userdata.
3232
DefaultIgnitionVersion = "2.3"
33+
34+
// DefaultIgnitionStorageType represents the default storage type of Ignition userdata
35+
DefaultIgnitionStorageType = IgnitionStorageTypeOptionClusterObjectStore
36+
37+
// DefaultMachinePoolIgnitionStorageType represents the default storage type of Ignition userdata for machine pools.
38+
//
39+
// This is only different from DefaultIgnitionStorageType because of backward compatibility. Machine pools used to
40+
// default to store Ignition user data directly on the EC2 instance. Since the choice between remote storage (S3)
41+
// and direct storage was introduced, the default was kept, but might change in newer API versions.
42+
//
43+
// GIANT SWARM CUSTOMIZED!!!: We already have clusters without explicit "ClusterObjectStore" storage type, so they
44+
// should keep defaulting to this setting even if in the upstream PR, which merged later, the default became
45+
// `IgnitionStorageTypeOptionUnencryptedUserData`. After upgrading all clusters to the latest cluster-aws version
46+
// that sets the field explicitly, we can revert this to be equal to upstream's default:
47+
DefaultMachinePoolIgnitionStorageType = IgnitionStorageTypeOptionClusterObjectStore
3348
)
3449

3550
// SecretBackend defines variants for backend secret storage.

api/v1beta2/awsmachine_webhook.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -399,12 +399,11 @@ func (r *AWSMachine) Default() {
399399
}
400400

401401
if r.ignitionEnabled() && r.Spec.Ignition.Version == "" {
402-
if r.Spec.Ignition == nil {
403-
r.Spec.Ignition = &Ignition{}
404-
}
405-
406402
r.Spec.Ignition.Version = DefaultIgnitionVersion
407403
}
404+
if r.ignitionEnabled() && r.Spec.Ignition.StorageType == "" {
405+
r.Spec.Ignition.StorageType = DefaultIgnitionStorageType
406+
}
408407
}
409408

410409
func (r *AWSMachine) validateAdditionalSecurityGroups() field.ErrorList {

cmd/clusterawsadm/cloudformation/bootstrap/cluster_api_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,8 @@ func (t Template) ControllersPolicy() *iamv1.PolicyDocument {
295295
Action: iamv1.Actions{
296296
"s3:CreateBucket",
297297
"s3:DeleteBucket",
298-
"s3:GetObject",
299298
"s3:DeleteObject",
299+
"s3:GetObject",
300300
"s3:ListBucket",
301301
"s3:PutBucketPolicy",
302302
"s3:PutBucketTagging",

cmd/clusterawsadm/cloudformation/bootstrap/fixtures/with_s3_bucket.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,8 +301,8 @@ Resources:
301301
- Action:
302302
- s3:CreateBucket
303303
- s3:DeleteBucket
304-
- s3:GetObject
305304
- s3:DeleteObject
305+
- s3:GetObject
306306
- s3:ListBucket
307307
- s3:PutBucketPolicy
308308
- s3:PutBucketTagging

controllers/awsmachine_controller.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ func (r *AWSMachineReconciler) resolveUserData(machineScope *scope.MachineScope,
739739
if machineScope.UseIgnition(userDataFormat) {
740740
var ignitionStorageType infrav1.IgnitionStorageTypeOption
741741
if machineScope.AWSMachine.Spec.Ignition == nil {
742-
ignitionStorageType = infrav1.IgnitionStorageTypeOptionClusterObjectStore
742+
ignitionStorageType = infrav1.DefaultIgnitionStorageType
743743
} else {
744744
ignitionStorageType = machineScope.AWSMachine.Spec.Ignition.StorageType
745745
}
@@ -795,8 +795,8 @@ func (r *AWSMachineReconciler) cloudInitUserData(machineScope *scope.MachineScop
795795
// then returns the config to instruct ignition on how to pull the user data from the bucket.
796796
func (r *AWSMachineReconciler) generateIgnitionWithRemoteStorage(scope *scope.MachineScope, objectStoreSvc services.ObjectStoreInterface, userData []byte) ([]byte, error) {
797797
if objectStoreSvc == nil {
798-
return nil, errors.New("using Ignition by default requires a cluster wide object storage configured at `AWSCluster.Spec.Ignition.S3Bucket`. " +
799-
"You must configure one or instruct Ignition to use EC2 user data instead, by setting `AWSMachine.Spec.Ignition.StorageType` to `UnencryptedUserData`")
798+
return nil, errors.New("using Ignition by default requires a cluster wide object storage configured at `AWSCluster.spec.s3Bucket`. " +
799+
"You must configure one or instruct Ignition to use EC2 user data instead, by setting `AWSMachine.spec.ignition.storageType` to `UnencryptedUserData`")
800800
}
801801

802802
objectURL, err := objectStoreSvc.Create(scope, userData)

exp/api/v1beta2/awsmachinepool_webhook.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,7 @@ func (r *AWSMachinePool) Default() {
254254
if r.ignitionEnabled() && r.Spec.Ignition.Version == "" {
255255
r.Spec.Ignition.Version = infrav1.DefaultIgnitionVersion
256256
}
257+
if r.ignitionEnabled() && r.Spec.Ignition.StorageType == "" {
258+
r.Spec.Ignition.StorageType = infrav1.DefaultMachinePoolIgnitionStorageType
259+
}
257260
}

exp/controllers/awsmachinepool_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ func (r *AWSMachinePoolReconciler) reconcileDelete(machinePoolScope *scope.Machi
418418
}
419419

420420
launchTemplateID := machinePoolScope.AWSMachinePool.Status.LaunchTemplateID
421-
launchTemplate, _, _, _, err := ec2Svc.GetLaunchTemplate(machinePoolScope.LaunchTemplateName())
421+
launchTemplate, _, _, _, err := ec2Svc.GetLaunchTemplate(machinePoolScope.LaunchTemplateName()) //nolint:dogsled
422422
if err != nil {
423423
return err
424424
}

exp/controllers/awsmachinepool_controller_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ import (
3737
"k8s.io/apimachinery/pkg/runtime"
3838
apimachinerytypes "k8s.io/apimachinery/pkg/types"
3939
"k8s.io/client-go/tools/record"
40+
utilfeature "k8s.io/component-base/featuregate/testing"
4041
"k8s.io/klog/v2"
4142
"k8s.io/utils/ptr"
4243
"sigs.k8s.io/controller-runtime/pkg/client/fake"
4344

4445
infrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
4546
expinfrav1 "sigs.k8s.io/cluster-api-provider-aws/v2/exp/api/v1beta2"
47+
"sigs.k8s.io/cluster-api-provider-aws/v2/feature"
4648
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud"
4749
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/scope"
4850
"sigs.k8s.io/cluster-api-provider-aws/v2/pkg/cloud/services"
@@ -772,6 +774,8 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
772774
})
773775

774776
t.Run("launch template and ASG exist, bootstrap data secret name changed, Ignition bootstrap data stored in S3", func(t *testing.T) {
777+
defer utilfeature.SetFeatureGateDuringTest(t, feature.Gates, feature.MachinePool, true)()
778+
775779
g := NewWithT(t)
776780
setup(t, g)
777781
reconciler.reconcileServiceFactory = nil // use real implementation, but keep EC2 calls mocked (`ec2ServiceFactory`)
@@ -787,7 +791,9 @@ func TestAWSMachinePoolReconciler(t *testing.T) {
787791

788792
// Enable Ignition S3 storage
789793
cs.AWSCluster.Spec.S3Bucket = &infrav1.S3Bucket{}
790-
ms.AWSMachinePool.Spec.Ignition = &infrav1.Ignition{}
794+
ms.AWSMachinePool.Spec.Ignition = &infrav1.Ignition{
795+
StorageType: infrav1.IgnitionStorageTypeOptionClusterObjectStore,
796+
}
791797
ms.AWSMachinePool.Default() // simulate webhook that sets default ignition version
792798

793799
asgSvc.EXPECT().GetASGByName(gomock.Any()).DoAndReturn(func(scope *scope.MachinePoolScope) (*expinfrav1.AutoScalingGroup, error) {

pkg/cloud/services/ec2/launchtemplate.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,20 @@ func (s *Service) ReconcileLaunchTemplate(
9292
return nil, err
9393
}
9494

95+
var ignitionStorageType = infrav1.DefaultMachinePoolIgnitionStorageType
96+
var ignitionVersion = infrav1.DefaultIgnitionVersion
97+
if ignition := ignitionScope.Ignition(); ignition != nil {
98+
ignitionStorageType = ignition.StorageType
99+
ignitionVersion = ignition.Version
100+
}
101+
95102
var userDataForLaunchTemplate []byte
96-
if s3Scope.Bucket() != nil && bootstrapDataFormat == "ignition" && ignitionScope.Ignition() != nil {
103+
if bootstrapDataFormat == "ignition" && ignitionStorageType == infrav1.IgnitionStorageTypeOptionClusterObjectStore {
104+
if s3Scope.Bucket() == nil {
105+
return nil, errors.New("using Ignition with `AWSMachinePool.spec.ignition.storageType=ClusterObjectStore` " +
106+
"requires a cluster wide object storage configured at `AWSCluster.spec.s3Bucket`")
107+
}
108+
97109
scope.Info("Using S3 bucket storage for Ignition format")
98110

99111
// S3 bucket storage enabled and Ignition format is used. Ignition supports reading large user data from S3,
@@ -108,10 +120,9 @@ func (s *Service) ReconcileLaunchTemplate(
108120
return nil, err
109121
}
110122

111-
ignVersion := ignitionScope.Ignition().Version
112-
semver, err := semver.ParseTolerant(ignVersion)
123+
semver, err := semver.ParseTolerant(ignitionVersion)
113124
if err != nil {
114-
err = errors.Wrapf(err, "failed to parse ignition version %q", ignVersion)
125+
err = errors.Wrapf(err, "failed to parse ignition version %q", ignitionVersion)
115126
conditions.MarkFalse(scope.GetSetter(), expinfrav1.LaunchTemplateReadyCondition, expinfrav1.LaunchTemplateReconcileFailedReason, clusterv1.ConditionSeverityError, err.Error())
116127
return nil, err
117128
}
@@ -159,7 +170,7 @@ func (s *Service) ReconcileLaunchTemplate(
159170
return nil, err
160171
}
161172
default:
162-
err = errors.Errorf("unsupported ignition version %q", ignVersion)
173+
err = errors.Errorf("unsupported ignition version %q", ignitionVersion)
163174
conditions.MarkFalse(scope.GetSetter(), expinfrav1.LaunchTemplateReadyCondition, expinfrav1.LaunchTemplateReconcileFailedReason, clusterv1.ConditionSeverityError, err.Error())
164175
return nil, err
165176
}
@@ -279,7 +290,8 @@ func (s *Service) ReconcileLaunchTemplate(
279290
if err != nil {
280291
return nil, err
281292
}
282-
if deletedLaunchTemplateVersionBootstrapDataHash != nil && s3Scope.Bucket() != nil && bootstrapDataFormat == "ignition" && ignitionScope.Ignition() != nil {
293+
294+
if deletedLaunchTemplateVersionBootstrapDataHash != nil && s3Scope.Bucket() != nil && bootstrapDataFormat == "ignition" && ignitionStorageType == infrav1.IgnitionStorageTypeOptionClusterObjectStore {
283295
scope.Info("Deleting S3 object for deleted launch template version", "version", *deletedLaunchTemplateVersion.VersionNumber)
284296

285297
err = objectStoreSvc.DeleteForMachinePool(scope, *deletedLaunchTemplateVersionBootstrapDataHash)

pkg/cloud/services/ec2/launchtemplate_test.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,16 @@ var testBootstrapDataHash = userdata.ComputeHash(testBootstrapData)
8585

8686
func defaultEC2AndDataTags(name string, clusterName string, userDataSecretKey types.NamespacedName, bootstrapDataHash string) []*ec2.Tag {
8787
tags := defaultEC2Tags(name, clusterName)
88-
tags = append(tags, &ec2.Tag{
89-
Key: aws.String(infrav1.LaunchTemplateBootstrapDataSecret),
90-
Value: aws.String(userDataSecretKey.String()),
91-
})
92-
tags = append(tags, &ec2.Tag{
93-
Key: aws.String(infrav1.LaunchTemplateBootstrapDataHash),
94-
Value: aws.String(bootstrapDataHash),
95-
})
88+
tags = append(
89+
tags,
90+
&ec2.Tag{
91+
Key: aws.String(infrav1.LaunchTemplateBootstrapDataSecret),
92+
Value: aws.String(userDataSecretKey.String()),
93+
},
94+
&ec2.Tag{
95+
Key: aws.String(infrav1.LaunchTemplateBootstrapDataHash),
96+
Value: aws.String(bootstrapDataHash),
97+
})
9698
sortTags(tags)
9799
return tags
98100
}

0 commit comments

Comments
 (0)