Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MaxSpotPriceAsPercentageOfOptimalOnDemandPrice #38003

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .changelog/38003.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
```release-note:enhancement
resource/aws_launch_template: Add `instance_requirements.max_spot_price_as_percentage_of_optimal_on_demand_price` argument
```

```release-note:enhancement
resource/aws_ec2_fleet: Add `launch_template_config.override.instance_requirements.max_spot_price_as_percentage_of_optimal_on_demand_price` argument
```

```release-note:enhancement
resource/aws_autoscaling_group: Add `mixed_instances_policy.launch_template.override.instance_requirements.max_spot_price_as_percentage_of_optimal_on_demand_price` argument
```

```release-note:enhancement
data-source/aws_autoscaling_group: Add `mixed_instances_policy.launch_template.override.instance_requirements.max_spot_price_as_percentage_of_optimal_on_demand_price` attribute
```

```release-note:enhancement
data-source/aws_launch_template: Add `instance_requirements.max_spot_price_as_percentage_of_optimal_on_demand_price` attribute
```
13 changes: 13 additions & 0 deletions internal/service/autoscaling/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,11 @@ func resourceGroup() *schema.Resource {
ValidateDiagFunc: enum.Validate[awstypes.LocalStorageType](),
},
},
"max_spot_price_as_percentage_of_optimal_on_demand_price": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntAtLeast(1),
},
"memory_gib_per_vcpu": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -2886,6 +2891,10 @@ func expandInstanceRequirements(tfMap map[string]interface{}) *awstypes.Instance
apiObject.LocalStorageTypes = flex.ExpandStringyValueSet[awstypes.LocalStorageType](v)
}

if v, ok := tfMap["max_spot_price_as_percentage_of_optimal_on_demand_price"].(int); ok && v != 0 {
apiObject.MaxSpotPriceAsPercentageOfOptimalOnDemandPrice = aws.Int32(int32(v))
}

if v, ok := tfMap["memory_gib_per_vcpu"].([]interface{}); ok && len(v) > 0 {
apiObject.MemoryGiBPerVCpu = expandMemoryGiBPerVCPURequest(v[0].(map[string]interface{}))
}
Expand Down Expand Up @@ -3674,6 +3683,10 @@ func flattenInstanceRequirements(apiObject *awstypes.InstanceRequirements) map[s
tfMap["local_storage_types"] = apiObject.LocalStorageTypes
}

if v := apiObject.MaxSpotPriceAsPercentageOfOptimalOnDemandPrice; v != nil {
tfMap["max_spot_price_as_percentage_of_optimal_on_demand_price"] = aws.ToInt32(v)
}

if v := apiObject.MemoryGiBPerVCpu; v != nil {
tfMap["memory_gib_per_vcpu"] = []interface{}{flattenMemoryGiBPerVCPU(v)}
}
Expand Down
4 changes: 4 additions & 0 deletions internal/service/autoscaling/group_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ func dataSourceGroup() *schema.Resource {
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"max_spot_price_as_percentage_of_optimal_on_demand_price": {
Type: schema.TypeInt,
Computed: true,
},
"memory_gib_per_vcpu": {
Type: schema.TypeList,
Computed: true,
Expand Down
36 changes: 36 additions & 0 deletions internal/service/autoscaling/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3486,6 +3486,42 @@ func TestAccAutoScalingGroup_MixedInstancesPolicyLaunchTemplateOverride_instance
})
}

func TestAccAutoScalingGroup_MixedInstancesPolicyLaunchTemplateOverride_instanceRequirements_maxSpotPriceAsPercentageOfOptimalOnDemandPrice(t *testing.T) {
ctx := acctest.Context(t)
var group awstypes.AutoScalingGroup
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_autoscaling_group.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.AutoScalingServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckGroupDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccGroupConfig_mixedInstancesPolicyLaunchTemplateOverrideInstanceRequirements(rName,
`max_spot_price_as_percentage_of_optimal_on_demand_price = 75
memory_mib {
min = 500
}
vcpu_count {
min = 1
}`),
Check: resource.ComposeTestCheckFunc(
testAccCheckGroupExists(ctx, resourceName, &group),
resource.TestCheckResourceAttr(resourceName, "mixed_instances_policy.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "mixed_instances_policy.0.launch_template.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "mixed_instances_policy.0.launch_template.0.override.#", acctest.Ct1),

resource.TestCheckResourceAttr(resourceName, "mixed_instances_policy.0.launch_template.0.override.0.instance_requirements.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "mixed_instances_policy.0.launch_template.0.override.0.instance_requirements.0.max_spot_price_as_percentage_of_optimal_on_demand_price", "75"),
),
},
testAccGroupImportStep(resourceName),
},
})
}

func TestAccAutoScalingGroup_MixedInstancesPolicyLaunchTemplateOverride_instanceRequirements_memoryGiBPerVCPU(t *testing.T) {
ctx := acctest.Context(t)
var group awstypes.AutoScalingGroup
Expand Down
5 changes: 5 additions & 0 deletions internal/service/ec2/ec2_fleet.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,11 @@ func resourceFleet() *schema.Resource {
ValidateDiagFunc: enum.Validate[awstypes.LocalStorageType](),
},
},
"max_spot_price_as_percentage_of_optimal_on_demand_price": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntAtLeast(1),
},
"memory_gib_per_vcpu": {
Type: schema.TypeList,
Optional: true,
Expand Down
39 changes: 39 additions & 0 deletions internal/service/ec2/ec2_fleet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1561,6 +1561,45 @@ func TestAccEC2Fleet_LaunchTemplateOverride_instanceRequirements_localStorageTyp
})
}

func TestAccEC2Fleet_LaunchTemplateOverride_instanceRequirements_maxSpotPriceAsPercentageOfOptimalOnDemandPrice(t *testing.T) {
ctx := acctest.Context(t)
var fleet awstypes.FleetData
resourceName := "aws_ec2_fleet.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckFleet(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckFleetDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccFleetConfig_launchTemplateOverrideInstanceRequirements(sdkacctest.RandomWithPrefix(acctest.ResourcePrefix),
`max_spot_price_as_percentage_of_optimal_on_demand_price = 75
memory_mib {
min = 500
}
vcpu_count {
min = 1
}`),
Check: resource.ComposeTestCheckFunc(
testAccCheckFleetExists(ctx, resourceName, &fleet),
resource.TestCheckResourceAttr(resourceName, "launch_template_config.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "launch_template_config.0.override.#", acctest.Ct1),

resource.TestCheckResourceAttr(resourceName, "launch_template_config.0.override.0.instance_requirements.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "launch_template_config.0.override.0.instance_requirements.0.max_spot_price_as_percentage_of_optimal_on_demand_price", "75"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"terminate_instances"},
},
},
})
}

func TestAccEC2Fleet_LaunchTemplateOverride_instanceRequirements_memoryGiBPerVCPU(t *testing.T) {
ctx := acctest.Context(t)
var fleet awstypes.FleetData
Expand Down
21 changes: 18 additions & 3 deletions internal/service/ec2/ec2_launch_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,12 @@ func resourceLaunchTemplate() *schema.Resource {
ValidateDiagFunc: enum.Validate[awstypes.LocalStorageType](),
},
},
"max_spot_price_as_percentage_of_optimal_on_demand_price": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntAtLeast(1),
ConflictsWith: []string{"instance_requirements.0.spot_max_price_percentage_over_lowest_price"},
},
"memory_gib_per_vcpu": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -572,9 +578,10 @@ func resourceLaunchTemplate() *schema.Resource {
Optional: true,
},
"spot_max_price_percentage_over_lowest_price": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntAtLeast(1),
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntAtLeast(1),
ConflictsWith: []string{"instance_requirements.0.max_spot_price_as_percentage_of_optimal_on_demand_price"},
},
"total_local_storage_gb": {
Type: schema.TypeList,
Expand Down Expand Up @@ -1600,6 +1607,10 @@ func expandInstanceRequirementsRequest(tfMap map[string]interface{}) *awstypes.I
apiObject.LocalStorageTypes = flex.ExpandStringyValueSet[awstypes.LocalStorageType](v)
}

if v, ok := tfMap["max_spot_price_as_percentage_of_optimal_on_demand_price"].(int); ok && v != 0 {
apiObject.MaxSpotPriceAsPercentageOfOptimalOnDemandPrice = aws.Int32(int32(v))
}

if v, ok := tfMap["memory_gib_per_vcpu"].([]interface{}); ok && len(v) > 0 && v[0] != nil {
apiObject.MemoryGiBPerVCpu = expandMemoryGiBPerVCPURequest(v[0].(map[string]interface{}))
}
Expand Down Expand Up @@ -2565,6 +2576,10 @@ func flattenInstanceRequirements(apiObject *awstypes.InstanceRequirements) map[s
tfMap["local_storage_types"] = flex.FlattenStringyValueSet[awstypes.LocalStorageType](v)
}

if v := apiObject.MaxSpotPriceAsPercentageOfOptimalOnDemandPrice; v != nil {
tfMap["max_spot_price_as_percentage_of_optimal_on_demand_price"] = aws.ToInt32(v)
}

if v := apiObject.MemoryGiBPerVCpu; v != nil {
tfMap["memory_gib_per_vcpu"] = []interface{}{flattenMemoryGiBPerVCPU(v)}
}
Expand Down
4 changes: 4 additions & 0 deletions internal/service/ec2/ec2_launch_template_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,10 @@ func dataSourceLaunchTemplate() *schema.Resource {
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"max_spot_price_as_percentage_of_optimal_on_demand_price": {
Type: schema.TypeInt,
Computed: true,
},
"memory_gib_per_vcpu": {
Type: schema.TypeList,
Computed: true,
Expand Down
35 changes: 35 additions & 0 deletions internal/service/ec2/ec2_launch_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,41 @@ func TestAccEC2LaunchTemplate_instanceRequirements_localStorageTypes(t *testing.
})
}

func TestAccEC2LaunchTemplate_instanceRequirements_maxSpotPriceAsPercentageOfOptimalOnDemandPrice(t *testing.T) {
ctx := acctest.Context(t)
var template awstypes.LaunchTemplate
resourceName := "aws_launch_template.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckLaunchTemplateDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccLaunchTemplateConfig_instanceRequirements(sdkacctest.RandomWithPrefix(acctest.ResourcePrefix),
`max_spot_price_as_percentage_of_optimal_on_demand_price = 75
memory_mib {
min = 500
}
vcpu_count {
min = 1
}`),
Check: resource.ComposeTestCheckFunc(
testAccCheckLaunchTemplateExists(ctx, resourceName, &template),
resource.TestCheckResourceAttr(resourceName, "instance_requirements.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "instance_requirements.0.max_spot_price_as_percentage_of_optimal_on_demand_price", "75"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccEC2LaunchTemplate_instanceRequirements_memoryGiBPerVCPU(t *testing.T) {
ctx := acctest.Context(t)
var template awstypes.LaunchTemplate
Expand Down
1 change: 1 addition & 0 deletions website/docs/d/autoscaling_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ interpolation.
* `instance_generations` - List of instance generation names.
* `local_storage` - Indicates whether instance types with instance store volumes are included, excluded, or required.
* `local_storage_types` - List of local storage type names.
* `max_spot_price_as_percentage_of_optimal_on_demand_price` - Price protection threshold for Spot Instances.
* `memory_gib_per_vcpu` - List of objects describing the minimum and maximum amount of memory (GiB) per vCPU.
* `min` - Minimum.
* `max` - Maximum.
Expand Down
3 changes: 2 additions & 1 deletion website/docs/r/autoscaling_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ This configuration block supports the following:
* ssd - solid state drive
```

- `max_spot_price_as_percentage_of_optimal_on_demand_price` - (Optional) The price protection threshold for Spot Instances. This is the maximum you’ll pay for a Spot Instance, expressed as a percentage higher than the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 Auto Scaling selects instance types with your attributes, we will exclude instance types whose price is higher than your threshold. The parameter accepts an integer, which Amazon EC2 Auto Scaling interprets as a percentage. To turn off price protection, specify a high value, such as 999999. Conflicts with `spot_max_price_percentage_over_lowest_price`
- `memory_gib_per_vcpu` - (Optional) Block describing the minimum and maximum amount of memory (GiB) per vCPU. Default is no minimum or maximum.
- `min` - (Optional) Minimum. May be a decimal number, e.g. `0.5`.
- `max` - (Optional) Maximum. May be a decimal number, e.g. `0.5`.
Expand All @@ -629,7 +630,7 @@ This configuration block supports the following:
If you set DesiredCapacityType to vcpu or memory-mib, the price protection threshold is applied based on the per vCPU or per memory price instead of the per instance price.

- `require_hibernate_support` - (Optional) Indicate whether instance types must support On-Demand Instance Hibernation, either `true` or `false`. Default is `false`.
- `spot_max_price_percentage_over_lowest_price` - (Optional) Price protection threshold for Spot Instances. This is the maximum you’ll pay for a Spot Instance, expressed as a percentage higher than the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 Auto Scaling selects instance types with your attributes, we will exclude instance types whose price is higher than your threshold. The parameter accepts an integer, which Amazon EC2 Auto Scaling interprets as a percentage. To turn off price protection, specify a high value, such as 999999. Default is 100.
- `spot_max_price_percentage_over_lowest_price` - (Optional) Price protection threshold for Spot Instances. This is the maximum you’ll pay for a Spot Instance, expressed as a percentage higher than the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 Auto Scaling selects instance types with your attributes, we will exclude instance types whose price is higher than your threshold. The parameter accepts an integer, which Amazon EC2 Auto Scaling interprets as a percentage. To turn off price protection, specify a high value, such as 999999. Default is 100. Conflicts with `max_spot_price_as_percentage_of_optimal_on_demand_price`

If you set DesiredCapacityType to vcpu or memory-mib, the price protection threshold is applied based on the per vCPU or per memory price instead of the per instance price.

Expand Down
3 changes: 2 additions & 1 deletion website/docs/r/ec2_fleet.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ This configuration block supports the following:
* `instance_generations` - (Optional) Indicates whether current or previous generation instance types are included. The current generation instance types are recommended for use. Valid values are `current` and `previous`. Default is `current` and `previous` generation instance types.
* `local_storage` - (Optional) Indicate whether instance types with local storage volumes are `included`, `excluded`, or `required`. Default is `included`.
* `local_storage_types` - (Optional) List of local storage type names. Valid values are `hdd` and `ssd`. Default any storage type.
* `max_spot_price_as_percentage_of_optimal_on_demand_price` - (Optional) The price protection threshold for Spot Instances. This is the maximum you’ll pay for a Spot Instance, expressed as a percentage higher than the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 Auto Scaling selects instance types with your attributes, we will exclude instance types whose price is higher than your threshold. The parameter accepts an integer, which Amazon EC2 Auto Scaling interprets as a percentage. To turn off price protection, specify a high value, such as 999999. Conflicts with `spot_max_price_percentage_over_lowest_price`
* `memory_gib_per_vcpu` - (Optional) Block describing the minimum and maximum amount of memory (GiB) per vCPU. Default is no minimum or maximum.
* `min` - (Optional) The minimum amount of memory per vCPU, in GiB. To specify no minimum limit, omit this parameter.
* `max` - (Optional) The maximum amount of memory per vCPU, in GiB. To specify no maximum limit, omit this parameter.
Expand All @@ -147,7 +148,7 @@ This configuration block supports the following:
If you set `target_capacity_unit_type` to `vcpu` or `memory-mib`, the price protection threshold is applied based on the per-vCPU or per-memory price instead of the per-instance price.

* `require_hibernate_support` - (Optional) Indicate whether instance types must support On-Demand Instance Hibernation, either `true` or `false`. Default is `false`.
* `spot_max_price_percentage_over_lowest_price` - (Optional) The price protection threshold for Spot Instances. This is the maximum you’ll pay for a Spot Instance, expressed as a percentage higher than the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 Auto Scaling selects instance types with your attributes, we will exclude instance types whose price is higher than your threshold. The parameter accepts an integer, which Amazon EC2 Auto Scaling interprets as a percentage. To turn off price protection, specify a high value, such as 999999. Default is 100.
* `spot_max_price_percentage_over_lowest_price` - (Optional) The price protection threshold for Spot Instances. This is the maximum you’ll pay for a Spot Instance, expressed as a percentage higher than the cheapest M, C, or R instance type with your specified attributes. When Amazon EC2 Auto Scaling selects instance types with your attributes, we will exclude instance types whose price is higher than your threshold. The parameter accepts an integer, which Amazon EC2 Auto Scaling interprets as a percentage. To turn off price protection, specify a high value, such as 999999. Default is 100. Conflicts with `max_spot_price_as_percentage_of_optimal_on_demand_price`

If you set DesiredCapacityType to vcpu or memory-mib, the price protection threshold is applied based on the per vCPU or per memory price instead of the per instance price.

Expand Down
Loading
Loading