From 57d37d813b557dc898c0837a202d5a5b8cd5b8b3 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 11 Dec 2020 10:03:43 -0500 Subject: [PATCH] aws_launch_template: AWS Wavelength support (#16707) * r/aws_launch_template: Add 'associate_carrier_ip_address' to 'network_interfaces' block. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSLaunchTemplate_associateCarrierIPAddress' ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 20 -run=TestAccAWSLaunchTemplate_associateCarrierIPAddress -timeout 120m === RUN TestAccAWSLaunchTemplate_associateCarrierIPAddress === PAUSE TestAccAWSLaunchTemplate_associateCarrierIPAddress === CONT TestAccAWSLaunchTemplate_associateCarrierIPAddress --- PASS: TestAccAWSLaunchTemplate_associateCarrierIPAddress (96.08s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 96.150s * d/aws_launch_template: Add 'associate_carrier_ip_address' to 'network_interfaces' block. Acceptance test output: $ make testacc TEST=./aws/ TESTARGS='-run=TestAccAWSLaunchTemplateDataSource_associateCarrierIPAddress' ACCTEST_PARALLELISM=2 ==> Checking that code complies with gofmt requirements... TF_ACC=1 go test ./aws -v -count 1 -parallel 2 -run=TestAccAWSLaunchTemplateDataSource_associateCarrierIPAddress -timeout 120m === RUN TestAccAWSLaunchTemplateDataSource_associateCarrierIPAddress === PAUSE TestAccAWSLaunchTemplateDataSource_associateCarrierIPAddress === CONT TestAccAWSLaunchTemplateDataSource_associateCarrierIPAddress --- PASS: TestAccAWSLaunchTemplateDataSource_associateCarrierIPAddress (38.24s) PASS ok github.com/terraform-providers/terraform-provider-aws/aws 38.329s --- aws/data_source_aws_launch_template.go | 4 ++ aws/data_source_aws_launch_template_test.go | 51 +++++++++++++ aws/resource_aws_launch_template.go | 19 +++++ aws/resource_aws_launch_template_test.go | 76 ++++++++++++++++++++ website/docs/r/launch_template.html.markdown | 1 + 5 files changed, 151 insertions(+) diff --git a/aws/data_source_aws_launch_template.go b/aws/data_source_aws_launch_template.go index 3c4f27dad4e4..8de8edac8c0d 100644 --- a/aws/data_source_aws_launch_template.go +++ b/aws/data_source_aws_launch_template.go @@ -239,6 +239,10 @@ func dataSourceAwsLaunchTemplate() *schema.Resource { Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "associate_carrier_ip_address": { + Type: schema.TypeString, + Computed: true, + }, "associate_public_ip_address": { Type: schema.TypeString, Computed: true, diff --git a/aws/data_source_aws_launch_template_test.go b/aws/data_source_aws_launch_template_test.go index 596695bbc6ea..8f03d3983c25 100644 --- a/aws/data_source_aws_launch_template_test.go +++ b/aws/data_source_aws_launch_template_test.go @@ -160,6 +160,41 @@ func TestAccAWSLaunchTemplateDataSource_associatePublicIPAddress(t *testing.T) { }) } +func TestAccAWSLaunchTemplateDataSource_associateCarrierIPAddress(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + dataSourceName := "data.aws_launch_template.test" + resourceName := "aws_launch_template.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSLaunchTemplateDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSLaunchTemplateDataSourceConfig_associateCarrierIpAddress(rName, "true"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, "network_interfaces.#", resourceName, "network_interfaces.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "network_interfaces.0.associate_carrier_ip_address", resourceName, "network_interfaces.0.associate_carrier_ip_address"), + ), + }, + { + Config: testAccAWSLaunchTemplateDataSourceConfig_associateCarrierIpAddress(rName, "false"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, "network_interfaces.#", resourceName, "network_interfaces.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "network_interfaces.0.associate_carrier_ip_address", resourceName, "network_interfaces.0.associate_carrier_ip_address"), + ), + }, + { + Config: testAccAWSLaunchTemplateDataSourceConfig_associateCarrierIpAddress(rName, "null"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrPair(dataSourceName, "network_interfaces.#", resourceName, "network_interfaces.#"), + resource.TestCheckResourceAttrPair(dataSourceName, "network_interfaces.0.associate_carrier_ip_address", resourceName, "network_interfaces.0.associate_carrier_ip_address"), + ), + }, + }, + }) +} + func TestAccAWSLaunchTemplateDataSource_networkInterfaces_deleteOnTermination(t *testing.T) { rName := acctest.RandomWithPrefix("tf-acc-test") dataSourceName := "data.aws_launch_template.test" @@ -290,6 +325,22 @@ data "aws_launch_template" "test" { `, rName, associatePublicIPAddress) } +func testAccAWSLaunchTemplateDataSourceConfig_associateCarrierIpAddress(rName, associateCarrierIPAddress string) string { + return fmt.Sprintf(` +resource "aws_launch_template" "test" { + name = %[1]q + + network_interfaces { + associate_carrier_ip_address = %[2]s + } +} + +data "aws_launch_template" "test" { + name = aws_launch_template.test.name +} +`, rName, associateCarrierIPAddress) +} + func testAccAWSLaunchTemplateDataSourceConfigNetworkInterfacesDeleteOnTermination(rName, deleteOnTermination string) string { return fmt.Sprintf(` resource "aws_launch_template" "test" { diff --git a/aws/resource_aws_launch_template.go b/aws/resource_aws_launch_template.go index 06afca1cfd23..48b7b2e54af2 100644 --- a/aws/resource_aws_launch_template.go +++ b/aws/resource_aws_launch_template.go @@ -418,6 +418,12 @@ func resourceAwsLaunchTemplate() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "associate_carrier_ip_address": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: suppressEquivalentTypeStringBoolean, + ValidateFunc: validateTypeStringNullableBoolean, + }, "associate_public_ip_address": { Type: schema.TypeString, Optional: true, @@ -1130,6 +1136,11 @@ func getNetworkInterfaces(n []*ec2.LaunchTemplateInstanceNetworkInterfaceSpecifi "private_ip_address": aws.StringValue(v.PrivateIpAddress), "subnet_id": aws.StringValue(v.SubnetId), } + + if v.AssociateCarrierIpAddress != nil { + networkInterface["associate_carrier_ip_address"] = strconv.FormatBool(aws.BoolValue(v.AssociateCarrierIpAddress)) + } + if v.AssociatePublicIpAddress != nil { networkInterface["associate_public_ip_address"] = strconv.FormatBool(aws.BoolValue(v.AssociatePublicIpAddress)) } @@ -1533,6 +1544,14 @@ func readNetworkInterfacesFromConfig(ni map[string]interface{}) (*ec2.LaunchTemp networkInterface.NetworkInterfaceId = aws.String(v) } + if v, ok := ni["associate_carrier_ip_address"]; ok && v.(string) != "" { + vBool, err := strconv.ParseBool(v.(string)) + if err != nil { + return nil, fmt.Errorf("error converting associate_carrier_ip_address %q from string to boolean: %s", v.(string), err) + } + networkInterface.AssociateCarrierIpAddress = aws.Bool(vBool) + } + if v, ok := ni["associate_public_ip_address"]; ok && v.(string) != "" { vBool, err := strconv.ParseBool(v.(string)) if err != nil { diff --git a/aws/resource_aws_launch_template_test.go b/aws/resource_aws_launch_template_test.go index abe1c477cc12..0c9d5172157f 100644 --- a/aws/resource_aws_launch_template_test.go +++ b/aws/resource_aws_launch_template_test.go @@ -772,6 +772,55 @@ func TestAccAWSLaunchTemplate_associatePublicIPAddress(t *testing.T) { }) } +func TestAccAWSLaunchTemplate_associateCarrierIPAddress(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_associateCarrierIpAddress(rName, "true"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLaunchTemplateExists(resourceName, &template), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "network_interfaces.0.network_interface_id"), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.associate_carrier_ip_address", "true"), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.ipv4_address_count", "2"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSLaunchTemplateConfig_associateCarrierIpAddress(rName, "false"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLaunchTemplateExists(resourceName, &template), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "network_interfaces.0.network_interface_id"), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.associate_carrier_ip_address", "false"), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.ipv4_address_count", "2"), + ), + }, + { + Config: testAccAWSLaunchTemplateConfig_associateCarrierIpAddress(rName, "null"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSLaunchTemplateExists(resourceName, &template), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.#", "1"), + resource.TestCheckResourceAttrSet(resourceName, "network_interfaces.0.network_interface_id"), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.associate_carrier_ip_address", ""), + resource.TestCheckResourceAttr(resourceName, "network_interfaces.0.ipv4_address_count", "2"), + ), + }, + }, + }) +} + func TestAccAWSLaunchTemplate_placement_partitionNum(t *testing.T) { var template ec2.LaunchTemplate resourceName := "aws_launch_template.test" @@ -1605,6 +1654,33 @@ resource "aws_launch_template" "test" { `, rName, associatePublicIPAddress) } +func testAccAWSLaunchTemplateConfig_associateCarrierIpAddress(rName, associateCarrierIPAddress string) string { + return fmt.Sprintf(` +resource "aws_vpc" "test" { + cidr_block = "10.1.0.0/16" +} + +resource "aws_subnet" "test" { + vpc_id = aws_vpc.test.id + cidr_block = "10.1.0.0/24" +} + +resource "aws_network_interface" "test" { + subnet_id = aws_subnet.test.id +} + +resource "aws_launch_template" "test" { + name = %[1]q + + network_interfaces { + network_interface_id = aws_network_interface.test.id + associate_carrier_ip_address = %[2]s + ipv4_address_count = 2 + } +} +`, rName, associateCarrierIPAddress) +} + func testAccAWSLaunchTemplateConfig_networkInterface_ipv6Addresses(rName string) string { return fmt.Sprintf(` resource "aws_launch_template" "test" { diff --git a/website/docs/r/launch_template.html.markdown b/website/docs/r/launch_template.html.markdown index 6adf5f4c5ac6..04a730939a87 100644 --- a/website/docs/r/launch_template.html.markdown +++ b/website/docs/r/launch_template.html.markdown @@ -289,6 +289,7 @@ Check limitations for autoscaling group in [Creating an Auto Scaling Group Using Each `network_interfaces` block supports the following: +* `associate_carrier_ip_address` - Associate a Carrier IP address with `eth0` for a new network interface. Use this option when you launch an instance in a Wavelength Zone and want to associate a Carrier IP address with the network interface. Boolean value. * `associate_public_ip_address` - Associate a public ip address with the network interface. Boolean value. * `delete_on_termination` - Whether the network interface should be destroyed on instance termination. Defaults to `false` if not set. * `description` - Description of the network interface.