provider/aws: Add replace_unhealthy_instances to spot_fleet_request (#12681)

Fixes: #12635

```
% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSSpotFleetRequest_'                                                                    ✹
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/03/14 15:57:08 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSpotFleetRequest_ -timeout 120m
=== RUN   TestAccAWSSpotFleetRequest_changePriceForcesNewRequest
--- PASS: TestAccAWSSpotFleetRequest_changePriceForcesNewRequest (182.81s)
=== RUN   TestAccAWSSpotFleetRequest_lowestPriceAzOrSubnetInRegion
--- PASS: TestAccAWSSpotFleetRequest_lowestPriceAzOrSubnetInRegion (88.80s)
=== RUN   TestAccAWSSpotFleetRequest_lowestPriceAzInGivenList
--- PASS: TestAccAWSSpotFleetRequest_lowestPriceAzInGivenList (92.50s)
=== RUN   TestAccAWSSpotFleetRequest_lowestPriceSubnetInGivenList
--- PASS: TestAccAWSSpotFleetRequest_lowestPriceSubnetInGivenList (119.25s)
=== RUN   TestAccAWSSpotFleetRequest_multipleInstanceTypesInSameAz
--- PASS: TestAccAWSSpotFleetRequest_multipleInstanceTypesInSameAz (95.23s)
=== RUN   TestAccAWSSpotFleetRequest_multipleInstanceTypesInSameSubnet
--- PASS: TestAccAWSSpotFleetRequest_multipleInstanceTypesInSameSubnet (125.55s)
=== RUN   TestAccAWSSpotFleetRequest_overriddingSpotPrice
--- PASS: TestAccAWSSpotFleetRequest_overriddingSpotPrice (92.24s)
=== RUN   TestAccAWSSpotFleetRequest_diversifiedAllocation
--- PASS: TestAccAWSSpotFleetRequest_diversifiedAllocation (400.04s)
=== RUN   TestAccAWSSpotFleetRequest_withWeightedCapacity
--- PASS: TestAccAWSSpotFleetRequest_withWeightedCapacity (349.51s)
=== RUN   TestAccAWSSpotFleetRequest_withEBSDisk
--- PASS: TestAccAWSSpotFleetRequest_withEBSDisk (86.70s)
=== RUN   TestAccAWSSpotFleetRequest_CannotUseEmptyKeyName
--- PASS: TestAccAWSSpotFleetRequest_CannotUseEmptyKeyName (0.00s)
PASS
ok	github.com/hashicorp/terraform/builtin/providers/aws	1632.663s
```
This commit is contained in:
Paul Stack 2017-03-14 18:23:00 +02:00 committed by GitHub
parent 38fc08306c
commit ad12d8804b
2 changed files with 50 additions and 41 deletions

View File

@ -26,73 +26,79 @@ func resourceAwsSpotFleetRequest() *schema.Resource {
MigrateState: resourceAwsSpotFleetRequestMigrateState, MigrateState: resourceAwsSpotFleetRequestMigrateState,
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"iam_fleet_role": &schema.Schema{ "iam_fleet_role": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"replace_unhealthy_instances": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
},
// http://docs.aws.amazon.com/sdk-for-go/api/service/ec2.html#type-SpotFleetLaunchSpecification // http://docs.aws.amazon.com/sdk-for-go/api/service/ec2.html#type-SpotFleetLaunchSpecification
// http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_SpotFleetLaunchSpecification.html // http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_SpotFleetLaunchSpecification.html
"launch_specification": &schema.Schema{ "launch_specification": {
Type: schema.TypeSet, Type: schema.TypeSet,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"vpc_security_group_ids": &schema.Schema{ "vpc_security_group_ids": {
Type: schema.TypeSet, Type: schema.TypeSet,
Optional: true, Optional: true,
Computed: true, Computed: true,
Elem: &schema.Schema{Type: schema.TypeString}, Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString, Set: schema.HashString,
}, },
"associate_public_ip_address": &schema.Schema{ "associate_public_ip_address": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Default: false, Default: false,
}, },
"ebs_block_device": &schema.Schema{ "ebs_block_device": {
Type: schema.TypeSet, Type: schema.TypeSet,
Optional: true, Optional: true,
Computed: true, Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"delete_on_termination": &schema.Schema{ "delete_on_termination": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Default: true, Default: true,
ForceNew: true, ForceNew: true,
}, },
"device_name": &schema.Schema{ "device_name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"encrypted": &schema.Schema{ "encrypted": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"iops": &schema.Schema{ "iops": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"snapshot_id": &schema.Schema{ "snapshot_id": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"volume_size": &schema.Schema{ "volume_size": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"volume_type": &schema.Schema{ "volume_type": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
@ -102,18 +108,18 @@ func resourceAwsSpotFleetRequest() *schema.Resource {
}, },
Set: hashEbsBlockDevice, Set: hashEbsBlockDevice,
}, },
"ephemeral_block_device": &schema.Schema{ "ephemeral_block_device": {
Type: schema.TypeSet, Type: schema.TypeSet,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"device_name": &schema.Schema{ "device_name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
}, },
"virtual_name": &schema.Schema{ "virtual_name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
}, },
@ -121,7 +127,7 @@ func resourceAwsSpotFleetRequest() *schema.Resource {
}, },
Set: hashEphemeralBlockDevice, Set: hashEphemeralBlockDevice,
}, },
"root_block_device": &schema.Schema{ "root_block_device": {
// TODO: This is a set because we don't support singleton // TODO: This is a set because we don't support singleton
// sub-resources today. We'll enforce that the set only ever has // sub-resources today. We'll enforce that the set only ever has
// length zero or one below. When TF gains support for // length zero or one below. When TF gains support for
@ -134,25 +140,25 @@ func resourceAwsSpotFleetRequest() *schema.Resource {
// Termination flag on the block device mapping entry for the root // Termination flag on the block device mapping entry for the root
// device volume." - bit.ly/ec2bdmap // device volume." - bit.ly/ec2bdmap
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"delete_on_termination": &schema.Schema{ "delete_on_termination": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Default: true, Default: true,
ForceNew: true, ForceNew: true,
}, },
"iops": &schema.Schema{ "iops": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"volume_size": &schema.Schema{ "volume_size": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"volume_type": &schema.Schema{ "volume_type": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
@ -162,50 +168,50 @@ func resourceAwsSpotFleetRequest() *schema.Resource {
}, },
Set: hashRootBlockDevice, Set: hashRootBlockDevice,
}, },
"ebs_optimized": &schema.Schema{ "ebs_optimized": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Default: false, Default: false,
}, },
"iam_instance_profile": &schema.Schema{ "iam_instance_profile": {
Type: schema.TypeString, Type: schema.TypeString,
ForceNew: true, ForceNew: true,
Optional: true, Optional: true,
}, },
"ami": &schema.Schema{ "ami": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"instance_type": &schema.Schema{ "instance_type": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"key_name": &schema.Schema{ "key_name": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
Computed: true, Computed: true,
ValidateFunc: validateSpotFleetRequestKeyName, ValidateFunc: validateSpotFleetRequestKeyName,
}, },
"monitoring": &schema.Schema{ "monitoring": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Default: false, Default: false,
}, },
"placement_group": &schema.Schema{ "placement_group": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"spot_price": &schema.Schema{ "spot_price": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"user_data": &schema.Schema{ "user_data": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
@ -218,18 +224,18 @@ func resourceAwsSpotFleetRequest() *schema.Resource {
} }
}, },
}, },
"weighted_capacity": &schema.Schema{ "weighted_capacity": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"subnet_id": &schema.Schema{ "subnet_id": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
ForceNew: true, ForceNew: true,
}, },
"availability_zone": &schema.Schema{ "availability_zone": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true, Computed: true,
@ -240,48 +246,48 @@ func resourceAwsSpotFleetRequest() *schema.Resource {
Set: hashLaunchSpecification, Set: hashLaunchSpecification,
}, },
// Everything on a spot fleet is ForceNew except target_capacity // Everything on a spot fleet is ForceNew except target_capacity
"target_capacity": &schema.Schema{ "target_capacity": {
Type: schema.TypeInt, Type: schema.TypeInt,
Required: true, Required: true,
ForceNew: false, ForceNew: false,
}, },
"allocation_strategy": &schema.Schema{ "allocation_strategy": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Default: "lowestPrice", Default: "lowestPrice",
ForceNew: true, ForceNew: true,
}, },
"excess_capacity_termination_policy": &schema.Schema{ "excess_capacity_termination_policy": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Default: "Default", Default: "Default",
ForceNew: false, ForceNew: false,
}, },
"spot_price": &schema.Schema{ "spot_price": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, ForceNew: true,
}, },
"terminate_instances_with_expiration": &schema.Schema{ "terminate_instances_with_expiration": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"valid_from": &schema.Schema{ "valid_from": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"valid_until": &schema.Schema{ "valid_until": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ForceNew: true, ForceNew: true,
}, },
"spot_request_state": &schema.Schema{ "spot_request_state": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
"client_token": &schema.Schema{ "client_token": {
Type: schema.TypeString, Type: schema.TypeString,
Computed: true, Computed: true,
}, },
@ -525,6 +531,7 @@ func resourceAwsSpotFleetRequestCreate(d *schema.ResourceData, meta interface{})
TargetCapacity: aws.Int64(int64(d.Get("target_capacity").(int))), TargetCapacity: aws.Int64(int64(d.Get("target_capacity").(int))),
ClientToken: aws.String(resource.UniqueId()), ClientToken: aws.String(resource.UniqueId()),
TerminateInstancesWithExpiration: aws.Bool(d.Get("terminate_instances_with_expiration").(bool)), TerminateInstancesWithExpiration: aws.Bool(d.Get("terminate_instances_with_expiration").(bool)),
ReplaceUnhealthyInstances: aws.Bool(d.Get("replace_unhealthy_instances").(bool)),
} }
if v, ok := d.GetOk("excess_capacity_termination_policy"); ok { if v, ok := d.GetOk("excess_capacity_termination_policy"); ok {
@ -716,6 +723,7 @@ func resourceAwsSpotFleetRequestRead(d *schema.ResourceData, meta interface{}) e
aws.TimeValue(config.ValidUntil).Format(awsAutoscalingScheduleTimeLayout)) aws.TimeValue(config.ValidUntil).Format(awsAutoscalingScheduleTimeLayout))
} }
d.Set("replace_unhealthy_instances", config.ReplaceUnhealthyInstances)
d.Set("launch_specification", launchSpecsToSet(config.LaunchSpecifications, conn)) d.Set("launch_specification", launchSpecsToSet(config.LaunchSpecifications, conn))
return nil return nil

View File

@ -82,6 +82,7 @@ Most of these arguments directly correspond to the
Spot instances on your behalf when you cancel its Spot fleet request using Spot instances on your behalf when you cancel its Spot fleet request using
CancelSpotFleetRequests or when the Spot fleet request expires, if you set CancelSpotFleetRequests or when the Spot fleet request expires, if you set
terminateInstancesWithExpiration. terminateInstancesWithExpiration.
* `replace_unhealthy_instances` - (Optional) Indicates whether Spot fleet should replace unhealthy instances. Default `false`.
* `launch_specification` - Used to define the launch configuration of the * `launch_specification` - Used to define the launch configuration of the
spot-fleet request. Can be specified multiple times to define different bids spot-fleet request. Can be specified multiple times to define different bids
across different markets and instance types. across different markets and instance types.