provider/aws: Implement IPV6 Support for ec2 / VPC (#10538)

* provider/aws: Add support for IPV6 enabled VPC

```
% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSVpc'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2016/12/09 14:07:31 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSVpc -timeout 120m
=== RUN   TestAccAWSVpc_importBasic
--- PASS: TestAccAWSVpc_importBasic (43.03s)
=== RUN   TestAccAWSVpc_basic
--- PASS: TestAccAWSVpc_basic (36.32s)
=== RUN   TestAccAWSVpc_enableIpv6
--- PASS: TestAccAWSVpc_enableIpv6 (29.37s)
=== RUN   TestAccAWSVpc_dedicatedTenancy
--- PASS: TestAccAWSVpc_dedicatedTenancy (36.63s)
=== RUN   TestAccAWSVpc_tags
--- PASS: TestAccAWSVpc_tags (67.54s)
=== RUN   TestAccAWSVpc_update
--- PASS: TestAccAWSVpc_update (66.16s)
=== RUN   TestAccAWSVpc_bothDnsOptionsSet
--- PASS: TestAccAWSVpc_bothDnsOptionsSet (16.82s)
=== RUN   TestAccAWSVpc_DisabledDnsSupport
--- PASS: TestAccAWSVpc_DisabledDnsSupport (36.52s)
=== RUN   TestAccAWSVpc_classiclinkOptionSet
--- PASS: TestAccAWSVpc_classiclinkOptionSet (38.13s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/aws	739.543s
```

* provider/aws: New Resource: aws_egress_only_internet_gateway

```
make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSEgressOnlyInternetGateway_'
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2016/12/09 14:22:16 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSEgressOnlyInternetGateway_ -timeout 120m
=== RUN   TestAccAWSEgressOnlyInternetGateway_basic
--- PASS: TestAccAWSEgressOnlyInternetGateway_basic (32.67s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/aws	32.692s
```

* provider/aws: Add IPV6 support to aws_subnet

```
% make testacc TEST=./builtin/providers/aws
% TESTARGS='-run=TestAccAWSSubnet_'
% 1 ↵ ✹ ✭
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/02/27 19:08:34 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSubnet_
-timeout 120m
=== RUN   TestAccAWSSubnet_importBasic
--- PASS: TestAccAWSSubnet_importBasic (69.88s)
=== RUN   TestAccAWSSubnet_basic
--- PASS: TestAccAWSSubnet_basic (51.28s)
=== RUN   TestAccAWSSubnet_ipv6
--- PASS: TestAccAWSSubnet_ipv6 (90.39s)
PASS
ok      github.com/hashicorp/terraform/builtin/providers/aws211.574s
```

* provider/aws: Add support for running aws_instances with ipv6 addresses
This commit is contained in:
Paul Stack 2017-03-01 16:16:59 +00:00 committed by GitHub
parent 3d198295f2
commit 177400dbbf
14 changed files with 568 additions and 9 deletions

View File

@ -275,6 +275,7 @@ func Provider() terraform.ResourceProvider {
"aws_ecs_task_definition": resourceAwsEcsTaskDefinition(),
"aws_efs_file_system": resourceAwsEfsFileSystem(),
"aws_efs_mount_target": resourceAwsEfsMountTarget(),
"aws_egress_only_internet_gateway": resourceAwsEgressOnlyInternetGateway(),
"aws_eip": resourceAwsEip(),
"aws_eip_association": resourceAwsEipAssociation(),
"aws_elasticache_cluster": resourceAwsElasticacheCluster(),

View File

@ -0,0 +1,126 @@
package aws
import (
"fmt"
"log"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsEgressOnlyInternetGateway() *schema.Resource {
return &schema.Resource{
Create: resourceAwsEgressOnlyInternetGatewayCreate,
Read: resourceAwsEgressOnlyInternetGatewayRead,
Delete: resourceAwsEgressOnlyInternetGatewayDelete,
Schema: map[string]*schema.Schema{
"vpc_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}
func resourceAwsEgressOnlyInternetGatewayCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
resp, err := conn.CreateEgressOnlyInternetGateway(&ec2.CreateEgressOnlyInternetGatewayInput{
VpcId: aws.String(d.Get("vpc_id").(string)),
})
if err != nil {
return fmt.Errorf("Error creating egress internet gateway: %s", err)
}
d.SetId(*resp.EgressOnlyInternetGateway.EgressOnlyInternetGatewayId)
err = resource.Retry(5*time.Minute, func() *resource.RetryError {
igRaw, _, err := EIGWStateRefreshFunc(conn, d.Id())()
if igRaw != nil {
return nil
}
if err == nil {
return resource.RetryableError(err)
} else {
return resource.NonRetryableError(err)
}
})
if err != nil {
return errwrap.Wrapf("{{err}}", err)
}
return resourceAwsEgressOnlyInternetGatewayRead(d, meta)
}
func EIGWStateRefreshFunc(conn *ec2.EC2, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
resp, err := conn.DescribeEgressOnlyInternetGateways(&ec2.DescribeEgressOnlyInternetGatewaysInput{
EgressOnlyInternetGatewayIds: []*string{aws.String(id)},
})
if err != nil {
ec2err, ok := err.(awserr.Error)
if ok && ec2err.Code() == "InvalidEgressInternetGatewayID.NotFound" {
resp = nil
} else {
log.Printf("[ERROR] Error on EIGWStateRefreshFunc: %s", err)
return nil, "", err
}
}
if resp == nil {
// Sometimes AWS just has consistency issues and doesn't see
// our instance yet. Return an empty state.
return nil, "", nil
}
ig := resp.EgressOnlyInternetGateways[0]
return ig, "available", nil
}
}
func resourceAwsEgressOnlyInternetGatewayRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
resp, err := conn.DescribeEgressOnlyInternetGateways(&ec2.DescribeEgressOnlyInternetGatewaysInput{
EgressOnlyInternetGatewayIds: []*string{aws.String(d.Id())},
})
if err != nil {
return fmt.Errorf("Error describing egress internet gateway: %s", err)
}
found := false
for _, igw := range resp.EgressOnlyInternetGateways {
if *igw.EgressOnlyInternetGatewayId == d.Id() {
found = true
}
}
if !found {
log.Printf("[Error] Cannot find Egress Only Internet Gateway: %q", d.Id())
d.SetId("")
return nil
}
return nil
}
func resourceAwsEgressOnlyInternetGatewayDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
_, err := conn.DeleteEgressOnlyInternetGateway(&ec2.DeleteEgressOnlyInternetGatewayInput{
EgressOnlyInternetGatewayId: aws.String(d.Id()),
})
if err != nil {
return fmt.Errorf("Error deleting egress internet gateway: %s", err)
}
return nil
}

View File

@ -0,0 +1,92 @@
package aws
import (
"fmt"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccAWSEgressOnlyInternetGateway_basic(t *testing.T) {
var igw ec2.EgressOnlyInternetGateway
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSEgressOnlyInternetGatewayDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSEgressOnlyInternetGatewayConfig_basic,
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSEgressOnlyInternetGatewayExists("aws_egress_only_internet_gateway.foo", &igw),
),
},
},
})
}
func testAccCheckAWSEgressOnlyInternetGatewayDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_egress_only_internet_gateway" {
continue
}
describe, err := conn.DescribeEgressOnlyInternetGateways(&ec2.DescribeEgressOnlyInternetGatewaysInput{
EgressOnlyInternetGatewayIds: []*string{aws.String(rs.Primary.ID)},
})
if err == nil {
if len(describe.EgressOnlyInternetGateways) != 0 &&
*describe.EgressOnlyInternetGateways[0].EgressOnlyInternetGatewayId == rs.Primary.ID {
return fmt.Errorf("Egress Only Internet Gateway %q still exists", rs.Primary.ID)
}
}
return nil
}
return nil
}
func testAccCheckAWSEgressOnlyInternetGatewayExists(n string, igw *ec2.EgressOnlyInternetGateway) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No Egress Only IGW ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).ec2conn
resp, err := conn.DescribeEgressOnlyInternetGateways(&ec2.DescribeEgressOnlyInternetGatewaysInput{
EgressOnlyInternetGatewayIds: []*string{aws.String(rs.Primary.ID)},
})
if err != nil {
return err
}
if len(resp.EgressOnlyInternetGateways) == 0 {
return fmt.Errorf("Egress Only IGW not found")
}
*igw = *resp.EgressOnlyInternetGateways[0]
return nil
}
}
const testAccAWSEgressOnlyInternetGatewayConfig_basic = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
assign_generated_ipv6_cidr_block = true
}
resource "aws_egress_only_internet_gateway" "foo" {
vpc_id = "${aws_vpc.foo.id}"
}
`

View File

@ -175,6 +175,23 @@ func resourceAwsInstance() *schema.Resource {
Optional: true,
},
"ipv6_address_count": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"ipv6_addresses": {
Type: schema.TypeList,
Optional: true,
Computed: true,
ForceNew: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
ConflictsWith: []string{"ipv6_address_count"},
},
"tenancy": {
Type: schema.TypeString,
Optional: true,
@ -363,6 +380,23 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error {
UserData: instanceOpts.UserData64,
}
if v, ok := d.GetOk("ipv6_address_count"); ok {
runOpts.Ipv6AddressCount = aws.Int64(int64(v.(int)))
}
if v, ok := d.GetOk("ipv6_addresses"); ok {
ipv6Addresses := make([]*ec2.InstanceIpv6Address, len(v.([]interface{})))
for _, address := range v.([]interface{}) {
ipv6Address := &ec2.InstanceIpv6Address{
Ipv6Address: aws.String(address.(string)),
}
ipv6Addresses = append(ipv6Addresses, ipv6Address)
}
runOpts.Ipv6Addresses = ipv6Addresses
}
// Create the instance
log.Printf("[DEBUG] Run configuration: %s", runOpts)
@ -501,6 +535,13 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error {
d.Set("subnet_id", ni.SubnetId)
d.Set("network_interface_id", ni.NetworkInterfaceId)
d.Set("associate_public_ip_address", ni.Association != nil)
d.Set("ipv6_address_count", len(ni.Ipv6Addresses))
var ipv6Addresses []string
for _, address := range ni.Ipv6Addresses {
ipv6Addresses = append(ipv6Addresses, *address.Ipv6Address)
}
d.Set("ipv6_addresses", ipv6Addresses)
}
}
} else {

View File

@ -498,6 +498,29 @@ func TestAccAWSInstance_vpc(t *testing.T) {
})
}
func TestAccAWSInstance_ipv6_supportAddressCount(t *testing.T) {
var v ec2.Instance
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccInstanceConfigIpv6Support,
Check: resource.ComposeTestCheckFunc(
testAccCheckInstanceExists(
"aws_instance.foo", &v),
resource.TestCheckResourceAttr(
"aws_instance.foo",
"ipv6_address_count",
"1"),
),
},
},
})
}
func TestAccAWSInstance_multipleRegions(t *testing.T) {
var v ec2.Instance
@ -1123,6 +1146,37 @@ resource "aws_instance" "foo" {
}
`
const testAccInstanceConfigIpv6Support = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
assign_generated_ipv6_cidr_block = true
tags {
Name = "tf-ipv6-instance-acc-test"
}
}
resource "aws_subnet" "foo" {
cidr_block = "10.1.1.0/24"
vpc_id = "${aws_vpc.foo.id}"
ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 1)}"
tags {
Name = "tf-ipv6-instance-acc-test"
}
}
resource "aws_instance" "foo" {
# us-west-2
ami = "ami-c5eabbf5"
instance_type = "t2.micro"
subnet_id = "${aws_subnet.foo.id}"
ipv6_address_count = 1
tags {
Name = "tf-ipv6-instance-acc-test"
}
}
`
const testAccInstanceConfigMultipleRegions = `
provider "aws" {
alias = "west"

View File

@ -23,31 +23,48 @@ func resourceAwsSubnet() *schema.Resource {
},
Schema: map[string]*schema.Schema{
"vpc_id": &schema.Schema{
"vpc_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"cidr_block": &schema.Schema{
"cidr_block": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"availability_zone": &schema.Schema{
"ipv6_cidr_block": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},
"availability_zone": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"map_public_ip_on_launch": &schema.Schema{
"map_public_ip_on_launch": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"assign_ipv6_address_on_creation": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"ipv6_cidr_block_association_id": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchema(),
},
}
@ -62,6 +79,10 @@ func resourceAwsSubnetCreate(d *schema.ResourceData, meta interface{}) error {
VpcId: aws.String(d.Get("vpc_id").(string)),
}
if v, ok := d.GetOk("ipv6_cidr_block"); ok {
createOpts.Ipv6CidrBlock = aws.String(v.(string))
}
var err error
resp, err := conn.CreateSubnet(createOpts)
@ -119,6 +140,11 @@ func resourceAwsSubnetRead(d *schema.ResourceData, meta interface{}) error {
d.Set("availability_zone", subnet.AvailabilityZone)
d.Set("cidr_block", subnet.CidrBlock)
d.Set("map_public_ip_on_launch", subnet.MapPublicIpOnLaunch)
d.Set("assign_ipv6_address_on_creation", subnet.AssignIpv6AddressOnCreation)
if subnet.Ipv6CidrBlockAssociationSet != nil {
d.Set("ipv6_cidr_block", subnet.Ipv6CidrBlockAssociationSet[0].Ipv6CidrBlock)
d.Set("ipv6_cidr_block_association_id", subnet.Ipv6CidrBlockAssociationSet[0].AssociationId)
}
d.Set("tags", tagsToMap(subnet.Tags))
return nil
@ -135,6 +161,25 @@ func resourceAwsSubnetUpdate(d *schema.ResourceData, meta interface{}) error {
d.SetPartial("tags")
}
if d.HasChange("assign_ipv6_address_on_creation") {
modifyOpts := &ec2.ModifySubnetAttributeInput{
SubnetId: aws.String(d.Id()),
AssignIpv6AddressOnCreation: &ec2.AttributeBooleanValue{
Value: aws.Bool(d.Get("assign_ipv6_address_on_creation").(bool)),
},
}
log.Printf("[DEBUG] Subnet modify attributes: %#v", modifyOpts)
_, err := conn.ModifySubnetAttribute(modifyOpts)
if err != nil {
return err
} else {
d.SetPartial("assign_ipv6_address_on_creation")
}
}
if d.HasChange("map_public_ip_on_launch") {
modifyOpts := &ec2.ModifySubnetAttributeInput{
SubnetId: aws.String(d.Id()),

View File

@ -32,7 +32,7 @@ func TestAccAWSSubnet_basic(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckSubnetDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccSubnetConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckSubnetExists(
@ -44,6 +44,55 @@ func TestAccAWSSubnet_basic(t *testing.T) {
})
}
func TestAccAWSSubnet_ipv6(t *testing.T) {
var v ec2.Subnet
testCheck := func(*terraform.State) error {
if v.Ipv6CidrBlockAssociationSet == nil {
return fmt.Errorf("Expected IPV6 CIDR Block Association")
}
if *v.AssignIpv6AddressOnCreation != true {
return fmt.Errorf("bad AssignIpv6AddressOnCreation: %t", *v.AssignIpv6AddressOnCreation)
}
return nil
}
testCheckUpdated := func(*terraform.State) error {
if *v.AssignIpv6AddressOnCreation != false {
return fmt.Errorf("bad AssignIpv6AddressOnCreation: %t", *v.AssignIpv6AddressOnCreation)
}
return nil
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: "aws_subnet.foo",
Providers: testAccProviders,
CheckDestroy: testAccCheckSubnetDestroy,
Steps: []resource.TestStep{
{
Config: testAccSubnetConfigIpv6,
Check: resource.ComposeTestCheckFunc(
testAccCheckSubnetExists(
"aws_subnet.foo", &v),
testCheck,
),
},
{
Config: testAccSubnetConfigIpv6Updated,
Check: resource.ComposeTestCheckFunc(
testAccCheckSubnetExists(
"aws_subnet.foo", &v),
testCheckUpdated,
),
},
},
})
}
func testAccCheckSubnetDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn
@ -119,3 +168,39 @@ resource "aws_subnet" "foo" {
}
}
`
const testAccSubnetConfigIpv6 = `
resource "aws_vpc" "foo" {
cidr_block = "10.10.0.0/16"
assign_generated_ipv6_cidr_block = true
}
resource "aws_subnet" "foo" {
cidr_block = "10.10.1.0/24"
vpc_id = "${aws_vpc.foo.id}"
ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 1)}"
map_public_ip_on_launch = true
assign_ipv6_address_on_creation = true
tags {
Name = "tf-subnet-acc-test"
}
}
`
const testAccSubnetConfigIpv6Updated = `
resource "aws_vpc" "foo" {
cidr_block = "10.10.0.0/16"
assign_generated_ipv6_cidr_block = true
}
resource "aws_subnet" "foo" {
cidr_block = "10.10.1.0/24"
vpc_id = "${aws_vpc.foo.id}"
ipv6_cidr_block = "${cidrsubnet(aws_vpc.foo.ipv6_cidr_block, 8, 3)}"
map_public_ip_on_launch = true
assign_ipv6_address_on_creation = false
tags {
Name = "tf-subnet-acc-test"
}
}
`

View File

@ -55,6 +55,13 @@ func resourceAwsVpc() *schema.Resource {
Computed: true,
},
"assign_generated_ipv6_cidr_block": {
Type: schema.TypeBool,
ForceNew: true,
Optional: true,
Default: false,
},
"main_route_table_id": {
Type: schema.TypeString,
Computed: true,
@ -80,6 +87,16 @@ func resourceAwsVpc() *schema.Resource {
Computed: true,
},
"ipv6_association_id": {
Type: schema.TypeString,
Computed: true,
},
"ipv6_cidr_block": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchema(),
},
}
@ -91,11 +108,14 @@ func resourceAwsVpcCreate(d *schema.ResourceData, meta interface{}) error {
if v, ok := d.GetOk("instance_tenancy"); ok {
instance_tenancy = v.(string)
}
// Create the VPC
createOpts := &ec2.CreateVpcInput{
CidrBlock: aws.String(d.Get("cidr_block").(string)),
InstanceTenancy: aws.String(instance_tenancy),
CidrBlock: aws.String(d.Get("cidr_block").(string)),
InstanceTenancy: aws.String(instance_tenancy),
AmazonProvidedIpv6CidrBlock: aws.Bool(d.Get("assign_generated_ipv6_cidr_block").(bool)),
}
log.Printf("[DEBUG] VPC create config: %#v", *createOpts)
vpcResp, err := conn.CreateVpc(createOpts)
if err != nil {
@ -154,6 +174,14 @@ func resourceAwsVpcRead(d *schema.ResourceData, meta interface{}) error {
// Tags
d.Set("tags", tagsToMap(vpc.Tags))
if vpc.Ipv6CidrBlockAssociationSet != nil {
d.Set("assign_generated_ipv6_cidr_block", true)
d.Set("ipv6_association_id", vpc.Ipv6CidrBlockAssociationSet[0].AssociationId)
d.Set("ipv6_cidr_block", vpc.Ipv6CidrBlockAssociationSet[0].Ipv6CidrBlock)
} else {
d.Set("assign_generated_ipv6_cidr_block", false)
}
// Attributes
attribute := "enableDnsSupport"
DescribeAttrOpts := &ec2.DescribeVpcAttributeInput{

View File

@ -36,6 +36,31 @@ func TestAccAWSVpc_basic(t *testing.T) {
})
}
func TestAccAWSVpc_enableIpv6(t *testing.T) {
var vpc ec2.Vpc
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckVpcDestroy,
Steps: []resource.TestStep{
{
Config: testAccVpcConfigIpv6Enabled,
Check: resource.ComposeTestCheckFunc(
testAccCheckVpcExists("aws_vpc.foo", &vpc),
testAccCheckVpcCidr(&vpc, "10.1.0.0/16"),
resource.TestCheckResourceAttr(
"aws_vpc.foo", "cidr_block", "10.1.0.0/16"),
resource.TestCheckResourceAttrSet(
"aws_vpc.foo", "ipv6_association_id"),
resource.TestCheckResourceAttrSet(
"aws_vpc.foo", "ipv6_cidr_block"),
),
},
},
})
}
func TestAccAWSVpc_dedicatedTenancy(t *testing.T) {
var vpc ec2.Vpc
@ -251,6 +276,13 @@ resource "aws_vpc" "foo" {
}
`
const testAccVpcConfigIpv6Enabled = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
assign_generated_ipv6_cidr_block = true
}
`
const testAccVpcConfigUpdate = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"

View File

@ -0,0 +1,39 @@
---
layout: "aws"
page_title: "AWS: aws_egress_only_internet_gateway"
sidebar_current: "docs-aws-resource-egress-only-internet-gateway"
description: |-
Provides a resource to create a VPC Egress Only Internet Gateway.
---
# aws\_egress\_only\_internet\_gateway
[IPv6 only] Creates an egress-only Internet gateway for your VPC.
An egress-only Internet gateway is used to enable outbound communication
over IPv6 from instances in your VPC to the Internet, and prevents hosts
outside of your VPC from initiating an IPv6 connection with your instance.
## Example Usage
```
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
assign_amazon_ipv6_cidr_block = true
}
resource "aws_egress_only_internet_gateway" "foo" {
vpc_id = "${aws_vpc.foo.id}"
}
```
## Argument Reference
The following arguments are supported:
* `vpc_id` - (Required) The VPC ID to create in.
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the Egress Only Internet Gateway.

View File

@ -77,6 +77,8 @@ instances. See [Shutdown Behavior](https://docs.aws.amazon.com/AWSEC2/latest/Use
* `user_data` - (Optional) The user data to provide when launching the instance.
* `iam_instance_profile` - (Optional) The IAM Instance Profile to
launch the instance with.
* `ipv6_address_count`- (Optional) A number of IPv6 addresses to associate with the primary network interface. Amazon EC2 chooses the IPv6 addresses from the range of your subnet.
* `ipv6_addresses` - (Optional) Specify one or more IPv6 addresses from the range of the subnet to associate with the primary network interface
* `tags` - (Optional) A mapping of tags to assign to the resource.
* `root_block_device` - (Optional) Customize details about the root block
device of the instance. See [Block Devices](#block-devices) below for details.

View File

@ -29,9 +29,14 @@ The following arguments are supported:
* `availability_zone`- (Optional) The AZ for the subnet.
* `cidr_block` - (Required) The CIDR block for the subnet.
* `ipv6_cidr_block` - (Optional) The IPv6 network range for the subnet,
in CIDR notation. The subnet size must use a /64 prefix length.
* `map_public_ip_on_launch` - (Optional) Specify true to indicate
that instances launched into the subnet should be assigned
a public IP address.
a public IP address. Default is `false`.
* `assign_ipv6_address_on_creation` - (Optional) Specify true to indicate
that network interfaces created in the specified subnet should be
assigned an IPv6 address. Default is `false`
* `vpc_id` - (Required) The VPC ID.
* `tags` - (Optional) A mapping of tags to assign to the resource.

View File

@ -44,6 +44,9 @@ The following arguments are supported:
* `enable_classiclink` - (Optional) A boolean flag to enable/disable ClassicLink
for the VPC. Only valid in regions and accounts that support EC2 Classic.
See the [ClassicLink documentation][1] for more information. Defaults false.
* `assign_generated_ipv6_cidr_block` - (Optional) Requests an Amazon-provided IPv6 CIDR
block with a /56 prefix length for the VPC. You cannot specify the range of IP addresses, or
the size of the CIDR block. Default is `false`.
* `tags` - (Optional) A mapping of tags to assign to the resource.
## Attributes Reference
@ -62,6 +65,8 @@ The following attributes are exported:
* `default_network_acl_id` - The ID of the network ACL created by default on VPC creation
* `default_security_group_id` - The ID of the security group created by default on VPC creation
* `default_route_table_id` - The ID of the route table created by default on VPC creation
* `ipv6_association_id` - The association ID for the IPv6 CIDR block.
* `ipv6_cidr_block` - The IPv6 CIDR block.
[1]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html

View File

@ -1209,7 +1209,7 @@
</li>
<li<%= sidebar_current(/^docs-aws-resource-(default|customer|flow|internet-gateway|main-route|network|route-|security-group|subnet|vpc|vpn)/) %>>
<li<%= sidebar_current(/^docs-aws-resource-(default|customer|egress-only-internet-gateway|flow|internet-gateway|main-route|network|route-|security-group|subnet|vpc|vpn)/) %>>
<a href="#">VPC Resources</a>
<ul class="nav nav-visible">
@ -1229,6 +1229,10 @@
<a href="/docs/providers/aws/r/default_security_group.html">aws_default_security_group</a>
</li>
<li<%= sidebar_current("docs-aws-resource-egress-only-internet-gateway") %>>
<a href="/docs/providers/aws/r/egress_only_internet_gateway.html">aws_egress_only_internet_gateway</a>
</li>
<li<%= sidebar_current("docs-aws-resource-flow-log") %>>
<a href="/docs/providers/aws/r/flow_log.html">aws_flow_log</a>
</li>