From 12432cbcca09468dcb4ec0ae8918964c685b103a Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Fri, 2 Aug 2019 00:50:57 -0400 Subject: [PATCH] resource/aws_spot_fleet_request: Add ebs_block_device and root_block_device kms_key_id argument (support encryption on launch) Reference: https://github.com/terraform-providers/terraform-provider-aws/issues/8624 NOTE: No documentation updates because the `launch_specification` argument documentation points to the `aws_instance` resource documentation. Output from acceptance testing: ``` --- PASS: TestAccAWSSpotFleetRequest_associatePublicIpAddress (270.69s) --- PASS: TestAccAWSSpotFleetRequest_basic (405.39s) --- PASS: TestAccAWSSpotFleetRequest_changePriceForcesNewRequest (529.67s) --- PASS: TestAccAWSSpotFleetRequest_diversifiedAllocation (327.08s) --- PASS: TestAccAWSSpotFleetRequest_fleetType (261.37s) --- PASS: TestAccAWSSpotFleetRequest_iamInstanceProfileArn (324.47s) --- PASS: TestAccAWSSpotFleetRequest_instanceInterruptionBehavior (195.94s) --- PASS: TestAccAWSSpotFleetRequest_LaunchSpecification_EbsBlockDevice_KmsKeyId (142.16s) --- PASS: TestAccAWSSpotFleetRequest_LaunchSpecification_RootBlockDevice_KmsKeyId (141.99s) --- PASS: TestAccAWSSpotFleetRequest_lowestPriceAzInGivenList (334.76s) --- PASS: TestAccAWSSpotFleetRequest_lowestPriceAzOrSubnetInRegion (260.11s) --- PASS: TestAccAWSSpotFleetRequest_lowestPriceSubnetInGivenList (262.82s) --- PASS: TestAccAWSSpotFleetRequest_multipleInstancePools (327.36s) --- PASS: TestAccAWSSpotFleetRequest_multipleInstanceTypesInSameAz (263.10s) --- PASS: TestAccAWSSpotFleetRequest_multipleInstanceTypesInSameSubnet (260.47s) --- PASS: TestAccAWSSpotFleetRequest_overriddingSpotPrice (263.28s) --- PASS: TestAccAWSSpotFleetRequest_placementTenancy (68.47s) --- PASS: TestAccAWSSpotFleetRequest_updateExcessCapacityTerminationPolicy (517.31s) --- PASS: TestAccAWSSpotFleetRequest_updateTargetCapacity (797.62s) --- PASS: TestAccAWSSpotFleetRequest_withEBSDisk (404.38s) --- PASS: TestAccAWSSpotFleetRequest_WithELBs (313.70s) --- PASS: TestAccAWSSpotFleetRequest_withoutSpotPrice (263.82s) --- PASS: TestAccAWSSpotFleetRequest_withTags (261.37s) --- PASS: TestAccAWSSpotFleetRequest_WithTargetGroups (429.61s) --- PASS: TestAccAWSSpotFleetRequest_withWeightedCapacity (334.88s) ``` --- aws/resource_aws_spot_fleet_request.go | 42 ++++++ aws/resource_aws_spot_fleet_request_test.go | 141 ++++++++++++++++++++ 2 files changed, 183 insertions(+) diff --git a/aws/resource_aws_spot_fleet_request.go b/aws/resource_aws_spot_fleet_request.go index 1922b10cb05..22f9380ecc1 100644 --- a/aws/resource_aws_spot_fleet_request.go +++ b/aws/resource_aws_spot_fleet_request.go @@ -99,6 +99,12 @@ func resourceAwsSpotFleetRequest() *schema.Resource { Computed: true, ForceNew: true, }, + "kms_key_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, "snapshot_id": { Type: schema.TypeString, Optional: true, @@ -159,12 +165,24 @@ func resourceAwsSpotFleetRequest() *schema.Resource { Default: true, ForceNew: true, }, + "encrypted": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + ForceNew: true, + }, "iops": { Type: schema.TypeInt, Optional: true, Computed: true, ForceNew: true, }, + "kms_key_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, "volume_size": { Type: schema.TypeInt, Optional: true, @@ -512,6 +530,10 @@ func readSpotFleetBlockDeviceMappingsFromConfig( ebs.Encrypted = aws.Bool(v) } + if v, ok := bd["kms_key_id"].(string); ok && v != "" { + ebs.KmsKeyId = aws.String(v) + } + if v, ok := bd["volume_size"].(int); ok && v != 0 { ebs.VolumeSize = aws.Int64(int64(v)) } @@ -553,6 +575,14 @@ func readSpotFleetBlockDeviceMappingsFromConfig( DeleteOnTermination: aws.Bool(bd["delete_on_termination"].(bool)), } + if v, ok := bd["encrypted"].(bool); ok && v { + ebs.Encrypted = aws.Bool(v) + } + + if v, ok := bd["kms_key_id"].(string); ok && v != "" { + ebs.KmsKeyId = aws.String(v) + } + if v, ok := bd["volume_size"].(int); ok && v != 0 { ebs.VolumeSize = aws.Int64(int64(v)) } @@ -1065,6 +1095,10 @@ func ebsBlockDevicesToSet(bdm []*ec2.BlockDeviceMapping, rootDevName *string) *s m["encrypted"] = aws.BoolValue(ebs.Encrypted) } + if ebs.KmsKeyId != nil { + m["kms_key_id"] = aws.StringValue(ebs.KmsKeyId) + } + if ebs.VolumeSize != nil { m["volume_size"] = aws.Int64Value(ebs.VolumeSize) } @@ -1117,6 +1151,14 @@ func rootBlockDeviceToSet( m["delete_on_termination"] = aws.BoolValue(val.Ebs.DeleteOnTermination) } + if val.Ebs.Encrypted != nil { + m["encrypted"] = aws.BoolValue(val.Ebs.Encrypted) + } + + if val.Ebs.KmsKeyId != nil { + m["kms_key_id"] = aws.StringValue(val.Ebs.KmsKeyId) + } + if val.Ebs.VolumeSize != nil { m["volume_size"] = aws.Int64Value(val.Ebs.VolumeSize) } diff --git a/aws/resource_aws_spot_fleet_request_test.go b/aws/resource_aws_spot_fleet_request_test.go index 974b0af7394..fa901462432 100644 --- a/aws/resource_aws_spot_fleet_request_test.go +++ b/aws/resource_aws_spot_fleet_request_test.go @@ -555,6 +555,48 @@ func TestAccAWSSpotFleetRequest_withEBSDisk(t *testing.T) { }) } +func TestAccAWSSpotFleetRequest_LaunchSpecification_EbsBlockDevice_KmsKeyId(t *testing.T) { + var config ec2.SpotFleetRequestConfig + rName := acctest.RandString(10) + rInt := acctest.RandInt() + resourceName := "aws_spot_fleet_request.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSEc2SpotFleetRequest(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSpotFleetRequestDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSpotFleetRequestLaunchSpecificationEbsBlockDeviceKmsKeyId(rName, rInt), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSSpotFleetRequestExists(resourceName, &config), + ), + }, + }, + }) +} + +func TestAccAWSSpotFleetRequest_LaunchSpecification_RootBlockDevice_KmsKeyId(t *testing.T) { + var config ec2.SpotFleetRequestConfig + rName := acctest.RandString(10) + rInt := acctest.RandInt() + resourceName := "aws_spot_fleet_request.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSEc2SpotFleetRequest(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSpotFleetRequestDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSpotFleetRequestLaunchSpecificationRootBlockDeviceKmsKeyId(rName, rInt), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSSpotFleetRequestExists(resourceName, &config), + ), + }, + }, + }) +} + func TestAccAWSSpotFleetRequest_withTags(t *testing.T) { var config ec2.SpotFleetRequestConfig rName := acctest.RandString(10) @@ -1483,6 +1525,105 @@ resource "aws_spot_fleet_request" "foo" { `) } +func testAccAWSSpotFleetRequestLaunchSpecificationEbsBlockDeviceKmsKeyId(rName string, rInt int) string { + return testAccAWSSpotFleetRequestConfigBase(rName, rInt) + fmt.Sprint(` +data "aws_ami" "amzn-ami-minimal-hvm-ebs" { + most_recent = true + owners = ["amazon"] + + filter { + name = "name" + values = ["amzn-ami-minimal-hvm-*"] + } + + filter { + name = "root-device-type" + values = ["ebs"] + } +} + +resource "aws_kms_key" "test" { + deletion_window_in_days = 7 +} + +resource "aws_spot_fleet_request" "test" { + iam_fleet_role = "${aws_iam_role.test-role.arn}" + spot_price = "0.005" + target_capacity = 1 + terminate_instances_with_expiration = true + valid_until = "2029-11-04T20:44:20Z" + wait_for_fulfillment = true + + launch_specification { + ami = "${data.aws_ami.amzn-ami-minimal-hvm-ebs.id}" + instance_type = "t2.micro" + + ebs_block_device { + device_name = "/dev/xvda" + volume_type = "gp2" + volume_size = 8 + } + + ebs_block_device { + device_name = "/dev/xvdcz" + encrypted = true + kms_key_id = "${aws_kms_key.test.arn}" + volume_type = "gp2" + volume_size = 10 + } + } + + depends_on = ["aws_iam_policy_attachment.test-attach"] +} +`) +} + +func testAccAWSSpotFleetRequestLaunchSpecificationRootBlockDeviceKmsKeyId(rName string, rInt int) string { + return testAccAWSSpotFleetRequestConfigBase(rName, rInt) + fmt.Sprint(` +data "aws_ami" "amzn-ami-minimal-hvm-ebs" { + most_recent = true + owners = ["amazon"] + + filter { + name = "name" + values = ["amzn-ami-minimal-hvm-*"] + } + + filter { + name = "root-device-type" + values = ["ebs"] + } +} + +resource "aws_kms_key" "test" { + deletion_window_in_days = 7 +} + +resource "aws_spot_fleet_request" "test" { + iam_fleet_role = "${aws_iam_role.test-role.arn}" + spot_price = "0.005" + target_capacity = 1 + terminate_instances_with_expiration = true + valid_until = "2029-11-04T20:44:20Z" + wait_for_fulfillment = true + + launch_specification { + ami = "${data.aws_ami.amzn-ami-minimal-hvm-ebs.id}" + instance_type = "t2.micro" + + root_block_device { + encrypted = true + kms_key_id = "${aws_kms_key.test.arn}" + volume_type = "gp2" + volume_size = 10 + } + } + + depends_on = ["aws_iam_policy_attachment.test-attach"] +} +`) +} + func testAccAWSSpotFleetRequestTagsConfig(rName string, rInt int) string { return testAccAWSSpotFleetRequestConfigBase(rName, rInt) + fmt.Sprint(` resource "aws_spot_fleet_request" "foo" {