Skip to content

Commit

Permalink
Merge pull request #8612 from savar/fix_launch_template_network_inter…
Browse files Browse the repository at this point in the history
…face

delete_on_termination on ENI has to be optional
  • Loading branch information
anGie44 committed Jul 15, 2020
2 parents def3ab0 + f2d80fb commit 1627f6a
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 12 deletions.
37 changes: 25 additions & 12 deletions aws/resource_aws_launch_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,14 @@ func resourceAwsLaunchTemplate() *schema.Resource {
ValidateFunc: validateTypeStringNullableBoolean,
},
"delete_on_termination": {
Type: schema.TypeBool,
Optional: true,
// Use TypeString to allow an "unspecified" value,
// since TypeBool only has true/false with false default.
// The conversion from bare true/false values in
// configurations to TypeString value is currently safe.
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: suppressEquivalentTypeStringBoolean,
ValidateFunc: validateTypeStringNullableBoolean,
},
"description": {
Type: schema.TypeString,
Expand Down Expand Up @@ -1119,19 +1125,22 @@ func getNetworkInterfaces(n []*ec2.LaunchTemplateInstanceNetworkInterfaceSpecifi
var ipv4Addresses []string

networkInterface := map[string]interface{}{
"delete_on_termination": aws.BoolValue(v.DeleteOnTermination),
"description": aws.StringValue(v.Description),
"device_index": aws.Int64Value(v.DeviceIndex),
"ipv4_address_count": aws.Int64Value(v.SecondaryPrivateIpAddressCount),
"ipv6_address_count": aws.Int64Value(v.Ipv6AddressCount),
"network_interface_id": aws.StringValue(v.NetworkInterfaceId),
"private_ip_address": aws.StringValue(v.PrivateIpAddress),
"subnet_id": aws.StringValue(v.SubnetId),
"description": aws.StringValue(v.Description),
"device_index": aws.Int64Value(v.DeviceIndex),
"ipv4_address_count": aws.Int64Value(v.SecondaryPrivateIpAddressCount),
"ipv6_address_count": aws.Int64Value(v.Ipv6AddressCount),
"network_interface_id": aws.StringValue(v.NetworkInterfaceId),
"private_ip_address": aws.StringValue(v.PrivateIpAddress),
"subnet_id": aws.StringValue(v.SubnetId),
}
if v.AssociatePublicIpAddress != nil {
networkInterface["associate_public_ip_address"] = strconv.FormatBool(aws.BoolValue(v.AssociatePublicIpAddress))
}

if v.DeleteOnTermination != nil {
networkInterface["delete_on_termination"] = strconv.FormatBool(aws.BoolValue(v.DeleteOnTermination))
}

if len(v.Ipv6Addresses) > 0 {
raw, ok := networkInterface["ipv6_addresses"]
if !ok {
Expand Down Expand Up @@ -1507,8 +1516,12 @@ func readNetworkInterfacesFromConfig(ni map[string]interface{}) (*ec2.LaunchTemp
var privateIpAddress string
networkInterface := &ec2.LaunchTemplateInstanceNetworkInterfaceSpecificationRequest{}

if v, ok := ni["delete_on_termination"]; ok {
networkInterface.DeleteOnTermination = aws.Bool(v.(bool))
if v, ok := ni["delete_on_termination"]; ok && v.(string) != "" {
vBool, err := strconv.ParseBool(v.(string))
if err != nil {
return nil, fmt.Errorf("error converting delete_on_termination %q from string to boolean: %w", v.(string), err)
}
networkInterface.DeleteOnTermination = aws.Bool(vBool)
}

if v, ok := ni["description"].(string); ok && v != "" {
Expand Down
71 changes: 71 additions & 0 deletions aws/resource_aws_launch_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,61 @@ func TestAccAWSLaunchTemplate_ElasticInferenceAccelerator(t *testing.T) {
})
}

func TestAccAWSLaunchTemplate_NetworkInterfaces_DeleteOnTermination(t *testing.T) {
var template ec2.LaunchTemplate
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_launch_template.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSLaunchTemplateDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSLaunchTemplateConfig_NetworkInterfaces_DeleteOnTermination(rName, "true"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSLaunchTemplateExists(resourceName, &template),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.delete_on_termination", "true"),
),
},
{
Config: testAccAWSLaunchTemplateConfig_NetworkInterfaces_DeleteOnTermination(rName, "false"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSLaunchTemplateExists(resourceName, &template),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.delete_on_termination", "false"),
),
},
{
Config: testAccAWSLaunchTemplateConfig_NetworkInterfaces_DeleteOnTermination(rName, "\"\""),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSLaunchTemplateExists(resourceName, &template),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.delete_on_termination", ""),
),
},
{
Config: testAccAWSLaunchTemplateConfig_NetworkInterfaces_DeleteOnTermination(rName, "null"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSLaunchTemplateExists(resourceName, &template),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.delete_on_termination", ""),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSLaunchTemplate_data(t *testing.T) {
var template ec2.LaunchTemplate
resourceName := "aws_launch_template.test"
Expand Down Expand Up @@ -313,6 +368,7 @@ func TestAccAWSLaunchTemplate_data(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "monitoring.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.security_groups.#", "1"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.delete_on_termination", ""),
resource.TestCheckResourceAttr(resourceName, "placement.#", "1"),
resource.TestCheckResourceAttrSet(resourceName, "ram_disk_id"),
resource.TestCheckResourceAttr(resourceName, "vpc_security_group_ids.#", "1"),
Expand Down Expand Up @@ -625,6 +681,7 @@ func TestAccAWSLaunchTemplate_networkInterface(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"),
resource.TestCheckResourceAttrSet(resourceName, "network_interfaces.0.network_interface_id"),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.associate_public_ip_address", ""),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.delete_on_termination", ""),
resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.ipv4_address_count", "2"),
),
},
Expand Down Expand Up @@ -1253,6 +1310,20 @@ resource "aws_autoscaling_group" "test" {
`, rName, deleteOnTermination, rName)
}

func testAccAWSLaunchTemplateConfig_NetworkInterfaces_DeleteOnTermination(rName string, deleteOnTermination string) string {
return fmt.Sprintf(`
resource "aws_launch_template" "test" {
name = %q
network_interfaces {
network_interface_id = "eni-123456ab"
security_groups = ["sg-1a23bc45"]
delete_on_termination = %s
}
}
`, rName, deleteOnTermination)
}

func testAccAWSLaunchTemplateConfig_EbsOptimized(rName, ebsOptimized string) string {
return fmt.Sprintf(`
resource "aws_launch_template" "test" {
Expand Down
35 changes: 35 additions & 0 deletions website/docs/guides/version-3-upgrade.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Upgrade topics:
- [Resource: aws_dx_gateway](#resource-aws_dx_gateway)
- [Resource: aws_elastic_transcoder_preset](#resource-aws_elastic_transcoder_preset)
- [Resource: aws_emr_cluster](#resource-aws_emr_cluster)
- [Resource: aws_launch_template](#resource-aws_launch_template)
- [Resource: aws_lb_listener_rule](#resource-aws_lb_listener_rule)
- [Resource: aws_msk_cluster](#resource-aws_msk_cluster)
- [Resource: aws_s3_bucket](#resource-aws_s3_bucket)
Expand Down Expand Up @@ -376,6 +377,40 @@ resource "aws_emr_cluster" "example" {
}
```

## Resource: aws_launch_template

### network_interfaces.delete_on_termination Argument type change

The `network_interfaces.delete_on_termination` argument is now of type `string`, allowing an unspecified value for the argument since the previous `bool` type only allowed for `true/false` and defaulted to `false` when no value was set. Now to enforce `delete_on_termination` to `false`, the string `"false"` or bare `false` value must be used.

For example, given this previous configuration:

```hcl
resource "aws_launch_template" "example" {
# ... other configuration ...
network_interfaces {
# ... other configuration ...
delete_on_termination = null
}
}
```

An updated configuration:

```hcl
resource "aws_launch_template" "example" {
# ... other configuration ...
network_interfaces {
# ... other configuration ...
delete_on_termination = false
}
}
```

## Resource: aws_lb_listener_rule

### condition.field and condition.values Arguments Removal
Expand Down

0 comments on commit 1627f6a

Please sign in to comment.