Skip to content

Commit

Permalink
resource/aws_customer_gateway: Allow 4-byte ASNs (#14030)
Browse files Browse the repository at this point in the history
Output from acceptance testing:

```
--- PASS: TestAccAWSCustomerGateway_disappears (18.14s)
--- PASS: TestAccAWSCustomerGateway_4ByteAsn (20.38s)
--- PASS: TestAccAWSCustomerGateway_similarAlreadyExists (23.01s)
--- PASS: TestAccAWSCustomerGateway_basic (36.37s)
--- PASS: TestAccAWSCustomerGateway_tags (62.25s)
```
  • Loading branch information
ewbankkit authored Jul 2, 2020
1 parent 0f3643c commit bb489e7
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 17 deletions.
30 changes: 13 additions & 17 deletions aws/resource_aws_customer_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ func resourceAwsCustomerGateway() *schema.Resource {

Schema: map[string]*schema.Schema{
"bgp_asn": {
Type: schema.TypeInt,
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.IntBetween(1, 65534),
ValidateFunc: validate4ByteAsn,
},

"ip_address": {
Expand Down Expand Up @@ -66,19 +66,24 @@ func resourceAwsCustomerGatewayCreate(d *schema.ResourceData, meta interface{})

ipAddress := d.Get("ip_address").(string)
vpnType := d.Get("type").(string)
bgpAsn := d.Get("bgp_asn").(int)
bgpAsn := d.Get("bgp_asn").(string)

alreadyExists, err := resourceAwsCustomerGatewayExists(vpnType, ipAddress, bgpAsn, conn)
if err != nil {
return err
}

if alreadyExists {
return fmt.Errorf("An existing customer gateway for IpAddress: %s, VpnType: %s, BGP ASN: %d has been found", ipAddress, vpnType, bgpAsn)
return fmt.Errorf("An existing customer gateway for IpAddress: %s, VpnType: %s, BGP ASN: %s has been found", ipAddress, vpnType, bgpAsn)
}

i64BgpAsn, err := strconv.ParseInt(bgpAsn, 10, 64)
if err != nil {
return err
}

createOpts := &ec2.CreateCustomerGatewayInput{
BgpAsn: aws.Int64(int64(bgpAsn)),
BgpAsn: aws.Int64(i64BgpAsn),
PublicIp: aws.String(ipAddress),
Type: aws.String(vpnType),
}
Expand Down Expand Up @@ -150,7 +155,7 @@ func customerGatewayRefreshFunc(conn *ec2.EC2, gatewayId string) resource.StateR
}
}

func resourceAwsCustomerGatewayExists(vpnType, ipAddress string, bgpAsn int, conn *ec2.EC2) (bool, error) {
func resourceAwsCustomerGatewayExists(vpnType, ipAddress, bgpAsn string, conn *ec2.EC2) (bool, error) {
ipAddressFilter := &ec2.Filter{
Name: aws.String("ip-address"),
Values: []*string{aws.String(ipAddress)},
Expand All @@ -161,10 +166,9 @@ func resourceAwsCustomerGatewayExists(vpnType, ipAddress string, bgpAsn int, con
Values: []*string{aws.String(vpnType)},
}

bgp := strconv.Itoa(bgpAsn)
bgpAsnFilter := &ec2.Filter{
Name: aws.String("bgp-asn"),
Values: []*string{aws.String(bgp)},
Values: []*string{aws.String(bgpAsn)},
}

resp, err := conn.DescribeCustomerGateways(&ec2.DescribeCustomerGatewaysInput{
Expand Down Expand Up @@ -215,22 +219,14 @@ func resourceAwsCustomerGatewayRead(d *schema.ResourceData, meta interface{}) er
}

customerGateway := resp.CustomerGateways[0]
d.Set("bgp_asn", customerGateway.BgpAsn)
d.Set("ip_address", customerGateway.IpAddress)
d.Set("type", customerGateway.Type)

if err := d.Set("tags", keyvaluetags.Ec2KeyValueTags(customerGateway.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %s", err)
}

if aws.StringValue(customerGateway.BgpAsn) != "" {
val, err := strconv.ParseInt(aws.StringValue(customerGateway.BgpAsn), 0, 0)
if err != nil {
return fmt.Errorf("error parsing bgp_asn: %s", err)
}

d.Set("bgp_asn", int(val))
}

arn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Service: "ec2",
Expand Down
41 changes: 41 additions & 0 deletions aws/resource_aws_customer_gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"regexp"
"strconv"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
Expand All @@ -27,6 +28,7 @@ func TestAccAWSCustomerGateway_basic(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testAccCheckCustomerGateway(resourceName, &gateway),
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`customer-gateway/cgw-.+`)),
resource.TestCheckResourceAttr(resourceName, "bgp_asn", strconv.Itoa(rBgpAsn)),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
),
},
Expand Down Expand Up @@ -139,6 +141,35 @@ func TestAccAWSCustomerGateway_disappears(t *testing.T) {
})
}

func TestAccAWSCustomerGateway_4ByteAsn(t *testing.T) {
var gateway ec2.CustomerGateway
rBgpAsn := strconv.FormatInt(int64(randIntRange(64512, 65534))*10000, 10)
resourceName := "aws_customer_gateway.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: resourceName,
Providers: testAccProviders,
CheckDestroy: testAccCheckCustomerGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccCustomerGatewayConfig4ByteAsn(rBgpAsn),
Check: resource.ComposeTestCheckFunc(
testAccCheckCustomerGateway(resourceName, &gateway),
testAccMatchResourceAttrRegionalARN(resourceName, "arn", "ec2", regexp.MustCompile(`customer-gateway/cgw-.+`)),
resource.TestCheckResourceAttr(resourceName, "bgp_asn", rBgpAsn),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckCustomerGatewayDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn

Expand Down Expand Up @@ -278,3 +309,13 @@ resource "aws_customer_gateway" "test" {
}
`, rBgpAsn)
}

func testAccCustomerGatewayConfig4ByteAsn(rBgpAsn string) string {
return fmt.Sprintf(`
resource "aws_customer_gateway" "test" {
bgp_asn = %[1]q
ip_address = "172.0.0.1"
type = "ipsec.1"
}
`, rBgpAsn)
}
15 changes: 15 additions & 0 deletions aws/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -2126,6 +2126,21 @@ func validateAmazonSideAsn(v interface{}, k string) (ws []string, errors []error
return
}

func validate4ByteAsn(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)

asn, err := strconv.ParseInt(value, 10, 64)
if err != nil {
errors = append(errors, fmt.Errorf("%q (%q) must be a 64-bit integer", k, v))
return
}

if asn < 0 || asn > 4294967295 {
errors = append(errors, fmt.Errorf("%q (%q) must be in the range 0 to 4294967295", k, v))
}
return
}

func validateIotThingTypeName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`[a-zA-Z0-9:_-]+`).MatchString(value) {
Expand Down
31 changes: 31 additions & 0 deletions aws/validators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2727,6 +2727,37 @@ func TestValidateAmazonSideAsn(t *testing.T) {
}
}

func TestValidate4ByteAsn(t *testing.T) {
validAsns := []string{
"0",
"1",
"65534",
"65535",
"4294967294",
"4294967295",
}
for _, v := range validAsns {
_, errors := validate4ByteAsn(v, "bgp_asn")
if len(errors) != 0 {
t.Fatalf("%q should be a valid ASN: %q", v, errors)
}
}

invalidAsns := []string{
"-1",
"ABCDEFG",
"",
"4294967296",
"9999999999",
}
for _, v := range invalidAsns {
_, errors := validate4ByteAsn(v, "bgp_asn")
if len(errors) == 0 {
t.Fatalf("%q should be an invalid ASN", v)
}
}
}

func TestValidateLaunchTemplateName(t *testing.T) {
validNames := []string{
"fooBAR123",
Expand Down

0 comments on commit bb489e7

Please sign in to comment.