From a345cc45d74992a6450f53d17d52ab263e6caebd Mon Sep 17 00:00:00 2001 From: Paddy Date: Tue, 2 May 2017 15:52:54 -0700 Subject: [PATCH] provider/aws: support tenancy for spot fleets Add the `placement_tenancy` attribute to the `aws_spot_fleet_request` resource so users can request instances use dedicated hardware. Fixes #14152. --- .../aws/resource_aws_spot_fleet_request.go | 16 ++- .../resource_aws_spot_fleet_request_test.go | 120 ++++++++++++++++++ 2 files changed, 133 insertions(+), 3 deletions(-) diff --git a/builtin/providers/aws/resource_aws_spot_fleet_request.go b/builtin/providers/aws/resource_aws_spot_fleet_request.go index db2424e20..1116c32ab 100644 --- a/builtin/providers/aws/resource_aws_spot_fleet_request.go +++ b/builtin/providers/aws/resource_aws_spot_fleet_request.go @@ -206,6 +206,11 @@ func resourceAwsSpotFleetRequest() *schema.Resource { Computed: true, ForceNew: true, }, + "placement_tenancy": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, "spot_price": { Type: schema.TypeString, Optional: true, @@ -304,10 +309,15 @@ func buildSpotFleetLaunchSpecification(d map[string]interface{}, meta interface{ SpotPrice: aws.String(d["spot_price"].(string)), } + placement := new(ec2.SpotPlacement) if v, ok := d["availability_zone"]; ok { - opts.Placement = &ec2.SpotPlacement{ - AvailabilityZone: aws.String(v.(string)), - } + placement.AvailabilityZone = aws.String(v.(string)) + opts.Placement = placement + } + + if v, ok := d["placement_tenancy"]; ok { + placement.Tenancy = aws.String(v.(string)) + opts.Placement = placement } if v, ok := d["ebs_optimized"]; ok { diff --git a/builtin/providers/aws/resource_aws_spot_fleet_request_test.go b/builtin/providers/aws/resource_aws_spot_fleet_request_test.go index 0f90a57f6..2a9ac1bd7 100644 --- a/builtin/providers/aws/resource_aws_spot_fleet_request_test.go +++ b/builtin/providers/aws/resource_aws_spot_fleet_request_test.go @@ -325,6 +325,30 @@ func TestAccAWSSpotFleetRequest_withEBSDisk(t *testing.T) { }) } +func TestAccAWSSpotFleetRequest_placementTenancy(t *testing.T) { + var sfr ec2.SpotFleetRequestConfig + rName := acctest.RandString(10) + rInt := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSpotFleetRequestDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSpotFleetRequestTenancyConfig(rName, rInt), + Check: resource.ComposeAggregateTestCheckFunc( + testAccCheckAWSSpotFleetRequestExists( + "aws_spot_fleet_request.foo", &sfr), + resource.TestCheckResourceAttr( + "aws_spot_fleet_request.foo", "spot_request_state", "active"), + testAccCheckAWSSpotFleetRequest_PlacementAttributes(&sfr), + ), + }, + }, + }) +} + func TestAccAWSSpotFleetRequest_CannotUseEmptyKeyName(t *testing.T) { _, errs := validateSpotFleetRequestKeyName("", "key_name") if len(errs) == 0 { @@ -400,6 +424,27 @@ func testAccCheckAWSSpotFleetRequest_EBSAttributes( } } +func testAccCheckAWSSpotFleetRequest_PlacementAttributes( + sfr *ec2.SpotFleetRequestConfig) resource.TestCheckFunc { + return func(s *terraform.State) error { + if len(sfr.SpotFleetRequestConfig.LaunchSpecifications) == 0 { + return errors.New("Missing launch specification") + } + + spec := *sfr.SpotFleetRequestConfig.LaunchSpecifications[0] + + placement := spec.Placement + if placement == nil { + return fmt.Errorf("Expected placement to be set, got nil") + } + if *placement.Tenancy != "dedicated" { + return fmt.Errorf("Expected placement tenancy to be %q, got %q", "dedicated", placement.Tenancy) + } + + return nil + } +} + func testAccCheckAWSSpotFleetRequestDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn @@ -1251,3 +1296,78 @@ resource "aws_spot_fleet_request" "foo" { } `, rInt, rInt, rName) } + +func testAccAWSSpotFleetRequestTenancyConfig(rName string, rInt int) string { + return fmt.Sprintf(` +resource "aws_key_pair" "debugging" { + key_name = "tmp-key-%s" + public_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD3F6tyPEFEzV0LX3X8BsXdMsQz1x2cEikKDEY0aIj41qgxMCP/iteneqXSIFZBp5vizPvaoIR3Um9xK7PGoW8giupGn+EPuxIA4cDM4vzOqOkiMPhz5XK0whEjkVzTo4+S0puvDZuwIsdiW9mxhJc7tgBNL0cYlWSYVkz4G/fslNfRPW5mYAM49f4fhtxPb5ok4Q2Lg9dPKVHO/Bgeu5woMc7RY0p1ej6D4CKFE6lymSDJpW0YHX/wqE9+cfEauh7xZcG0q9t2ta6F6fmX0agvpFyZo8aFbXeUBr7osSCJNgvavWbM/06niWrOvYX2xwWdhXmXSrbX8ZbabVohBK41 phodgson@thoughtworks.com" +} + +resource "aws_iam_policy" "test-policy" { + name = "test-policy-%d" + path = "/" + description = "Spot Fleet Request ACCTest Policy" + policy = <