From 391a7f85b0d402e5d165909b3ccc7cce838df26a Mon Sep 17 00:00:00 2001 From: Paul Forman Date: Wed, 8 Jun 2016 14:56:27 -0600 Subject: [PATCH] provider/aws: Fix issue with Root Block Devices and encrypted flag in Launch Configurations [GH-6512] Fixed the problem where the root_block_device could cause an apply error by reading back an "encrypted" parameter that was meant for an ebs_block_device. "encrypted" is not part of the root_block_device schema, since it can't be set explicitly. Added a check in Create to fail when the root device is incorrectly specified as an ebs_block_device, as this causes continual refreshing due to mismatched state between root_block_device and ebs_block_device. "encrypted" and "snapshot_id" should be guarded with ConflictsWith, but that doesn't appear to work on nested resources despite #1926. --- .../aws/resource_aws_launch_configuration.go | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/builtin/providers/aws/resource_aws_launch_configuration.go b/builtin/providers/aws/resource_aws_launch_configuration.go index 536acfc76ca0..7726dda46861 100644 --- a/builtin/providers/aws/resource_aws_launch_configuration.go +++ b/builtin/providers/aws/resource_aws_launch_configuration.go @@ -331,6 +331,17 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface var blockDevices []*autoscaling.BlockDeviceMapping + // We'll use this to detect if we're declaring it incorrectly as an ebs_block_device. + rootDeviceName, err := fetchRootDeviceName(d.Get("image_id").(string), ec2conn) + if err != nil { + return err + } + if rootDeviceName == nil { + // We do this so the value is empty so we don't have to do nil checks later + var blank string + rootDeviceName = &blank + } + if v, ok := d.GetOk("ebs_block_device"); ok { vL := v.(*schema.Set).List() for _, v := range vL { @@ -359,6 +370,10 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface ebs.Iops = aws.Int64(int64(v)) } + if *aws.String(bd["device_name"].(string)) == *rootDeviceName { + return fmt.Errorf("Root device (%s) declared as an 'ebs_block_device'. Use 'root_block_device' keyword.", *rootDeviceName) + } + blockDevices = append(blockDevices, &autoscaling.BlockDeviceMapping{ DeviceName: aws.String(bd["device_name"].(string)), Ebs: ebs, @@ -435,7 +450,7 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface // IAM profiles can take ~10 seconds to propagate in AWS: // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html#launch-instance-with-role-console - err := resource.Retry(30*time.Second, func() *resource.RetryError { + err = resource.Retry(30*time.Second, func() *resource.RetryError { _, err := autoscalingconn.CreateLaunchConfiguration(&createLaunchConfigurationOpts) if err != nil { if awsErr, ok := err.(awserr.Error); ok { @@ -587,12 +602,13 @@ func readBlockDevicesFromLaunchConfiguration(d *schema.ResourceData, lc *autosca if bdm.Ebs != nil && bdm.Ebs.Iops != nil { bd["iops"] = *bdm.Ebs.Iops } - if bdm.Ebs != nil && bdm.Ebs.Encrypted != nil { - bd["encrypted"] = *bdm.Ebs.Encrypted - } + if bdm.DeviceName != nil && *bdm.DeviceName == *rootDeviceName { blockDevices["root"] = bd } else { + if bdm.Ebs != nil && bdm.Ebs.Encrypted != nil { + bd["encrypted"] = *bdm.Ebs.Encrypted + } if bdm.DeviceName != nil { bd["device_name"] = *bdm.DeviceName }