Skip to content

Commit fef3eea

Browse files
authored
Merge pull request #5211 from athiruma/add_instance_market_option
✨ Add the support for capacity blocks
2 parents b92e5eb + 66769de commit fef3eea

24 files changed

+901
-58
lines changed

api/v1beta1/awscluster_conversion.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ func (src *AWSCluster) ConvertTo(dstRaw conversion.Hub) error {
6060
dst.Status.Bastion.PrivateDNSName = restored.Status.Bastion.PrivateDNSName
6161
dst.Status.Bastion.PublicIPOnLaunch = restored.Status.Bastion.PublicIPOnLaunch
6262
dst.Status.Bastion.CapacityReservationID = restored.Status.Bastion.CapacityReservationID
63+
dst.Status.Bastion.MarketType = restored.Status.Bastion.MarketType
6364
}
6465
dst.Spec.Partition = restored.Spec.Partition
6566

api/v1beta1/awsmachine_conversion.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func (src *AWSMachine) ConvertTo(dstRaw conversion.Hub) error {
4242
dst.Spec.PrivateDNSName = restored.Spec.PrivateDNSName
4343
dst.Spec.SecurityGroupOverrides = restored.Spec.SecurityGroupOverrides
4444
dst.Spec.CapacityReservationID = restored.Spec.CapacityReservationID
45+
dst.Spec.MarketType = restored.Spec.MarketType
4546
if restored.Spec.ElasticIPPool != nil {
4647
if dst.Spec.ElasticIPPool == nil {
4748
dst.Spec.ElasticIPPool = &infrav1.ElasticIPPool{}
@@ -104,6 +105,7 @@ func (r *AWSMachineTemplate) ConvertTo(dstRaw conversion.Hub) error {
104105
dst.Spec.Template.Spec.PrivateDNSName = restored.Spec.Template.Spec.PrivateDNSName
105106
dst.Spec.Template.Spec.SecurityGroupOverrides = restored.Spec.Template.Spec.SecurityGroupOverrides
106107
dst.Spec.Template.Spec.CapacityReservationID = restored.Spec.Template.Spec.CapacityReservationID
108+
dst.Spec.Template.Spec.MarketType = restored.Spec.Template.Spec.MarketType
107109
if restored.Spec.Template.Spec.ElasticIPPool != nil {
108110
if dst.Spec.Template.Spec.ElasticIPPool == nil {
109111
dst.Spec.Template.Spec.ElasticIPPool = &infrav1.ElasticIPPool{}

api/v1beta1/zz_generated.conversion.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1beta2/awsmachine_types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ type AWSMachineSpec struct {
197197
// CapacityReservationID specifies the target Capacity Reservation into which the instance should be launched.
198198
// +optional
199199
CapacityReservationID *string `json:"capacityReservationId,omitempty"`
200+
201+
// MarketType specifies the type of market for the EC2 instance. Valid values include:
202+
// "OnDemand" (default): The instance runs as a standard OnDemand instance.
203+
// "Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
204+
// "CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
205+
// If this value is selected, CapacityReservationID must be specified to identify the target reservation.
206+
// If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
207+
// +optional
208+
MarketType MarketType `json:"marketType,omitempty"`
200209
}
201210

202211
// CloudInit defines options related to the bootstrapping systems where

api/v1beta2/awsmachine_webhook.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ func (r *AWSMachine) ValidateCreate() (admission.Warnings, error) {
6666
allErrs = append(allErrs, r.validateAdditionalSecurityGroups()...)
6767
allErrs = append(allErrs, r.Spec.AdditionalTags.Validate()...)
6868
allErrs = append(allErrs, r.validateNetworkElasticIPPool()...)
69+
allErrs = append(allErrs, r.validateInstanceMarketType()...)
6970

7071
return nil, aggregateObjErrors(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
7172
}
@@ -361,6 +362,20 @@ func (r *AWSMachine) validateNetworkElasticIPPool() field.ErrorList {
361362
return allErrs
362363
}
363364

365+
func (r *AWSMachine) validateInstanceMarketType() field.ErrorList {
366+
var allErrs field.ErrorList
367+
if r.Spec.MarketType == MarketTypeCapacityBlock && r.Spec.SpotMarketOptions != nil {
368+
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "marketType"), "marketType set to CapacityBlock and spotMarketOptions cannot be used together"))
369+
}
370+
if r.Spec.MarketType == MarketTypeOnDemand && r.Spec.SpotMarketOptions != nil {
371+
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "marketType"), "setting marketType to OnDemand and spotMarketOptions cannot be used together"))
372+
}
373+
if r.Spec.MarketType == MarketTypeCapacityBlock && r.Spec.CapacityReservationID == nil {
374+
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "capacityReservationID"), "is required when CapacityBlock is provided"))
375+
}
376+
return allErrs
377+
}
378+
364379
func (r *AWSMachine) validateNonRootVolumes() field.ErrorList {
365380
var allErrs field.ErrorList
366381

api/v1beta2/awsmachine_webhook_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,49 @@ func TestAWSMachineCreate(t *testing.T) {
217217
},
218218
wantErr: false,
219219
},
220+
{
221+
name: "invalid case, MarketType set to MarketTypeCapacityBlock and spotMarketOptions are specified",
222+
machine: &AWSMachine{
223+
Spec: AWSMachineSpec{
224+
MarketType: MarketTypeCapacityBlock,
225+
SpotMarketOptions: &SpotMarketOptions{},
226+
InstanceType: "test",
227+
},
228+
},
229+
wantErr: true,
230+
},
231+
{
232+
name: "invalid case, MarketType set to MarketTypeOnDemand and spotMarketOptions are specified",
233+
machine: &AWSMachine{
234+
Spec: AWSMachineSpec{
235+
MarketType: MarketTypeOnDemand,
236+
SpotMarketOptions: &SpotMarketOptions{},
237+
InstanceType: "test",
238+
},
239+
},
240+
wantErr: true,
241+
},
242+
{
243+
name: "valid MarketType set to MarketTypeCapacityBlock is specified and CapacityReservationId is not provided",
244+
machine: &AWSMachine{
245+
Spec: AWSMachineSpec{
246+
MarketType: MarketTypeCapacityBlock,
247+
InstanceType: "test",
248+
},
249+
},
250+
wantErr: true,
251+
},
252+
{
253+
name: "valid MarketType set to MarketTypeCapacityBlock and CapacityReservationId are specified",
254+
machine: &AWSMachine{
255+
Spec: AWSMachineSpec{
256+
MarketType: MarketTypeCapacityBlock,
257+
CapacityReservationID: aws.String("cr-12345678901234567"),
258+
InstanceType: "test",
259+
},
260+
},
261+
wantErr: false,
262+
},
220263
{
221264
name: "empty instance type not allowed",
222265
machine: &AWSMachine{

api/v1beta2/types.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,32 @@ type Instance struct {
261261
// CapacityReservationID specifies the target Capacity Reservation into which the instance should be launched.
262262
// +optional
263263
CapacityReservationID *string `json:"capacityReservationId,omitempty"`
264+
265+
// MarketType specifies the type of market for the EC2 instance. Valid values include:
266+
// "OnDemand" (default): The instance runs as a standard OnDemand instance.
267+
// "Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
268+
// "CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
269+
// If this value is selected, CapacityReservationID must be specified to identify the target reservation.
270+
// If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
271+
// +optional
272+
MarketType MarketType `json:"marketType,omitempty"`
264273
}
265274

275+
// MarketType describes the market type of an Instance
276+
// +kubebuilder:validation:Enum:=OnDemand;Spot;CapacityBlock
277+
type MarketType string
278+
279+
const (
280+
// MarketTypeOnDemand is a MarketType enum value
281+
MarketTypeOnDemand MarketType = "OnDemand"
282+
283+
// MarketTypeSpot is a MarketType enum value
284+
MarketTypeSpot MarketType = "Spot"
285+
286+
// MarketTypeCapacityBlock is a MarketType enum value
287+
MarketTypeCapacityBlock MarketType = "CapacityBlock"
288+
)
289+
266290
// InstanceMetadataState describes the state of InstanceMetadataOptions.HttpEndpoint and InstanceMetadataOptions.InstanceMetadataTags
267291
type InstanceMetadataState string
268292

config/crd/bases/controlplane.cluster.x-k8s.io_awsmanagedcontrolplanes.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,6 +1210,19 @@ spec:
12101210
instanceState:
12111211
description: The current state of the instance.
12121212
type: string
1213+
marketType:
1214+
description: |-
1215+
MarketType specifies the type of market for the EC2 instance. Valid values include:
1216+
"OnDemand" (default): The instance runs as a standard OnDemand instance.
1217+
"Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
1218+
"CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
1219+
If this value is selected, CapacityReservationID must be specified to identify the target reservation.
1220+
If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
1221+
enum:
1222+
- OnDemand
1223+
- Spot
1224+
- CapacityBlock
1225+
type: string
12131226
networkInterfaces:
12141227
description: Specifies ENIs attached to instance
12151228
items:
@@ -3250,6 +3263,19 @@ spec:
32503263
instanceState:
32513264
description: The current state of the instance.
32523265
type: string
3266+
marketType:
3267+
description: |-
3268+
MarketType specifies the type of market for the EC2 instance. Valid values include:
3269+
"OnDemand" (default): The instance runs as a standard OnDemand instance.
3270+
"Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
3271+
"CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
3272+
If this value is selected, CapacityReservationID must be specified to identify the target reservation.
3273+
If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
3274+
enum:
3275+
- OnDemand
3276+
- Spot
3277+
- CapacityBlock
3278+
type: string
32533279
networkInterfaces:
32543280
description: Specifies ENIs attached to instance
32553281
items:

config/crd/bases/infrastructure.cluster.x-k8s.io_awsclusters.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2177,6 +2177,19 @@ spec:
21772177
instanceState:
21782178
description: The current state of the instance.
21792179
type: string
2180+
marketType:
2181+
description: |-
2182+
MarketType specifies the type of market for the EC2 instance. Valid values include:
2183+
"OnDemand" (default): The instance runs as a standard OnDemand instance.
2184+
"Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
2185+
"CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
2186+
If this value is selected, CapacityReservationID must be specified to identify the target reservation.
2187+
If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
2188+
enum:
2189+
- OnDemand
2190+
- Spot
2191+
- CapacityBlock
2192+
type: string
21802193
networkInterfaces:
21812194
description: Specifies ENIs attached to instance
21822195
items:

config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinepools.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,10 @@ spec:
629629
description: ID of resource
630630
type: string
631631
type: object
632+
capacityReservationId:
633+
description: CapacityReservationID specifies the target Capacity
634+
Reservation into which the instance should be launched.
635+
type: string
632636
iamInstanceProfile:
633637
description: |-
634638
The name or the Amazon Resource Name (ARN) of the instance profile associated
@@ -724,6 +728,19 @@ spec:
724728
description: 'InstanceType is the type of instance to create.
725729
Example: m4.xlarge'
726730
type: string
731+
marketType:
732+
description: |-
733+
MarketType specifies the type of market for the EC2 instance. Valid values include:
734+
"OnDemand" (default): The instance runs as a standard OnDemand instance.
735+
"Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
736+
"CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
737+
If this value is selected, CapacityReservationID must be specified to identify the target reservation.
738+
If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
739+
enum:
740+
- OnDemand
741+
- Spot
742+
- CapacityBlock
743+
type: string
727744
name:
728745
description: The name of the launch template.
729746
type: string

config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachines.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,19 @@ spec:
878878
m4.xlarge'
879879
minLength: 2
880880
type: string
881+
marketType:
882+
description: |-
883+
MarketType specifies the type of market for the EC2 instance. Valid values include:
884+
"OnDemand" (default): The instance runs as a standard OnDemand instance.
885+
"Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
886+
"CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
887+
If this value is selected, CapacityReservationID must be specified to identify the target reservation.
888+
If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
889+
enum:
890+
- OnDemand
891+
- Spot
892+
- CapacityBlock
893+
type: string
881894
networkInterfaces:
882895
description: |-
883896
NetworkInterfaces is a list of ENIs to associate with the instance.

config/crd/bases/infrastructure.cluster.x-k8s.io_awsmachinetemplates.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,19 @@ spec:
812812
Example: m4.xlarge'
813813
minLength: 2
814814
type: string
815+
marketType:
816+
description: |-
817+
MarketType specifies the type of market for the EC2 instance. Valid values include:
818+
"OnDemand" (default): The instance runs as a standard OnDemand instance.
819+
"Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
820+
"CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
821+
If this value is selected, CapacityReservationID must be specified to identify the target reservation.
822+
If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
823+
enum:
824+
- OnDemand
825+
- Spot
826+
- CapacityBlock
827+
type: string
815828
networkInterfaces:
816829
description: |-
817830
NetworkInterfaces is a list of ENIs to associate with the instance.

config/crd/bases/infrastructure.cluster.x-k8s.io_awsmanagedmachinepools.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,10 @@ spec:
625625
description: ID of resource
626626
type: string
627627
type: object
628+
capacityReservationId:
629+
description: CapacityReservationID specifies the target Capacity
630+
Reservation into which the instance should be launched.
631+
type: string
628632
iamInstanceProfile:
629633
description: |-
630634
The name or the Amazon Resource Name (ARN) of the instance profile associated
@@ -720,6 +724,19 @@ spec:
720724
description: 'InstanceType is the type of instance to create.
721725
Example: m4.xlarge'
722726
type: string
727+
marketType:
728+
description: |-
729+
MarketType specifies the type of market for the EC2 instance. Valid values include:
730+
"OnDemand" (default): The instance runs as a standard OnDemand instance.
731+
"Spot": The instance runs as a Spot instance. When SpotMarketOptions is provided, the marketType defaults to "Spot".
732+
"CapacityBlock": The instance utilizes pre-purchased compute capacity (capacity blocks) with AWS Capacity Reservations.
733+
If this value is selected, CapacityReservationID must be specified to identify the target reservation.
734+
If marketType is not specified and spotMarketOptions is provided, the marketType defaults to "Spot".
735+
enum:
736+
- OnDemand
737+
- Spot
738+
- CapacityBlock
739+
type: string
723740
name:
724741
description: The name of the launch template.
725742
type: string

exp/api/v1beta1/conversion.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,16 @@ func (src *AWSMachinePool) ConvertTo(dstRaw conversion.Hub) error {
5757
dst.Spec.AWSLaunchTemplate.PrivateDNSName = restored.Spec.AWSLaunchTemplate.PrivateDNSName
5858
}
5959

60+
if restored.Spec.AWSLaunchTemplate.CapacityReservationID != nil {
61+
dst.Spec.AWSLaunchTemplate.CapacityReservationID = restored.Spec.AWSLaunchTemplate.CapacityReservationID
62+
}
63+
64+
if restored.Spec.AWSLaunchTemplate.MarketType != "" {
65+
dst.Spec.AWSLaunchTemplate.MarketType = restored.Spec.AWSLaunchTemplate.MarketType
66+
}
67+
6068
dst.Spec.DefaultInstanceWarmup = restored.Spec.DefaultInstanceWarmup
6169
dst.Spec.AWSLaunchTemplate.NonRootVolumes = restored.Spec.AWSLaunchTemplate.NonRootVolumes
62-
6370
return nil
6471
}
6572

@@ -109,6 +116,15 @@ func (src *AWSManagedMachinePool) ConvertTo(dstRaw conversion.Hub) error {
109116
if restored.Spec.AWSLaunchTemplate.PrivateDNSName != nil {
110117
dst.Spec.AWSLaunchTemplate.PrivateDNSName = restored.Spec.AWSLaunchTemplate.PrivateDNSName
111118
}
119+
120+
if restored.Spec.AWSLaunchTemplate.CapacityReservationID != nil {
121+
dst.Spec.AWSLaunchTemplate.CapacityReservationID = restored.Spec.AWSLaunchTemplate.CapacityReservationID
122+
}
123+
124+
if restored.Spec.AWSLaunchTemplate.MarketType != "" {
125+
dst.Spec.AWSLaunchTemplate.MarketType = restored.Spec.AWSLaunchTemplate.MarketType
126+
}
127+
112128
}
113129
if restored.Spec.AvailabilityZoneSubnetType != nil {
114130
dst.Spec.AvailabilityZoneSubnetType = restored.Spec.AvailabilityZoneSubnetType

exp/api/v1beta1/zz_generated.conversion.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)