Skip to content

Commit

Permalink
Added the support for capacity blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
athiruma committed Nov 21, 2024
1 parent df09e6c commit c975830
Show file tree
Hide file tree
Showing 25 changed files with 728 additions and 49 deletions.
1 change: 1 addition & 0 deletions api/v1beta1/awscluster_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func (src *AWSCluster) ConvertTo(dstRaw conversion.Hub) error {
dst.Status.Bastion.PrivateDNSName = restored.Status.Bastion.PrivateDNSName
dst.Status.Bastion.PublicIPOnLaunch = restored.Status.Bastion.PublicIPOnLaunch
dst.Status.Bastion.CapacityReservationID = restored.Status.Bastion.CapacityReservationID
dst.Status.Bastion.UseCapacityBlock = restored.Status.Bastion.UseCapacityBlock
}
dst.Spec.Partition = restored.Spec.Partition

Expand Down
2 changes: 2 additions & 0 deletions api/v1beta1/awsmachine_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func (src *AWSMachine) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.PrivateDNSName = restored.Spec.PrivateDNSName
dst.Spec.SecurityGroupOverrides = restored.Spec.SecurityGroupOverrides
dst.Spec.CapacityReservationID = restored.Spec.CapacityReservationID
dst.Spec.UseCapacityBlock = restored.Spec.UseCapacityBlock
if restored.Spec.ElasticIPPool != nil {
if dst.Spec.ElasticIPPool == nil {
dst.Spec.ElasticIPPool = &infrav1.ElasticIPPool{}
Expand Down Expand Up @@ -104,6 +105,7 @@ func (r *AWSMachineTemplate) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.Template.Spec.PrivateDNSName = restored.Spec.Template.Spec.PrivateDNSName
dst.Spec.Template.Spec.SecurityGroupOverrides = restored.Spec.Template.Spec.SecurityGroupOverrides
dst.Spec.Template.Spec.CapacityReservationID = restored.Spec.Template.Spec.CapacityReservationID
dst.Spec.Template.Spec.UseCapacityBlock = restored.Spec.Template.Spec.UseCapacityBlock
if restored.Spec.Template.Spec.ElasticIPPool != nil {
if dst.Spec.Template.Spec.ElasticIPPool == nil {
dst.Spec.Template.Spec.ElasticIPPool = &infrav1.ElasticIPPool{}
Expand Down
2 changes: 2 additions & 0 deletions api/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/v1beta2/awsmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ type AWSMachineSpec struct {
// CapacityReservationID specifies the target Capacity Reservation into which the instance should be launched.
// +optional
CapacityReservationID *string `json:"capacityReservationId,omitempty"`

// UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
// If enabled, CapacityReservationID must be specified to identify the target reservation.
// +optional
UseCapacityBlock *bool `json:"useCapacityBlock,omitempty"`
}

// CloudInit defines options related to the bootstrapping systems where
Expand Down
9 changes: 9 additions & 0 deletions api/v1beta2/awsmachine_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func (r *AWSMachine) ValidateCreate() (admission.Warnings, error) {
allErrs = append(allErrs, r.validateAdditionalSecurityGroups()...)
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
allErrs = append(allErrs, r.validateNetworkElasticIPPool()...)
allErrs = append(allErrs, r.validateInstanceMarketType()...)

return nil, aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
}
Expand Down Expand Up @@ -361,6 +362,14 @@ func (r *AWSMachine) validateNetworkElasticIPPool() field.ErrorList {
return allErrs
}

func (r *AWSMachine) validateInstanceMarketType() field.ErrorList {
var allErrs field.ErrorList
if r.Spec.UseCapacityBlock != nil && r.Spec.SpotMarketOptions != nil {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "useCapacityBlock"), "useCapacityBlock and spotMarketOptions cannot be used together"))
}
return allErrs
}

func (r *AWSMachine) validateNonRootVolumes() field.ErrorList {
var allErrs field.ErrorList

Expand Down
21 changes: 21 additions & 0 deletions api/v1beta2/awsmachine_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,27 @@ func TestAWSMachineCreate(t *testing.T) {
},
wantErr: false,
},
{
name: "invalid useCapacityBlock and spotMarketOptions are specified",
machine: &AWSMachine{
Spec: AWSMachineSpec{
UseCapacityBlock: aws.Bool(true),
SpotMarketOptions: &SpotMarketOptions{},
InstanceType: "test",
},
},
wantErr: true,
},
{
name: "valid useCapacityBlock is specified",
machine: &AWSMachine{
Spec: AWSMachineSpec{
UseCapacityBlock: aws.Bool(true),
InstanceType: "test",
},
},
wantErr: false,
},
{
name: "empty instance type not allowed",
machine: &AWSMachine{
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ type Instance struct {
// CapacityReservationID specifies the target Capacity Reservation into which the instance should be launched.
// +optional
CapacityReservationID *string `json:"capacityReservationId,omitempty"`

// UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
// If enabled, CapacityReservationID must be specified to identify the target reservation.
// +optional
UseCapacityBlock *bool `json:"useCapacityBlock,omitempty"`
}

// InstanceMetadataState describes the state of InstanceMetadataOptions.HttpEndpoint and InstanceMetadataOptions.InstanceMetadataTags
Expand Down
10 changes: 10 additions & 0 deletions api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1397,6 +1397,11 @@ spec:
type:
description: The instance type.
type: string
useCapacityBlock:
description: |-
UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
If enabled, CapacityReservationID must be specified to identify the target reservation.
type: boolean
userData:
description: |-
UserData is the raw data script passed to the instance which is run upon bootstrap.
Expand Down Expand Up @@ -3458,6 +3463,11 @@ spec:
type:
description: The instance type.
type: string
useCapacityBlock:
description: |-
UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
If enabled, CapacityReservationID must be specified to identify the target reservation.
type: boolean
userData:
description: |-
UserData is the raw data script passed to the instance which is run upon bootstrap.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2372,6 +2372,11 @@ spec:
type:
description: The instance type.
type: string
useCapacityBlock:
description: |-
UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
If enabled, CapacityReservationID must be specified to identify the target reservation.
type: boolean
userData:
description: |-
UserData is the raw data script passed to the instance which is run upon bootstrap.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,10 @@ spec:
description: ID of resource
type: string
type: object
capacityReservationId:
description: CapacityReservationID specifies the target Capacity
Reservation into which the instance should be launched.
type: string
iamInstanceProfile:
description: |-
The name or the Amazon Resource Name (ARN) of the instance profile associated
Expand Down Expand Up @@ -857,6 +861,11 @@ spec:
SSHKeyName is the name of the ssh key to attach to the instance. Valid values are empty string
(do not use SSH keys), a valid SSH key name, or omitted (use the default SSH key name)
type: string
useCapacityBlock:
description: |-
UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
If enabled, CapacityReservationID must be specified to identify the target reservation.
type: boolean
versionNumber:
description: |-
VersionNumber is the version of the launch template that is applied.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,11 @@ spec:
cloud-init has built-in support for gzip-compressed user data
user data stored in aws secret manager is always gzip-compressed.
type: boolean
useCapacityBlock:
description: |-
UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
If enabled, CapacityReservationID must be specified to identify the target reservation.
type: boolean
required:
- instanceType
type: object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,11 @@ spec:
cloud-init has built-in support for gzip-compressed user data
user data stored in aws secret manager is always gzip-compressed.
type: boolean
useCapacityBlock:
description: |-
UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
If enabled, CapacityReservationID must be specified to identify the target reservation.
type: boolean
required:
- instanceType
type: object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,10 @@ spec:
description: ID of resource
type: string
type: object
capacityReservationId:
description: CapacityReservationID specifies the target Capacity
Reservation into which the instance should be launched.
type: string
iamInstanceProfile:
description: |-
The name or the Amazon Resource Name (ARN) of the instance profile associated
Expand Down Expand Up @@ -853,6 +857,11 @@ spec:
SSHKeyName is the name of the ssh key to attach to the instance. Valid values are empty string
(do not use SSH keys), a valid SSH key name, or omitted (use the default SSH key name)
type: string
useCapacityBlock:
description: |-
UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
If enabled, CapacityReservationID must be specified to identify the target reservation.
type: boolean
versionNumber:
description: |-
VersionNumber is the version of the launch template that is applied.
Expand Down
18 changes: 17 additions & 1 deletion exp/api/v1beta1/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,16 @@ func (src *AWSMachinePool) ConvertTo(dstRaw conversion.Hub) error {
dst.Spec.AWSLaunchTemplate.PrivateDNSName = restored.Spec.AWSLaunchTemplate.PrivateDNSName
}

if restored.Spec.AWSLaunchTemplate.CapacityReservationID != nil {
dst.Spec.AWSLaunchTemplate.CapacityReservationID = restored.Spec.AWSLaunchTemplate.CapacityReservationID
}

if restored.Spec.AWSLaunchTemplate.UseCapacityBlock != nil {
dst.Spec.AWSLaunchTemplate.UseCapacityBlock = restored.Spec.AWSLaunchTemplate.UseCapacityBlock
}

dst.Spec.DefaultInstanceWarmup = restored.Spec.DefaultInstanceWarmup
dst.Spec.AWSLaunchTemplate.NonRootVolumes = restored.Spec.AWSLaunchTemplate.NonRootVolumes

return nil
}

Expand Down Expand Up @@ -109,6 +116,15 @@ func (src *AWSManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error {
if restored.Spec.AWSLaunchTemplate.PrivateDNSName != nil {
dst.Spec.AWSLaunchTemplate.PrivateDNSName = restored.Spec.AWSLaunchTemplate.PrivateDNSName
}

if restored.Spec.AWSLaunchTemplate.CapacityReservationID != nil {
dst.Spec.AWSLaunchTemplate.CapacityReservationID = restored.Spec.AWSLaunchTemplate.CapacityReservationID
}

if restored.Spec.AWSLaunchTemplate.UseCapacityBlock != nil {
dst.Spec.AWSLaunchTemplate.UseCapacityBlock = restored.Spec.AWSLaunchTemplate.UseCapacityBlock
}

}
if restored.Spec.AvailabilityZoneSubnetType != nil {
dst.Spec.AvailabilityZoneSubnetType = restored.Spec.AvailabilityZoneSubnetType
Expand Down
2 changes: 2 additions & 0 deletions exp/api/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions exp/api/v1beta2/awsmachinepool_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ func (r *AWSMachinePool) ValidateCreate() (admission.Warnings, error) {
allErrs = append(allErrs, r.validateAdditionalSecurityGroups()...)
allErrs = append(allErrs, r.validateSpotInstances()...)
allErrs = append(allErrs, r.validateRefreshPreferences()...)
allErrs = append(allErrs, r.validateInstanceMarketType()...)

if len(allErrs) == 0 {
return nil, nil
Expand All @@ -188,6 +189,14 @@ func (r *AWSMachinePool) ValidateCreate() (admission.Warnings, error) {
)
}

func (r *AWSMachinePool) validateInstanceMarketType() field.ErrorList {
var allErrs field.ErrorList
if r.Spec.AWSLaunchTemplate.UseCapacityBlock != nil && r.Spec.AWSLaunchTemplate.SpotMarketOptions != nil {
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "useCapacityBlock"), "useCapacityBlock and spotMarketOptions cannot be used together"))
}
return allErrs
}

// ValidateUpdate will do any extra validation when updating a AWSMachinePool.
func (r *AWSMachinePool) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) {
var allErrs field.ErrorList
Expand Down
23 changes: 23 additions & 0 deletions exp/api/v1beta2/awsmachinepool_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,29 @@ func TestAWSMachinePoolValidateCreate(t *testing.T) {
},
wantErr: true,
},
{
name: "invalid useCapacityBlock and spotMarketOptions are specified",
pool: &AWSMachinePool{
Spec: AWSMachinePoolSpec{
AWSLaunchTemplate: AWSLaunchTemplate{
UseCapacityBlock: aws.Bool(true),
SpotMarketOptions: &infrav1.SpotMarketOptions{},
},
},
},
wantErr: true,
},
{
name: "valid useCapacityBlock is specified",
pool: &AWSMachinePool{
Spec: AWSMachinePoolSpec{
AWSLaunchTemplate: AWSLaunchTemplate{
UseCapacityBlock: aws.Bool(true),
},
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
9 changes: 9 additions & 0 deletions exp/api/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,15 @@ type AWSLaunchTemplate struct {
// PrivateDNSName is the options for the instance hostname.
// +optional
PrivateDNSName *infrav1.PrivateDNSName `json:"privateDnsName,omitempty"`

// CapacityReservationID specifies the target Capacity Reservation into which the instance should be launched.
// +optional
CapacityReservationID *string `json:"capacityReservationId,omitempty"`

// UseCapacityBlock enables usage of pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
// If enabled, CapacityReservationID must be specified to identify the target reservation.
// +optional
UseCapacityBlock *bool `json:"useCapacityBlock,omitempty"`
}

// Overrides are used to override the instance type specified by the launch template with multiple
Expand Down
10 changes: 10 additions & 0 deletions exp/api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c975830

Please sign in to comment.