Skip to content

Commit 59689b7

Browse files
committed
add launchtemplate updates and tests
1 parent 592e975 commit 59689b7

File tree

2 files changed

+137
-36
lines changed

2 files changed

+137
-36
lines changed

pkg/cloud/services/ec2/launchtemplate.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ func (s *Service) createLaunchTemplateData(scope scope.LaunchTemplateScope, imag
650650
}
651651
data.InstanceMarketOptions = instanceMarketOptions
652652
data.PrivateDnsNameOptions = getLaunchTemplatePrivateDNSNameOptionsRequest(scope.GetLaunchTemplate().PrivateDNSName)
653+
data.CapacityReservationSpecification = getLaunchTemplateCapacityReservationSpecification(scope.GetLaunchTemplate())
653654

654655
blockDeviceMappings := []types.LaunchTemplateBlockDeviceMappingRequest{}
655656

@@ -682,6 +683,24 @@ func (s *Service) createLaunchTemplateData(scope scope.LaunchTemplateScope, imag
682683
return data, nil
683684
}
684685

686+
func getLaunchTemplateCapacityReservationSpecification(awsLaunchTemplate *expinfrav1.AWSLaunchTemplate) *types.LaunchTemplateCapacityReservationSpecificationRequest {
687+
if awsLaunchTemplate == nil {
688+
return nil
689+
}
690+
if awsLaunchTemplate.CapacityReservationID == nil && awsLaunchTemplate.CapacityReservationPreference == "" {
691+
return nil
692+
}
693+
spec := &types.LaunchTemplateCapacityReservationSpecificationRequest{
694+
CapacityReservationPreference: CapacityReservationPreferenceToSDK(awsLaunchTemplate.CapacityReservationPreference),
695+
}
696+
if awsLaunchTemplate.CapacityReservationID != nil {
697+
spec.CapacityReservationTarget = &types.CapacityReservationTarget{
698+
CapacityReservationId: awsLaunchTemplate.CapacityReservationID,
699+
}
700+
}
701+
return spec
702+
}
703+
685704
func volumeToLaunchTemplateBlockDeviceMappingRequest(v *infrav1.Volume) *types.LaunchTemplateBlockDeviceMappingRequest {
686705
ltEbsDevice := &types.LaunchTemplateEbsBlockDeviceRequest{
687706
DeleteOnTermination: aws.Bool(true),
@@ -829,6 +848,32 @@ func SDKToSpotMarketOptions(instanceMarketOptions *types.LaunchTemplateInstanceM
829848
return result
830849
}
831850

851+
func SDKToCapacityReservationPreference(preference types.CapacityReservationPreference) infrav1.CapacityReservationPreference {
852+
switch preference {
853+
case types.CapacityReservationPreferenceCapacityReservationsOnly:
854+
return infrav1.CapacityReservationPreferenceOnly
855+
case types.CapacityReservationPreferenceNone:
856+
return infrav1.CapacityReservationPreferenceNone
857+
case types.CapacityReservationPreferenceOpen:
858+
return infrav1.CapacityReservationPreferenceOpen
859+
default:
860+
return ""
861+
}
862+
}
863+
864+
func CapacityReservationPreferenceToSDK(preference infrav1.CapacityReservationPreference) types.CapacityReservationPreference {
865+
switch preference {
866+
case infrav1.CapacityReservationPreferenceNone:
867+
return types.CapacityReservationPreferenceNone
868+
case infrav1.CapacityReservationPreferenceOnly:
869+
return types.CapacityReservationPreferenceCapacityReservationsOnly
870+
case infrav1.CapacityReservationPreferenceOpen:
871+
return types.CapacityReservationPreferenceOpen
872+
default:
873+
return ""
874+
}
875+
}
876+
832877
// SDKToLaunchTemplate converts an AWS EC2 SDK instance to the CAPA instance type.
833878
func (s *Service) SDKToLaunchTemplate(d types.LaunchTemplateVersion) (*expinfrav1.AWSLaunchTemplate, string, *apimachinerytypes.NamespacedName, *string, error) {
834879
v := d.LaunchTemplateData

pkg/cloud/services/ec2/launchtemplate_test.go

Lines changed: 92 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,18 @@ func TestLaunchTemplateDataCreation(t *testing.T) {
14391439
})
14401440
}
14411441

1442+
var LaunchTemplateVersionIgnoreUnexported = cmpopts.IgnoreUnexported(
1443+
ec2types.CapacityReservationTarget{},
1444+
ec2types.LaunchTemplateCapacityReservationSpecificationRequest{},
1445+
ec2types.LaunchTemplateIamInstanceProfileSpecificationRequest{},
1446+
ec2types.LaunchTemplateSpotMarketOptionsRequest{},
1447+
ec2types.LaunchTemplateInstanceMarketOptionsRequest{},
1448+
ec2types.Tag{},
1449+
ec2types.LaunchTemplateTagSpecificationRequest{},
1450+
ec2types.RequestLaunchTemplateData{},
1451+
ec2.CreateLaunchTemplateVersionInput{},
1452+
)
1453+
14421454
func TestCreateLaunchTemplateVersion(t *testing.T) {
14431455
mockCtrl := gomock.NewController(t)
14441456
defer mockCtrl.Finish()
@@ -1459,6 +1471,7 @@ func TestCreateLaunchTemplateVersion(t *testing.T) {
14591471
awsResourceReference []infrav1.AWSResourceReference
14601472
expect func(m *mocks.MockEC2APIMockRecorder)
14611473
wantErr bool
1474+
mpScopeUpdater func(*scope.MachinePoolScope)
14621475
marketType ec2types.MarketType
14631476
}{
14641477
{
@@ -1506,24 +1519,22 @@ func TestCreateLaunchTemplateVersion(t *testing.T) {
15061519
func(ctx context.Context, arg *ec2.CreateLaunchTemplateVersionInput, requestOptions ...request.Option) {
15071520
// formatting added to match tags slice during cmp.Equal()
15081521
formatTagsInput(arg)
1509-
if !cmp.Equal(expectedInput, arg, cmpopts.IgnoreUnexported(
1510-
ec2types.LaunchTemplateIamInstanceProfileSpecificationRequest{},
1511-
ec2types.LaunchTemplateSpotMarketOptionsRequest{},
1512-
ec2types.LaunchTemplateInstanceMarketOptionsRequest{},
1513-
ec2types.Tag{},
1514-
ec2types.LaunchTemplateTagSpecificationRequest{},
1515-
ec2types.RequestLaunchTemplateData{},
1516-
ec2.CreateLaunchTemplateVersionInput{},
1517-
)) {
1518-
t.Fatalf("mismatch in input expected: %+v, but got %+v, diff: %s", expectedInput, arg, cmp.Diff(expectedInput, arg))
1522+
if !cmp.Equal(expectedInput, arg, LaunchTemplateVersionIgnoreUnexported) {
1523+
t.Fatalf("mismatch in input expected: %+v, but got %+v, diff: %s", expectedInput, arg, cmp.Diff(expectedInput, arg, LaunchTemplateVersionIgnoreUnexported))
15191524
}
15201525
})
15211526
},
15221527
},
15231528
{
15241529
name: "Should successfully create launch template version with capacity-block",
15251530
awsResourceReference: []infrav1.AWSResourceReference{{ID: aws.String("1")}},
1526-
marketType: ec2types.MarketTypeCapacityBlock,
1531+
mpScopeUpdater: func(mps *scope.MachinePoolScope) {
1532+
spec := mps.AWSMachinePool.Spec
1533+
spec.AWSLaunchTemplate.CapacityReservationID = aws.String("cr-12345678901234567")
1534+
spec.AWSLaunchTemplate.MarketType = infrav1.MarketTypeCapacityBlock
1535+
spec.AWSLaunchTemplate.SpotMarketOptions = nil
1536+
mps.AWSMachinePool.Spec = spec
1537+
},
15271538
expect: func(m *mocks.MockEC2APIMockRecorder) {
15281539
sgMap := make(map[infrav1.SecurityGroupRole]infrav1.SecurityGroup)
15291540
sgMap[infrav1.SecurityGroupNode] = infrav1.SecurityGroup{ID: "1"}
@@ -1542,6 +1553,11 @@ func TestCreateLaunchTemplateVersion(t *testing.T) {
15421553
InstanceMarketOptions: &ec2types.LaunchTemplateInstanceMarketOptionsRequest{
15431554
MarketType: ec2types.MarketTypeCapacityBlock,
15441555
},
1556+
CapacityReservationSpecification: &ec2types.LaunchTemplateCapacityReservationSpecificationRequest{
1557+
CapacityReservationTarget: &ec2types.CapacityReservationTarget{
1558+
CapacityReservationId: aws.String("cr-12345678901234567"),
1559+
},
1560+
},
15451561
TagSpecifications: []ec2types.LaunchTemplateTagSpecificationRequest{
15461562
{
15471563
ResourceType: ec2types.ResourceTypeInstance,
@@ -1563,16 +1579,66 @@ func TestCreateLaunchTemplateVersion(t *testing.T) {
15631579
func(ctx context.Context, arg *ec2.CreateLaunchTemplateVersionInput, requestOptions ...request.Option) {
15641580
// formatting added to match tags slice during cmp.Equal()
15651581
formatTagsInput(arg)
1566-
if !cmp.Equal(expectedInput, arg, cmpopts.IgnoreUnexported(
1567-
ec2types.LaunchTemplateIamInstanceProfileSpecificationRequest{},
1568-
ec2types.LaunchTemplateSpotMarketOptionsRequest{},
1569-
ec2types.LaunchTemplateInstanceMarketOptionsRequest{},
1570-
ec2types.Tag{},
1571-
ec2types.LaunchTemplateTagSpecificationRequest{},
1572-
ec2types.RequestLaunchTemplateData{},
1573-
ec2.CreateLaunchTemplateVersionInput{},
1574-
)) {
1575-
t.Fatalf("mismatch in input expected: %+v, but got %+v, diff: %s", expectedInput, arg, cmp.Diff(expectedInput, arg))
1582+
if !cmp.Equal(expectedInput, arg, LaunchTemplateVersionIgnoreUnexported) {
1583+
t.Fatalf("mismatch in input expected: %+v, but got %+v, diff: %s", expectedInput, arg, cmp.Diff(expectedInput, arg, LaunchTemplateVersionIgnoreUnexported))
1584+
}
1585+
})
1586+
},
1587+
},
1588+
{
1589+
name: "Should successfully create launch template version with capacity reservation ID and preference",
1590+
awsResourceReference: []infrav1.AWSResourceReference{{ID: aws.String("1")}},
1591+
mpScopeUpdater: func(mps *scope.MachinePoolScope) {
1592+
spec := mps.AWSMachinePool.Spec
1593+
spec.AWSLaunchTemplate.CapacityReservationID = aws.String("cr-12345678901234567")
1594+
spec.AWSLaunchTemplate.CapacityReservationPreference = infrav1.CapacityReservationPreferenceOnly
1595+
spec.AWSLaunchTemplate.SpotMarketOptions = nil
1596+
mps.AWSMachinePool.Spec = spec
1597+
},
1598+
expect: func(m *mocks.MockEC2APIMockRecorder) {
1599+
sgMap := make(map[infrav1.SecurityGroupRole]infrav1.SecurityGroup)
1600+
sgMap[infrav1.SecurityGroupNode] = infrav1.SecurityGroup{ID: "1"}
1601+
sgMap[infrav1.SecurityGroupLB] = infrav1.SecurityGroup{ID: "2"}
1602+
1603+
expectedInput := &ec2.CreateLaunchTemplateVersionInput{
1604+
LaunchTemplateData: &ec2types.RequestLaunchTemplateData{
1605+
InstanceType: ec2types.InstanceTypeT3Large,
1606+
IamInstanceProfile: &ec2types.LaunchTemplateIamInstanceProfileSpecificationRequest{
1607+
Name: aws.String("instance-profile"),
1608+
},
1609+
KeyName: aws.String("default"),
1610+
UserData: ptr.To[string](base64.StdEncoding.EncodeToString(userData)),
1611+
SecurityGroupIds: []string{"nodeSG", "lbSG", "1"},
1612+
ImageId: aws.String("imageID"),
1613+
CapacityReservationSpecification: &ec2types.LaunchTemplateCapacityReservationSpecificationRequest{
1614+
CapacityReservationTarget: &ec2types.CapacityReservationTarget{
1615+
CapacityReservationId: aws.String("cr-12345678901234567"),
1616+
},
1617+
CapacityReservationPreference: ec2types.CapacityReservationPreferenceCapacityReservationsOnly,
1618+
},
1619+
TagSpecifications: []ec2types.LaunchTemplateTagSpecificationRequest{
1620+
{
1621+
ResourceType: ec2types.ResourceTypeInstance,
1622+
Tags: defaultEC2AndDataTags("aws-mp-name", "cluster-name", userDataSecretKey, testBootstrapDataHash),
1623+
},
1624+
{
1625+
ResourceType: ec2types.ResourceTypeVolume,
1626+
Tags: defaultEC2Tags("aws-mp-name", "cluster-name"),
1627+
},
1628+
},
1629+
},
1630+
LaunchTemplateId: aws.String("launch-template-id"),
1631+
}
1632+
m.CreateLaunchTemplateVersion(context.TODO(), gomock.AssignableToTypeOf(expectedInput)).Return(&ec2.CreateLaunchTemplateVersionOutput{
1633+
LaunchTemplateVersion: &ec2types.LaunchTemplateVersion{
1634+
LaunchTemplateId: aws.String("launch-template-id"),
1635+
},
1636+
}, nil).Do(
1637+
func(ctx context.Context, arg *ec2.CreateLaunchTemplateVersionInput, requestOptions ...request.Option) {
1638+
// formatting added to match tags slice during cmp.Equal()
1639+
formatTagsInput(arg)
1640+
if !cmp.Equal(expectedInput, arg, LaunchTemplateVersionIgnoreUnexported) {
1641+
t.Fatalf("mismatch in input expected: %+v, but got %+v, diff: %s", expectedInput, arg, cmp.Diff(expectedInput, arg, LaunchTemplateVersionIgnoreUnexported))
15761642
}
15771643
})
15781644
},
@@ -1619,15 +1685,7 @@ func TestCreateLaunchTemplateVersion(t *testing.T) {
16191685
func(ctx context.Context, arg *ec2.CreateLaunchTemplateVersionInput, requestOptions ...request.Option) {
16201686
// formatting added to match tags slice during cmp.Equal()
16211687
formatTagsInput(arg)
1622-
if !cmp.Equal(expectedInput, arg, cmpopts.IgnoreUnexported(
1623-
ec2types.LaunchTemplateIamInstanceProfileSpecificationRequest{},
1624-
ec2types.LaunchTemplateSpotMarketOptionsRequest{},
1625-
ec2types.LaunchTemplateInstanceMarketOptionsRequest{},
1626-
ec2types.Tag{},
1627-
ec2types.LaunchTemplateTagSpecificationRequest{},
1628-
ec2types.RequestLaunchTemplateData{},
1629-
ec2.CreateLaunchTemplateVersionInput{},
1630-
)) {
1688+
if !cmp.Equal(expectedInput, arg, LaunchTemplateVersionIgnoreUnexported) {
16311689
t.Fatalf("mismatch in input expected: %+v, got: %+v", expectedInput, arg)
16321690
}
16331691
})
@@ -1645,13 +1703,11 @@ func TestCreateLaunchTemplateVersion(t *testing.T) {
16451703
cs, err := setupClusterScope(client)
16461704
g.Expect(err).NotTo(HaveOccurred())
16471705

1648-
var ms *scope.MachinePoolScope
1649-
if tc.marketType == ec2types.MarketTypeCapacityBlock {
1650-
ms, err = setupCapacityBlocksMachinePoolScope(client, cs)
1651-
} else {
1652-
ms, err = setupMachinePoolScope(client, cs)
1653-
}
1706+
ms, err := setupMachinePoolScope(client, cs)
16541707
g.Expect(err).NotTo(HaveOccurred())
1708+
if updateScope := tc.mpScopeUpdater; updateScope != nil {
1709+
updateScope(ms)
1710+
}
16551711

16561712
ms.AWSMachinePool.Spec.AWSLaunchTemplate.AdditionalSecurityGroups = tc.awsResourceReference
16571713

0 commit comments

Comments
 (0)