diff --git a/aws/data_source_aws_vpn_gateway.go b/aws/data_source_aws_vpn_gateway.go index 10d33360c0f..2d0fa3277ac 100644 --- a/aws/data_source_aws_vpn_gateway.go +++ b/aws/data_source_aws_vpn_gateway.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "strconv" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" @@ -34,6 +35,11 @@ func dataSourceAwsVpnGateway() *schema.Resource { Optional: true, Computed: true, }, + "amazon_side_asn": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, "filter": ec2CustomFiltersSchema(), "tags": tagsSchemaComputed(), }, @@ -55,6 +61,13 @@ func dataSourceAwsVpnGatewayRead(d *schema.ResourceData, meta interface{}) error "availability-zone": d.Get("availability_zone").(string), }, ) + if asn, ok := d.GetOk("amazon_side_asn"); ok { + req.Filters = append(req.Filters, buildEC2AttributeFilterList( + map[string]string{ + "amazon-side-asn": asn.(string), + }, + )...) + } if id, ok := d.GetOk("attached_vpc_id"); ok { req.Filters = append(req.Filters, buildEC2AttributeFilterList( map[string]string{ @@ -91,6 +104,7 @@ func dataSourceAwsVpnGatewayRead(d *schema.ResourceData, meta interface{}) error d.SetId(aws.StringValue(vgw.VpnGatewayId)) d.Set("state", vgw.State) d.Set("availability_zone", vgw.AvailabilityZone) + d.Set("amazon_side_asn", strconv.FormatInt(aws.Int64Value(vgw.AmazonSideAsn), 10)) d.Set("tags", tagsToMap(vgw.Tags)) for _, attachment := range vgw.VpcAttachments { diff --git a/aws/data_source_aws_vpn_gateway_test.go b/aws/data_source_aws_vpn_gateway_test.go index 29bfb516fc8..084060675e4 100644 --- a/aws/data_source_aws_vpn_gateway_test.go +++ b/aws/data_source_aws_vpn_gateway_test.go @@ -25,9 +25,13 @@ func TestAccDataSourceAwsVpnGateway_unattached(t *testing.T) { resource.TestCheckResourceAttrPair( "data.aws_vpn_gateway.test_by_tags", "id", "aws_vpn_gateway.unattached", "id"), + resource.TestCheckResourceAttrPair( + "data.aws_vpn_gateway.test_by_amazon_side_asn", "id", + "aws_vpn_gateway.unattached", "id"), resource.TestCheckResourceAttrSet("data.aws_vpn_gateway.test_by_id", "state"), resource.TestCheckResourceAttr("data.aws_vpn_gateway.test_by_tags", "tags.%", "3"), resource.TestCheckNoResourceAttr("data.aws_vpn_gateway.test_by_id", "attached_vpc_id"), + resource.TestCheckResourceAttr("data.aws_vpn_gateway.test_by_amazon_side_asn", "amazon_side_asn", "4294967293"), ), }, }, @@ -59,46 +63,44 @@ func TestAccDataSourceAwsVpnGateway_attached(t *testing.T) { func testAccDataSourceAwsVpnGatewayUnattachedConfig(rInt int) string { return fmt.Sprintf(` -provider "aws" { - region = "us-west-2" -} - resource "aws_vpn_gateway" "unattached" { - tags { - Name = "terraform-testacc-vpn-gateway-data-source-unattached-%d" - ABC = "testacc-%d" - XYZ = "testacc-%d" - } + tags { + Name = "terraform-testacc-vpn-gateway-data-source-unattached-%d" + ABC = "testacc-%d" + XYZ = "testacc-%d" + } + amazon_side_asn = 4294967293 } data "aws_vpn_gateway" "test_by_id" { - id = "${aws_vpn_gateway.unattached.id}" + id = "${aws_vpn_gateway.unattached.id}" } data "aws_vpn_gateway" "test_by_tags" { - tags = "${aws_vpn_gateway.unattached.tags}" + tags = "${aws_vpn_gateway.unattached.tags}" +} + +data "aws_vpn_gateway" "test_by_amazon_side_asn" { + amazon_side_asn = "${aws_vpn_gateway.unattached.amazon_side_asn}" + state = "available" } `, rInt, rInt+1, rInt-1) } func testAccDataSourceAwsVpnGatewayAttachedConfig(rInt int) string { return fmt.Sprintf(` -provider "aws" { - region = "us-west-2" -} - resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" + cidr_block = "10.1.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway-data-source-foo-%d" - } + tags { + Name = "terraform-testacc-vpn-gateway-data-source-foo-%d" + } } resource "aws_vpn_gateway" "attached" { - tags { - Name = "terraform-testacc-vpn-gateway-data-source-attached-%d" - } + tags { + Name = "terraform-testacc-vpn-gateway-data-source-attached-%d" + } } resource "aws_vpn_gateway_attachment" "vpn_attachment" { @@ -107,7 +109,7 @@ resource "aws_vpn_gateway_attachment" "vpn_attachment" { } data "aws_vpn_gateway" "test_by_attached_vpc_id" { - attached_vpc_id = "${aws_vpn_gateway_attachment.vpn_attachment.vpc_id}" + attached_vpc_id = "${aws_vpn_gateway_attachment.vpn_attachment.vpc_id}" } `, rInt, rInt) } diff --git a/aws/resource_aws_vpn_gateway.go b/aws/resource_aws_vpn_gateway.go index af0a92e05bf..57ed8a58605 100644 --- a/aws/resource_aws_vpn_gateway.go +++ b/aws/resource_aws_vpn_gateway.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "strconv" "time" "github.com/aws/aws-sdk-go/aws" @@ -23,13 +24,21 @@ func resourceAwsVpnGateway() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "availability_zone": &schema.Schema{ + "availability_zone": { Type: schema.TypeString, Optional: true, ForceNew: true, }, - "vpc_id": &schema.Schema{ + "amazon_side_asn": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + ValidateFunc: validateAmazonSideAsn, + }, + + "vpc_id": { Type: schema.TypeString, Optional: true, Computed: true, @@ -47,6 +56,13 @@ func resourceAwsVpnGatewayCreate(d *schema.ResourceData, meta interface{}) error AvailabilityZone: aws.String(d.Get("availability_zone").(string)), Type: aws.String("ipsec.1"), } + if asn, ok := d.GetOk("amazon_side_asn"); ok { + i, err := strconv.ParseInt(asn.(string), 10, 64) + if err != nil { + return err + } + createOpts.AmazonSideAsn = aws.Int64(i) + } // Create the VPN gateway log.Printf("[DEBUG] Creating VPN gateway") @@ -98,6 +114,7 @@ func resourceAwsVpnGatewayRead(d *schema.ResourceData, meta interface{}) error { if vpnGateway.AvailabilityZone != nil && *vpnGateway.AvailabilityZone != "" { d.Set("availability_zone", vpnGateway.AvailabilityZone) } + d.Set("amazon_side_asn", strconv.FormatInt(aws.Int64Value(vpnGateway.AmazonSideAsn), 10)) d.Set("tags", tagsToMap(vpnGateway.Tags)) return nil diff --git a/aws/resource_aws_vpn_gateway_test.go b/aws/resource_aws_vpn_gateway_test.go index 5fbdf5fff1f..481f76966be 100644 --- a/aws/resource_aws_vpn_gateway_test.go +++ b/aws/resource_aws_vpn_gateway_test.go @@ -127,6 +127,25 @@ func TestAccAWSVpnGateway_withAvailabilityZoneSetToState(t *testing.T) { }, }) } +func TestAccAWSVpnGateway_withAmazonSideAsnSetToState(t *testing.T) { + var v ec2.VpnGateway + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckVpnGatewayDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccVpnGatewayConfigWithASN, + Check: resource.ComposeTestCheckFunc( + testAccCheckVpnGatewayExists("aws_vpn_gateway.foo", &v), + resource.TestCheckResourceAttr( + "aws_vpn_gateway.foo", "amazon_side_asn", "4294967294"), + ), + }, + }, + }) +} func TestAccAWSVpnGateway_disappears(t *testing.T) { var v ec2.VpnGateway @@ -420,150 +439,161 @@ func testAccCheckVpnGatewayExists(n string, ig *ec2.VpnGateway) resource.TestChe const testAccNoVpnGatewayConfig = ` resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.1.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } ` const testAccVpnGatewayConfig = ` resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.1.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpn_gateway" "foo" { - vpc_id = "${aws_vpc.foo.id}" - tags { - Name = "terraform-testacc-vpn-gateway-basic" - } + vpc_id = "${aws_vpc.foo.id}" + tags { + Name = "terraform-testacc-vpn-gateway-basic" + } } ` const testAccVpnGatewayConfigChangeVPC = ` resource "aws_vpc" "bar" { - cidr_block = "10.2.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.2.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpn_gateway" "foo" { - vpc_id = "${aws_vpc.bar.id}" - tags { - Name = "terraform-testacc-vpn-gateway-basic" - } + vpc_id = "${aws_vpc.bar.id}" + tags { + Name = "terraform-testacc-vpn-gateway-basic" + } } ` const testAccCheckVpnGatewayConfigTags = ` resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.1.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpn_gateway" "foo" { - vpc_id = "${aws_vpc.foo.id}" - tags { - Name = "terraform-testacc-vpn-gateway-tags" - } + vpc_id = "${aws_vpc.foo.id}" + tags { + Name = "terraform-testacc-vpn-gateway-tags" + } } ` const testAccCheckVpnGatewayConfigTagsUpdate = ` resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.1.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpn_gateway" "foo" { - vpc_id = "${aws_vpc.foo.id}" - tags { - Name = "terraform-testacc-vpn-gateway-tags-updated" - } + vpc_id = "${aws_vpc.foo.id}" + tags { + Name = "terraform-testacc-vpn-gateway-tags-updated" + } } ` const testAccCheckVpnGatewayConfigReattach = ` resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.1.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpc" "bar" { - cidr_block = "10.2.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.2.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpn_gateway" "foo" { - vpc_id = "${aws_vpc.foo.id}" - tags { - Name = "terraform-testacc-vpn-gateway-reattach" - } + vpc_id = "${aws_vpc.foo.id}" + tags { + Name = "terraform-testacc-vpn-gateway-reattach" + } } resource "aws_vpn_gateway" "bar" { - vpc_id = "${aws_vpc.bar.id}" - tags { - Name = "terraform-testacc-vpn-gateway-reattach" - } + vpc_id = "${aws_vpc.bar.id}" + tags { + Name = "terraform-testacc-vpn-gateway-reattach" + } } ` const testAccCheckVpnGatewayConfigReattachChange = ` resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.1.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpc" "bar" { - cidr_block = "10.2.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.2.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpn_gateway" "foo" { - vpc_id = "${aws_vpc.bar.id}" - tags { - Name = "terraform-testacc-vpn-gateway-reattach" - } + vpc_id = "${aws_vpc.bar.id}" + tags { + Name = "terraform-testacc-vpn-gateway-reattach" + } } resource "aws_vpn_gateway" "bar" { - vpc_id = "${aws_vpc.foo.id}" - tags { - Name = "terraform-testacc-vpn-gateway-reattach" - } + vpc_id = "${aws_vpc.foo.id}" + tags { + Name = "terraform-testacc-vpn-gateway-reattach" + } } ` const testAccVpnGatewayConfigWithAZ = ` resource "aws_vpc" "foo" { - cidr_block = "10.1.0.0/16" - tags { - Name = "terraform-testacc-vpn-gateway" - } + cidr_block = "10.1.0.0/16" + tags { + Name = "terraform-testacc-vpn-gateway" + } } resource "aws_vpn_gateway" "foo" { - vpc_id = "${aws_vpc.foo.id}" - availability_zone = "us-west-2a" - tags { - Name = "terraform-testacc-vpn-gateway-with-az" - } + vpc_id = "${aws_vpc.foo.id}" + availability_zone = "us-west-2a" + tags { + Name = "terraform-testacc-vpn-gateway-with-az" + } +} +` + +const testAccVpnGatewayConfigWithASN = ` +resource "aws_vpc" "foo" { + cidr_block = "10.1.0.0/16" +} + +resource "aws_vpn_gateway" "foo" { + vpc_id = "${aws_vpc.foo.id}" + amazon_side_asn = 4294967294 } ` diff --git a/aws/validators.go b/aws/validators.go index 7ca6ff05e59..990f90b36a8 100644 --- a/aws/validators.go +++ b/aws/validators.go @@ -6,6 +6,7 @@ import ( "net" "net/url" "regexp" + "strconv" "strings" "time" @@ -2254,3 +2255,19 @@ func validateStringIn(validValues ...string) schema.SchemaValidateFunc { return } } + +func validateAmazonSideAsn(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + // http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateVpnGateway.html + 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 < 64512) || (asn > 65534 && asn < 4200000000) || (asn > 4294967294) { + errors = append(errors, fmt.Errorf("%q (%q) must be in the range 64512 to 65534 or 4200000000 to 4294967294", k, v)) + } + return +} diff --git a/aws/validators_test.go b/aws/validators_test.go index 5cf9e95d844..80e76312a61 100644 --- a/aws/validators_test.go +++ b/aws/validators_test.go @@ -3068,3 +3068,34 @@ func TestValidateGuardDutyThreatIntelSetFormat(t *testing.T) { } } } + +func TestValidateAmazonSideAsn(t *testing.T) { + validAsns := []string{ + "64512", + "64513", + "65533", + "65534", + "4200000000", + "4200000001", + "4294967293", + "4294967294", + } + for _, v := range validAsns { + _, errors := validateAmazonSideAsn(v, "amazon_side_asn") + if len(errors) != 0 { + t.Fatalf("%q should be a valid ASN: %q", v, errors) + } + } + + invalidAsns := []string{ + "1", + "ABCDEFG", + "", + } + for _, v := range invalidAsns { + _, errors := validateAmazonSideAsn(v, "amazon_side_asn") + if len(errors) == 0 { + t.Fatalf("%q should be an invalid ASN", v) + } + } +} diff --git a/website/docs/d/vpn_gateway.html.markdown b/website/docs/d/vpn_gateway.html.markdown index c117b0b0aec..0996a88e350 100644 --- a/website/docs/d/vpn_gateway.html.markdown +++ b/website/docs/d/vpn_gateway.html.markdown @@ -44,6 +44,8 @@ The given filters must match exactly one VPN gateway whose data will be exported * `tags` - (Optional) A mapping of tags, each pair of which must exactly match a pair on the desired VPN Gateway. +* `amazon_side_asn` - (Optional) The Autonomous System Number (ASN) for the Amazon side of the specific VPN Gateway to retrieve. + More complex filters can be expressed using one or more `filter` sub-blocks, which take the following arguments: diff --git a/website/docs/r/vpn_gateway.html.markdown b/website/docs/r/vpn_gateway.html.markdown index a574a9210e7..57561031e3e 100644 --- a/website/docs/r/vpn_gateway.html.markdown +++ b/website/docs/r/vpn_gateway.html.markdown @@ -29,6 +29,7 @@ The following arguments are supported: * `vpc_id` - (Optional) The VPC ID to create in. * `availability_zone` - (Optional) The Availability Zone for the virtual private gateway. * `tags` - (Optional) A mapping of tags to assign to the resource. +* `amazon_side_asn` - (Optional) The Autonomous System Number (ASN) for the Amazon side of the gateway. If you don't specify an ASN, the virtual private gateway is created with the default ASN. ## Attributes Reference @@ -43,4 +44,4 @@ VPN Gateways can be imported using the `vpn gateway id`, e.g. ``` $ terraform import aws_vpn_gateway.testvpngateway vgw-9a4cacf3 -``` \ No newline at end of file +```