diff --git a/cloudmock/aws/mockec2/subnets.go b/cloudmock/aws/mockec2/subnets.go index d1e59dce4c..0ffa89ef30 100644 --- a/cloudmock/aws/mockec2/subnets.go +++ b/cloudmock/aws/mockec2/subnets.go @@ -260,6 +260,9 @@ func (m *MockEC2) ModifySubnetAttribute(request *ec2.ModifySubnetAttributeInput) defer m.mutex.Unlock() subnet := m.subnets[*request.SubnetId] + if request.AssignIpv6AddressOnCreation != nil { + subnet.main.AssignIpv6AddressOnCreation = request.AssignIpv6AddressOnCreation.Value + } if request.EnableResourceNameDnsAAAARecordOnLaunch != nil { subnet.main.PrivateDnsNameOptionsOnLaunch.EnableResourceNameDnsAAAARecord = request.EnableResourceNameDnsAAAARecordOnLaunch.Value } diff --git a/tests/integration/update_cluster/minimal-ipv6-calico/kubernetes.tf b/tests/integration/update_cluster/minimal-ipv6-calico/kubernetes.tf index ed4e8251eb..6b741bbd74 100644 --- a/tests/integration/update_cluster/minimal-ipv6-calico/kubernetes.tf +++ b/tests/integration/update_cluster/minimal-ipv6-calico/kubernetes.tf @@ -1090,6 +1090,7 @@ resource "aws_security_group_rule" "icmpv6-pmtu-api-elb-__--0" { } resource "aws_subnet" "dualstack-us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" cidr_block = "172.20.32.0/19" enable_resource_name_dns_a_record_on_launch = true @@ -1108,6 +1109,7 @@ resource "aws_subnet" "dualstack-us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "dualstack-us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" cidr_block = "172.20.64.0/19" enable_resource_name_dns_a_record_on_launch = true @@ -1125,6 +1127,7 @@ resource "aws_subnet" "dualstack-us-test-1b-minimal-ipv6-example-com" { } resource "aws_subnet" "us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" enable_dns64 = true enable_resource_name_dns_aaaa_record_on_launch = true @@ -1142,6 +1145,7 @@ resource "aws_subnet" "us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" enable_dns64 = true enable_resource_name_dns_aaaa_record_on_launch = true @@ -1159,6 +1163,7 @@ resource "aws_subnet" "us-test-1b-minimal-ipv6-example-com" { } resource "aws_subnet" "utility-us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" cidr_block = "172.20.0.0/22" enable_resource_name_dns_a_record_on_launch = true @@ -1176,6 +1181,7 @@ resource "aws_subnet" "utility-us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "utility-us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" cidr_block = "172.20.4.0/22" enable_resource_name_dns_a_record_on_launch = true diff --git a/tests/integration/update_cluster/minimal-ipv6-cilium/kubernetes.tf b/tests/integration/update_cluster/minimal-ipv6-cilium/kubernetes.tf index a3149248d7..386dae3e20 100644 --- a/tests/integration/update_cluster/minimal-ipv6-cilium/kubernetes.tf +++ b/tests/integration/update_cluster/minimal-ipv6-cilium/kubernetes.tf @@ -1081,6 +1081,7 @@ resource "aws_security_group_rule" "icmpv6-pmtu-api-elb-__--0" { } resource "aws_subnet" "dualstack-us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" cidr_block = "172.20.32.0/19" enable_resource_name_dns_a_record_on_launch = true @@ -1099,6 +1100,7 @@ resource "aws_subnet" "dualstack-us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "dualstack-us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" cidr_block = "172.20.64.0/19" enable_resource_name_dns_a_record_on_launch = true @@ -1116,6 +1118,7 @@ resource "aws_subnet" "dualstack-us-test-1b-minimal-ipv6-example-com" { } resource "aws_subnet" "us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" enable_dns64 = true enable_resource_name_dns_aaaa_record_on_launch = true @@ -1133,6 +1136,7 @@ resource "aws_subnet" "us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" enable_dns64 = true enable_resource_name_dns_aaaa_record_on_launch = true @@ -1150,6 +1154,7 @@ resource "aws_subnet" "us-test-1b-minimal-ipv6-example-com" { } resource "aws_subnet" "utility-us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" cidr_block = "172.20.0.0/22" enable_resource_name_dns_a_record_on_launch = true @@ -1167,6 +1172,7 @@ resource "aws_subnet" "utility-us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "utility-us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" cidr_block = "172.20.4.0/22" enable_resource_name_dns_a_record_on_launch = true diff --git a/tests/integration/update_cluster/minimal-ipv6/kubernetes.tf b/tests/integration/update_cluster/minimal-ipv6/kubernetes.tf index f5e7d55bde..129ff4a5fa 100644 --- a/tests/integration/update_cluster/minimal-ipv6/kubernetes.tf +++ b/tests/integration/update_cluster/minimal-ipv6/kubernetes.tf @@ -1073,6 +1073,7 @@ resource "aws_security_group_rule" "icmpv6-pmtu-api-elb-__--0" { } resource "aws_subnet" "dualstack-us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" cidr_block = "172.20.32.0/19" enable_resource_name_dns_a_record_on_launch = true @@ -1091,6 +1092,7 @@ resource "aws_subnet" "dualstack-us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "dualstack-us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" cidr_block = "172.20.64.0/19" enable_resource_name_dns_a_record_on_launch = true @@ -1108,6 +1110,7 @@ resource "aws_subnet" "dualstack-us-test-1b-minimal-ipv6-example-com" { } resource "aws_subnet" "us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" enable_dns64 = true enable_resource_name_dns_aaaa_record_on_launch = true @@ -1125,6 +1128,7 @@ resource "aws_subnet" "us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" enable_dns64 = true enable_resource_name_dns_aaaa_record_on_launch = true @@ -1142,6 +1146,7 @@ resource "aws_subnet" "us-test-1b-minimal-ipv6-example-com" { } resource "aws_subnet" "utility-us-test-1a-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1a" cidr_block = "172.20.0.0/22" enable_resource_name_dns_a_record_on_launch = true @@ -1159,6 +1164,7 @@ resource "aws_subnet" "utility-us-test-1a-minimal-ipv6-example-com" { } resource "aws_subnet" "utility-us-test-1b-minimal-ipv6-example-com" { + assign_ipv6_address_on_creation = true availability_zone = "us-test-1b" cidr_block = "172.20.4.0/22" enable_resource_name_dns_a_record_on_launch = true diff --git a/upup/pkg/fi/cloudup/awstasks/subnet.go b/upup/pkg/fi/cloudup/awstasks/subnet.go index 194a699c4f..5902b6d7f3 100644 --- a/upup/pkg/fi/cloudup/awstasks/subnet.go +++ b/upup/pkg/fi/cloudup/awstasks/subnet.go @@ -42,14 +42,15 @@ type Subnet struct { Lifecycle fi.Lifecycle - ID *string - VPC *VPC - AmazonIPv6CIDR *VPCAmazonIPv6CIDRBlock - AvailabilityZone *string - CIDR *string - IPv6CIDR *string - ResourceBasedNaming *bool - Shared *bool + ID *string + VPC *VPC + AmazonIPv6CIDR *VPCAmazonIPv6CIDRBlock + AvailabilityZone *string + CIDR *string + IPv6CIDR *string + ResourceBasedNaming *bool + AssignIPv6AddressOnCreation *bool + Shared *bool Tags map[string]string } @@ -70,6 +71,8 @@ func (a OrderSubnetsById) Less(i, j int) bool { } func (e *Subnet) Find(c *fi.Context) (*Subnet, error) { + e.AssignIPv6AddressOnCreation = fi.PtrTo(e.IPv6CIDR != nil) + subnet, err := e.findEc2Subnet(c) if err != nil { return nil, err @@ -103,6 +106,8 @@ func (e *Subnet) Find(c *fi.Context) (*Subnet, error) { break } + actual.AssignIPv6AddressOnCreation = subnet.AssignIpv6AddressOnCreation + actual.ResourceBasedNaming = fi.PtrTo(aws.StringValue(subnet.PrivateDnsNameOptionsOnLaunch.HostnameType) == ec2.HostnameTypeResourceName) if *actual.ResourceBasedNaming { if fi.ValueOf(actual.CIDR) != "" && !aws.BoolValue(subnet.PrivateDnsNameOptionsOnLaunch.EnableResourceNameDnsARecord) { @@ -288,6 +293,17 @@ func (_ *Subnet) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Subnet) error { } } + if a == nil || changes.AssignIPv6AddressOnCreation != nil { + request := &ec2.ModifySubnetAttributeInput{ + SubnetId: e.ID, + AssignIpv6AddressOnCreation: &ec2.AttributeBooleanValue{Value: e.AssignIPv6AddressOnCreation}, + } + _, err := t.Cloud.EC2().ModifySubnetAttribute(request) + if err != nil { + return fmt.Errorf("error modifying AssignIPv6AddressOnCreation: %w", err) + } + } + if changes.ResourceBasedNaming != nil { hostnameType := ec2.HostnameTypeIpName if *changes.ResourceBasedNaming { @@ -358,6 +374,7 @@ type terraformSubnet struct { CIDR *string `cty:"cidr_block"` IPv6CIDR *string `cty:"ipv6_cidr_block"` IPv6Native *bool `cty:"ipv6_native"` + AssignIPv6AddressOnCreation *bool `cty:"assign_ipv6_address_on_creation"` AvailabilityZone *string `cty:"availability_zone"` EnableDNS64 *bool `cty:"enable_dns64"` EnableResourceNameDNSAAAARecordOnLaunch *bool `cty:"enable_resource_name_dns_aaaa_record_on_launch"` @@ -402,6 +419,9 @@ func (_ *Subnet) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *Su tf.EnableDNS64 = fi.PtrTo(true) tf.IPv6Native = fi.PtrTo(true) } + if fi.ValueOf(e.IPv6CIDR) != "" { + tf.AssignIPv6AddressOnCreation = fi.PtrTo(true) + } if e.ResourceBasedNaming != nil { hostnameType := ec2.HostnameTypeIpName if *e.ResourceBasedNaming { diff --git a/upup/pkg/fi/cloudup/awstasks/subnet_test.go b/upup/pkg/fi/cloudup/awstasks/subnet_test.go index 6b86494e4e..d322dfd581 100644 --- a/upup/pkg/fi/cloudup/awstasks/subnet_test.go +++ b/upup/pkg/fi/cloudup/awstasks/subnet_test.go @@ -118,7 +118,8 @@ func TestSubnetCreate(t *testing.T) { } expected := &ec2.Subnet{ - CidrBlock: aws.String("172.20.1.0/24"), + AssignIpv6AddressOnCreation: aws.Bool(false), + CidrBlock: aws.String("172.20.1.0/24"), PrivateDnsNameOptionsOnLaunch: &ec2.PrivateDnsNameOptionsOnLaunch{ EnableResourceNameDnsAAAARecord: aws.Bool(false), EnableResourceNameDnsARecord: aws.Bool(true), @@ -208,7 +209,8 @@ func TestSubnetCreateIPv6(t *testing.T) { } expected := &ec2.Subnet{ - CidrBlock: aws.String("172.20.1.0/24"), + AssignIpv6AddressOnCreation: aws.Bool(true), + CidrBlock: aws.String("172.20.1.0/24"), Ipv6CidrBlockAssociationSet: []*ec2.SubnetIpv6CidrBlockAssociation{ { AssociationId: aws.String("subnet-cidr-assoc-ipv6-subnet-1"), @@ -306,7 +308,8 @@ func TestSubnetCreateIPv6NetNum(t *testing.T) { } expected := &ec2.Subnet{ - CidrBlock: aws.String("172.20.1.0/24"), + AssignIpv6AddressOnCreation: aws.Bool(true), + CidrBlock: aws.String("172.20.1.0/24"), Ipv6CidrBlockAssociationSet: []*ec2.SubnetIpv6CidrBlockAssociation{ { AssociationId: aws.String("subnet-cidr-assoc-ipv6-subnet-1"), @@ -442,7 +445,8 @@ func TestSharedSubnetCreateDoesNotCreateNew(t *testing.T) { t.Fatalf("Subnet created but then not found") } expected := &ec2.Subnet{ - CidrBlock: aws.String("172.20.1.0/24"), + AssignIpv6AddressOnCreation: aws.Bool(false), + CidrBlock: aws.String("172.20.1.0/24"), PrivateDnsNameOptionsOnLaunch: &ec2.PrivateDnsNameOptionsOnLaunch{ EnableResourceNameDnsAAAARecord: aws.Bool(false), EnableResourceNameDnsARecord: aws.Bool(false),