diff --git a/aws/resource_aws_launch_configuration.go b/aws/resource_aws_launch_configuration.go index f95b7f0f0ab..d6c05610dee 100644 --- a/aws/resource_aws_launch_configuration.go +++ b/aws/resource_aws_launch_configuration.go @@ -158,6 +158,12 @@ func resourceAwsLaunchConfiguration() *schema.Resource { ForceNew: true, }, + "no_device": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + }, + "iops": { Type: schema.TypeInt, Optional: true, @@ -338,8 +344,13 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface vL := v.(*schema.Set).List() for _, v := range vL { bd := v.(map[string]interface{}) - ebs := &autoscaling.Ebs{ - DeleteOnTermination: aws.Bool(bd["delete_on_termination"].(bool)), + ebs := &autoscaling.Ebs{} + + var noDevice *bool + if v, ok := bd["no_device"].(bool); ok && v { + noDevice = aws.Bool(v) + } else { + ebs.DeleteOnTermination = aws.Bool(bd["delete_on_termination"].(bool)) } if v, ok := bd["snapshot_id"].(string); ok && v != "" { @@ -369,6 +380,7 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface blockDevices = append(blockDevices, &autoscaling.BlockDeviceMapping{ DeviceName: aws.String(bd["device_name"].(string)), Ebs: ebs, + NoDevice: noDevice, }) } } @@ -580,11 +592,33 @@ func readBlockDevicesFromLaunchConfiguration(d *schema.ResourceData, lc *autosca var blank string rootDeviceName = &blank } + + // Collect existing configured devices, so we can check + // existing value of delete_on_termination below + existingEbsBlockDevices := make(map[string]map[string]interface{}, 0) + if v, ok := d.GetOk("ebs_block_device"); ok { + ebsBlocks := v.(*schema.Set) + for _, ebd := range ebsBlocks.List() { + m := ebd.(map[string]interface{}) + deviceName := m["device_name"].(string) + existingEbsBlockDevices[deviceName] = m + } + } + for _, bdm := range lc.BlockDeviceMappings { bd := make(map[string]interface{}) - if bdm.Ebs != nil && bdm.Ebs.DeleteOnTermination != nil { + + if bdm.NoDevice != nil { + // Keep existing value in place to avoid spurious diff + deleteOnTermination := true + if device, ok := existingEbsBlockDevices[*bdm.DeviceName]; ok { + deleteOnTermination = device["delete_on_termination"].(bool) + } + bd["delete_on_termination"] = deleteOnTermination + } else if bdm.Ebs != nil && bdm.Ebs.DeleteOnTermination != nil { bd["delete_on_termination"] = *bdm.Ebs.DeleteOnTermination } + if bdm.Ebs != nil && bdm.Ebs.VolumeSize != nil { bd["volume_size"] = *bdm.Ebs.VolumeSize } @@ -611,6 +645,9 @@ func readBlockDevicesFromLaunchConfiguration(d *schema.ResourceData, lc *autosca if bdm.Ebs != nil && bdm.Ebs.SnapshotId != nil { bd["snapshot_id"] = *bdm.Ebs.SnapshotId } + if bdm.NoDevice != nil { + bd["no_device"] = *bdm.NoDevice + } blockDevices["ebs"] = append(blockDevices["ebs"].([]map[string]interface{}), bd) } } diff --git a/aws/resource_aws_launch_configuration_test.go b/aws/resource_aws_launch_configuration_test.go index c869d427a78..e250d7884ce 100644 --- a/aws/resource_aws_launch_configuration_test.go +++ b/aws/resource_aws_launch_configuration_test.go @@ -281,7 +281,7 @@ func TestAccAWSLaunchConfiguration_updateEbsBlockDevices(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf), resource.TestCheckResourceAttr( - "aws_launch_configuration.baz", "ebs_block_device.2764618555.volume_size", "9"), + "aws_launch_configuration.baz", "ebs_block_device.1393547169.volume_size", "9"), ), }, { @@ -289,7 +289,29 @@ func TestAccAWSLaunchConfiguration_updateEbsBlockDevices(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.baz", &conf), resource.TestCheckResourceAttr( - "aws_launch_configuration.baz", "ebs_block_device.3859927736.volume_size", "10"), + "aws_launch_configuration.baz", "ebs_block_device.4131155854.volume_size", "10"), + ), + }, + }, + }) +} + +func TestAccAWSLaunchConfiguration_ebs_noDevice(t *testing.T) { + var conf autoscaling.LaunchConfiguration + rInt := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLaunchConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLaunchConfigurationConfigEbsNoDevice(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLaunchConfigurationExists("aws_launch_configuration.bar", &conf), + resource.TestCheckResourceAttr("aws_launch_configuration.bar", "ebs_block_device.#", "1"), + resource.TestCheckResourceAttr("aws_launch_configuration.bar", "ebs_block_device.3099842682.device_name", "/dev/sda2"), + resource.TestCheckResourceAttr("aws_launch_configuration.bar", "ebs_block_device.3099842682.no_device", "true"), ), }, }, @@ -608,3 +630,26 @@ resource "aws_launch_configuration" "bar" { } `, rInt) } + +func testAccAWSLaunchConfigurationConfigEbsNoDevice(rInt int) string { + return fmt.Sprintf(` +data "aws_ami" "ubuntu" { + most_recent = true + filter { + name = "name" + values = ["ubuntu/images/ebs/ubuntu-precise-12.04-i386-server-*"] + } + owners = ["099720109477"] # Canonical +} + +resource "aws_launch_configuration" "bar" { + name_prefix = "tf-acc-test-%d" + image_id = "${data.aws_ami.ubuntu.id}" + instance_type = "m1.small" + ebs_block_device { + device_name = "/dev/sda2" + no_device = true + } +} +`, rInt) +}