provider/aws: Allow IPv6/IPv4 addresses to coexist

Fix an issue when trying to get a public IPv4 address and a public IPv6
address that results in the following error:

    Error launching source instance: InvalidParameterCombination:
    Network interfaces and an instance-level IPv6 address count may not
    be specified on the same request

To fix, in situations where we want a IPv6 addresses AND we need to
manually specify network interfaces on the instance, create the IPv6
addresses on the network interface that we're creating rather than on
the instance itself.

Fixes #13250
pull/13702/head
Bryan Burgers 9 years ago
parent 15a5a84cd1
commit 7fac1ab1f6

@ -408,6 +408,8 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error {
ImageId: instanceOpts.ImageID,
InstanceInitiatedShutdownBehavior: instanceOpts.InstanceInitiatedShutdownBehavior,
InstanceType: instanceOpts.InstanceType,
Ipv6AddressCount: instanceOpts.Ipv6AddressCount,
Ipv6Addresses: instanceOpts.Ipv6Addresses,
KeyName: instanceOpts.KeyName,
MaxCount: aws.Int64(int64(1)),
MinCount: aws.Int64(int64(1)),
@ -420,30 +422,13 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error {
UserData: instanceOpts.UserData64,
}
ipv6Count, ipv6CountOk := d.GetOk("ipv6_address_count")
ipv6Address, ipv6AddressOk := d.GetOk("ipv6_addresses")
_, ipv6CountOk := d.GetOk("ipv6_address_count")
_, ipv6AddressOk := d.GetOk("ipv6_addresses")
if ipv6AddressOk && ipv6CountOk {
return fmt.Errorf("Only 1 of `ipv6_address_count` or `ipv6_addresses` can be specified")
}
if ipv6CountOk {
runOpts.Ipv6AddressCount = aws.Int64(int64(ipv6Count.(int)))
}
if ipv6AddressOk {
ipv6Addresses := make([]*ec2.InstanceIpv6Address, len(ipv6Address.([]interface{})))
for _, address := range ipv6Address.([]interface{}) {
ipv6Address := &ec2.InstanceIpv6Address{
Ipv6Address: aws.String(address.(string)),
}
ipv6Addresses = append(ipv6Addresses, ipv6Address)
}
runOpts.Ipv6Addresses = ipv6Addresses
}
restricted := meta.(*AWSClient).IsGovCloud() || meta.(*AWSClient).IsChinaCloud()
if !restricted {
tagsSpec := make([]*ec2.TagSpecification, 0)
@ -1202,6 +1187,23 @@ func buildNetworkInterfaceOpts(d *schema.ResourceData, groups []*string, nInterf
ni.PrivateIpAddress = aws.String(v.(string))
}
if v, ok := d.GetOk("ipv6_address_count"); ok {
ni.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)
}
ni.Ipv6Addresses = ipv6Addresses
}
if v := d.Get("vpc_security_group_ids").(*schema.Set); v.Len() > 0 {
for _, v := range v.List() {
ni.Groups = append(ni.Groups, aws.String(v.(string)))
@ -1436,6 +1438,8 @@ type awsInstanceOpts struct {
ImageID *string
InstanceInitiatedShutdownBehavior *string
InstanceType *string
Ipv6AddressCount *int64
Ipv6Addresses []*ec2.InstanceIpv6Address
KeyName *string
NetworkInterfaces []*ec2.InstanceNetworkInterfaceSpecification
Placement *ec2.Placement
@ -1533,6 +1537,23 @@ func buildAwsInstanceOpts(
opts.SecurityGroups = groups
}
if v, ok := d.GetOk("ipv6_address_count"); ok {
opts.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)
}
opts.Ipv6Addresses = ipv6Addresses
}
if v := d.Get("vpc_security_group_ids").(*schema.Set); v.Len() > 0 {
for _, v := range v.List() {
opts.SecurityGroupIDs = append(opts.SecurityGroupIDs, aws.String(v.(string)))

@ -538,6 +538,29 @@ func TestAccAWSInstance_ipv6AddressCountAndSingleAddressCausesError(t *testing.T
})
}
func TestAccAWSInstance_ipv6_supportAddressCountWithIpv4(t *testing.T) {
var v ec2.Instance
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckInstanceDestroy,
Steps: []resource.TestStep{
{
Config: testAccInstanceConfigIpv6SupportWithIpv4,
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
@ -1463,6 +1486,38 @@ resource "aws_instance" "foo" {
}
`
const testAccInstanceConfigIpv6SupportWithIpv4 = `
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}"
associate_public_ip_address = true
ipv6_address_count = 1
tags {
Name = "tf-ipv6-instance-acc-test"
}
}
`
const testAccInstanceConfigMultipleRegions = `
provider "aws" {
alias = "west"

Loading…
Cancel
Save