diff --git a/mmv1/products/compute/Instance.yaml b/mmv1/products/compute/Instance.yaml index 193b3cc410dd..5bce18cd96ba 100644 --- a/mmv1/products/compute/Instance.yaml +++ b/mmv1/products/compute/Instance.yaml @@ -495,6 +495,34 @@ properties: CIDR range for this alias IP range. If left unspecified, the primary range of the subnetwork will be used. + - name: 'aliasIpv6Ranges' + type: Array + description: | + An array of alias IPv6 ranges for this network interface. Can + only be specified for network interfaces on subnet-mode + networks. + min_version: beta + item_type: + type: NestedObject + properties: + - name: 'ipCidrRange' + type: String + description: | + The IP CIDR range represented by this alias IPv6 range. + This IP CIDR range must belong to the specified + subnetwork and cannot contain IP addresses reserved by + system or used by other network interfaces. This range + may be a single IP address (e.g. 2001:db8:1234:5678::), + a netmask (e.g. /96) or a CIDR format string + (e.g. 2001:db8:1234:5678::/96). + - name: 'subnetworkRangeName' + type: String + description: | + Optional subnetwork secondary range name specifying + the secondary range from which to allocate the IP + CIDR range for this alias IPv6 range. If left + unspecified, the primary range of the subnetwork will + be used. - name: 'internalIpv6PrefixLength' type: String description: | diff --git a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl index 3863236b923a..2b33b7cce6b6 100644 --- a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.tmpl @@ -77,6 +77,32 @@ func flattenAliasIpRange(d *schema.ResourceData, ranges []*compute.AliasIpRange, return sorted } +{{ if ne $.TargetVersionName `ga` -}} +func flattenIpv6AliasRange(d *schema.ResourceData, ranges []*compute.AliasIpRange, i int) []map[string]interface{} { + prefix := fmt.Sprintf("network_interface.%d", i) + + configData := []map[string]interface{}{} + for _, item := range d.Get(prefix + ".alias_ipv6_range").([]interface{}) { + configData = append(configData, item.(map[string]interface{})) + } + + apiData := make([]map[string]interface{}, 0, len(ranges)) + for _, ipRange := range ranges { + apiData = append(apiData, map[string]interface{}{ + "ip_cidr_range": ipRange.IpCidrRange, + "subnetwork_range_name": ipRange.SubnetworkRangeName, + }) + } + + //permadiff fix + sorted, err := tpgresource.SortMapsByConfigOrder(configData, apiData, "ip_cidr_range") + if err != nil { + return apiData + } + return sorted +} +{{- end }} + func expandScheduling(v interface{}) (*compute.Scheduling, error) { if v == nil { // We can't set default values for lists. @@ -559,6 +585,9 @@ func flattenNetworkInterfaces(d *schema.ResourceData, config *transport_tpg.Conf "subnetwork_project": subnet.Project, "access_config": ac, "alias_ip_range": flattenAliasIpRange(d, iface.AliasIpRanges, i), + {{ if ne $.TargetVersionName `ga` -}} + "alias_ipv6_range": flattenIpv6AliasRange(d, iface.AliasIpv6Ranges, i), + {{- end }} "nic_type": iface.NicType, "stack_type": iface.StackType, "ipv6_access_config": flattenIpv6AccessConfigs(iface.Ipv6AccessConfigs), @@ -693,6 +722,9 @@ func expandNetworkInterfaces(d tpgresource.TerraformResourceData, config *transp Subnetwork: sf.RelativeLink(), AccessConfigs: expandAccessConfigs(data["access_config"].([]interface{})), AliasIpRanges: expandAliasIpRanges(data["alias_ip_range"].([]interface{})), + {{ if ne $.TargetVersionName `ga` -}} + AliasIpv6Ranges: expandAliasIpRanges(data["alias_ipv6_range"].([]interface{})), + {{- end }} NicType: data["nic_type"].(string), StackType: data["stack_type"].(string), QueueCount: int64(data["queue_count"].(int)), diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl index 1a3e3c2b7d61..cacba3a76d83 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.tmpl @@ -747,6 +747,29 @@ func ResourceComputeInstance() *schema.Resource { }, }, + {{ if ne $.TargetVersionName `ga` -}} + "alias_ipv6_range": { + Type: schema.TypeList, + Optional: true, + Description: `An array of IPv6 alias IP ranges for this network interface.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_cidr_range": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: IpCidrRangeDiffSuppress, + Description: `The IPv6 CIDR range represented by this alias IP range.`, + }, + "subnetwork_range_name": { + Type: schema.TypeString, + Optional: true, + Description: `The subnetwork secondary range name specifying the secondary range from which to allocate the IP CIDR range for this alias IP range.`, + }, + }, + }, + }, + {{- end }} + "stack_type": { Type: schema.TypeString, Optional: true, @@ -2951,6 +2974,56 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } +{{ if ne $.TargetVersionName `ga` -}} + if !updateDuringStop && d.HasChange(prefix+".alias_ipv6_range") { + // Alias IPv6 ranges cannot be updated; they must be removed and then added + // unless you are changing subnetwork/network + if len(instNetworkInterface.AliasIpv6Ranges) > 0 { + ni := &compute.NetworkInterface{ + Fingerprint: instNetworkInterface.Fingerprint, + ForceSendFields: []string{"AliasIpv6Ranges"}, + } + if commonAliasIpv6Ranges := CheckForCommonAliasIpv6(instNetworkInterface, networkInterface); len(commonAliasIpv6Ranges) > 0 { + ni.AliasIpv6Ranges = commonAliasIpv6Ranges + } + op, err := NewClient(config, userAgent).Instances.UpdateNetworkInterface(project, zone, instance.Name, networkName, ni).Do() + if err != nil { + return errwrap.Wrapf("Error removing alias_ipv6_range: {{"{{"}}err{{"}}"}}", err) + } + opErr := ComputeOperationWaitTime(config, op, project, "updating alias ipv6 ranges", userAgent, d.Timeout(schema.TimeoutUpdate)) + if opErr != nil { + return opErr + } + // re-read fingerprint + instance, err = NewClient(config, userAgent).Instances.Get(project, zone, instance.Name).Do() + if err != nil { + return err + } + instNetworkInterface = instance.NetworkInterfaces[i] + } + + networkInterfacePatchObj := &compute.NetworkInterface{ + AliasIpv6Ranges: networkInterface.AliasIpv6Ranges, + Fingerprint: instNetworkInterface.Fingerprint, + } + updateCall := NewClient(config, userAgent).Instances.UpdateNetworkInterface(project, zone, instance.Name, networkName, networkInterfacePatchObj).Do + op, err := updateCall() + if err != nil { + return errwrap.Wrapf("Error updating network interface: {{`{{`}}err{{`}}`}}", err) + } + opErr := ComputeOperationWaitTime(config, op, project, "network interface to update", userAgent, d.Timeout(schema.TimeoutUpdate)) + if opErr != nil { + return opErr + } + // re-read fingerprint + instance, err = NewClient(config, userAgent).Instances.Get(project, zone, instance.Name).Do() + if err != nil { + return err + } + instNetworkInterface = instance.NetworkInterfaces[i] + } +{{- end }} + if !updateDuringStop && d.HasChange(prefix+".stack_type") { networkInterfacePatchObj := &compute.NetworkInterface{ @@ -3097,6 +3170,9 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err Network: networkInterface.Network, Subnetwork: networkInterface.Subnetwork, AliasIpRanges: networkInterface.AliasIpRanges, +{{ if ne $.TargetVersionName `ga` -}} + AliasIpv6Ranges: networkInterface.AliasIpv6Ranges, +{{- end }} } // network_ip can be inferred if not declared. Let's only patch if it's being changed by user @@ -4471,13 +4547,23 @@ func isEmptyServiceAccountBlock(d *schema.ResourceData) bool { // Alias ip ranges cannot be removed and created at the same time. This checks if there are any unchanged alias ip ranges // to be kept in between the PATCH operations on Network Interface func CheckForCommonAliasIp(old, new *compute.NetworkInterface) []*compute.AliasIpRange { + return checkForCommonAliasIpRanges(old.AliasIpRanges, new.AliasIpRanges) +} + +{{ if ne $.TargetVersionName `ga` -}} +func CheckForCommonAliasIpv6(old, new *compute.NetworkInterface) []*compute.AliasIpRange { + return checkForCommonAliasIpRanges(old.AliasIpv6Ranges, new.AliasIpv6Ranges) +} +{{- end }} + +func checkForCommonAliasIpRanges(old, new []*compute.AliasIpRange) []*compute.AliasIpRange { newAliasIpMap := make(map[string]bool) - for _, ipRange := range new.AliasIpRanges { + for _, ipRange := range new { newAliasIpMap[ipRange.IpCidrRange] = true } resultAliasIpRanges := make([]*compute.AliasIpRange, 0) - for _, val := range old.AliasIpRanges { + for _, val := range old { if newAliasIpMap[val.IpCidrRange] { resultAliasIpRanges = append(resultAliasIpRanges, val) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_meta.yaml.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_meta.yaml.tmpl index bc13336e0570..3a0f4ef4c9e7 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_meta.yaml.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_machine_image_meta.yaml.tmpl @@ -151,6 +151,12 @@ fields: field: 'network_interface.alias_ip_range.ip_cidr_range' - api_field: 'networkInterfaces.aliasIpRanges.subnetworkRangeName' field: 'network_interface.alias_ip_range.subnetwork_range_name' +{{- if ne $.TargetVersionName "ga" }} + - api_field: 'networkInterfaces.aliasIpv6Ranges.ipCidrRange' + field: 'network_interface.alias_ipv6_range.ip_cidr_range' + - api_field: 'networkInterfaces.aliasIpv6Ranges.subnetworkRangeName' + field: 'network_interface.alias_ipv6_range.subnetwork_range_name' +{{- end }} - api_field: 'networkInterfaces.internalIpv6PrefixLength' field: 'network_interface.internal_ipv6_prefix_length' - api_field: 'networkInterfaces.ipv6AccessConfigs.externalIpv6' diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template_meta.yaml.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template_meta.yaml.tmpl index dc5e2acb9a88..f4bd6732b378 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template_meta.yaml.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template_meta.yaml.tmpl @@ -156,6 +156,12 @@ fields: field: 'network_interface.alias_ip_range.ip_cidr_range' - api_field: 'networkInterfaces.aliasIpRanges.subnetworkRangeName' field: 'network_interface.alias_ip_range.subnetwork_range_name' +{{- if ne $.TargetVersionName "ga" }} + - api_field: 'networkInterfaces.aliasIpv6Ranges.ipCidrRange' + field: 'network_interface.alias_ipv6_range.ip_cidr_range' + - api_field: 'networkInterfaces.aliasIpv6Ranges.subnetworkRangeName' + field: 'network_interface.alias_ipv6_range.subnetwork_range_name' +{{- end }} - api_field: 'networkInterfaces.internalIpv6PrefixLength' field: 'network_interface.internal_ipv6_prefix_length' - api_field: 'networkInterfaces.ipv6AccessConfigs.externalIpv6' diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_meta.yaml.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_meta.yaml.tmpl index 43bb507ba76a..96b6f910b537 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_meta.yaml.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_meta.yaml.tmpl @@ -156,6 +156,12 @@ fields: field: 'network_interface.alias_ip_range.ip_cidr_range' - api_field: 'networkInterfaces.aliasIpRanges.subnetworkRangeName' field: 'network_interface.alias_ip_range.subnetwork_range_name' +{{- if ne $.TargetVersionName "ga" }} + - api_field: 'networkInterfaces.aliasIpv6Ranges.ipCidrRange' + field: 'network_interface.alias_ipv6_range.ip_cidr_range' + - api_field: 'networkInterfaces.aliasIpv6Ranges.subnetworkRangeName' + field: 'network_interface.alias_ipv6_range.subnetwork_range_name' +{{- end }} - api_field: 'networkInterfaces.internalIpv6PrefixLength' field: 'network_interface.internal_ipv6_prefix_length' - api_field: 'networkInterfaces.ipv6AccessConfigs.externalIpv6' diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl index 9621b914e727..31717ac5f041 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl @@ -626,6 +626,32 @@ Google Cloud KMS. Only one of kms_key_self_link, rsa_encrypted_key and raw_key m }, }, + {{ if ne $.TargetVersionName `ga` -}} + "alias_ipv6_range": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `An array of alias IPv6 ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_cidr_range": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: IpCidrRangeDiffSuppress, + Description: `The IP CIDR range represented by this alias IPv6 range. This IP CIDR range must belong to the specified subnetwork and cannot contain IP addresses reserved by system or used by other network interfaces. At the time of writing only a netmask (e.g. /96) may be supplied, with a CIDR format resulting in an API error.`, + }, + "subnetwork_range_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The subnetwork secondary range name specifying the secondary range from which to allocate the IP CIDR range for this alias IPv6 range. If left unspecified, the primary range of the subnetwork will be used.`, + }, + }, + }, + }, + {{- end }} + "stack_type": { Type: schema.TypeString, Optional: true, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_meta.yaml.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_meta.yaml.tmpl index cb121eabe26b..089b5e3d606d 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_meta.yaml.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_meta.yaml.tmpl @@ -129,6 +129,12 @@ fields: api_field: 'properties.networkInterfaces.aliasIpRanges.ipCidrRange' - field: 'network_interface.alias_ip_range.subnetwork_range_name' api_field: 'properties.networkInterfaces.aliasIpRanges.subnetworkRangeName' +{{- if ne $.TargetVersionName "ga" }} + - field: 'network_interface.alias_ipv6_range.ip_cidr_range' + api_field: 'properties.networkInterfaces.aliasIpv6Ranges.ipCidrRange' + - field: 'network_interface.alias_ipv6_range.subnetwork_range_name' + api_field: 'properties.networkInterfaces.aliasIpv6Ranges.subnetworkRangeName' +{{- end }} - field: 'network_interface.internal_ipv6_prefix_length' api_field: 'properties.networkInterfaces.internalIpv6PrefixLength' - field: 'network_interface.ipv6_access_config.external_ipv6' diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl index d8085d5bcde8..e2de2e866665 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl @@ -286,6 +286,35 @@ func TestAccComputeInstanceTemplate_IPv6(t *testing.T) { }) } +{{ if ne $.TargetVersionName `ga` -}} +func TestAccComputeInstanceTemplate_aliasIpv6Range(t *testing.T) { + t.Parallel() + + var instanceTemplate compute.InstanceTemplate + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceTemplate_aliasIpv6Range(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceTemplateExists( + t, "google_compute_instance_template.foobar", &instanceTemplate), + resource.TestCheckResourceAttr("google_compute_instance_template.foobar", "network_interface.0.alias_ipv6_range.0.ip_cidr_range", "/96"), + ), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} +{{- end }} + func TestAccComputeInstanceTemplate_networkTier(t *testing.T) { t.Parallel() @@ -5665,3 +5694,48 @@ resource "google_compute_instance_template" "foobar" { } `, context) } + + +{{ if ne $.TargetVersionName `ga` -}} +func testAccComputeInstanceTemplate_aliasIpv6Range(suffix string) string { + return fmt.Sprintf(` +resource "google_compute_network" "custom-test" { + name = "tf-test-network-%s" + auto_create_subnetworks = false + enable_ula_internal_ipv6 = true +} + +resource "google_compute_subnetwork" "custom-test" { + name = "tf-test-subnetwork-%s" + region = "us-central1" + network = google_compute_network.custom-test.id + stack_type = "IPV6_ONLY" + ipv6_access_type = "INTERNAL" + + secondary_ip_range { + range_name = "v6-ula" + ip_version = "IPV6" + } +} + +resource "google_compute_instance_template" "foobar" { + name = "tf-test-template-%s" + machine_type = "e2-medium" + + disk { + source_image = "debian-cloud/debian-11" + auto_delete = true + boot = true + } + + network_interface { + subnetwork = google_compute_subnetwork.custom-test.name + stack_type = "IPV6_ONLY" + alias_ipv6_range { + ip_cidr_range = "/96" + } + } +} +`, suffix, suffix, suffix) +} +{{- end }} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.tmpl index 77e15590677a..87a2fe1801b7 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.tmpl @@ -2736,6 +2736,70 @@ func TestAccComputeInstance_secondaryAliasIpRange(t *testing.T) { }) } +{{ if ne $.TargetVersionName `ga` -}} +func TestAccComputeInstance_addAliasIpv6Range(t *testing.T) { + t.Parallel() + + var instance map[string]interface{} + instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + networkName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + subnetName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_aliasIpv6Range_noAlias(networkName, subnetName, instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists(t, "google_compute_instance.foobar", &instance), + ), + }, + { + Config: testAccComputeInstance_aliasIpv6Range(networkName, subnetName, instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists(t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceHasAliasIpv6Range(&instance, "/96"), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{"network_interface.0.alias_ipv6_range.0.ip_cidr_range"}), + }, + }) +} + +func TestAccComputeInstance_removeAliasIpv6Range(t *testing.T) { + t.Parallel() + + var instance map[string]interface{} + instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + networkName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + subnetName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_aliasIpv6Range(networkName, subnetName, instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists(t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceHasAliasIpv6Range(&instance, "/96"), + ), + }, + { + Config: testAccComputeInstance_aliasIpv6Range_noAlias(networkName, subnetName, instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists(t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceNoAliasIpv6Range(&instance), + ), + }, + }, + }) +} +{{- end }} + func TestAccComputeInstance_aliasIpRangeCommonAddresses(t *testing.T) { t.Parallel() @@ -6458,6 +6522,51 @@ func testAccCheckComputeInstanceHasAliasIpRange(instance *map[string]interface{} } } +{{ if ne $.TargetVersionName `ga` -}} +func testAccCheckComputeInstanceHasAliasIpv6Range(instance *map[string]interface{}, iPCidrRange string) resource.TestCheckFunc { + return func(s *terraform.State) error { + nics, _ := (*instance)["networkInterfaces"].([]interface{}) + for _, rawNi := range nics { + ni, ok := rawNi.(map[string]interface{}) + if !ok { + continue + } + ranges, _ := ni["aliasIpv6Ranges"].([]interface{}) + for _, rawRange := range ranges { + aliasIpRange, ok := rawRange.(map[string]interface{}) + if !ok { + continue + } + cidr, _ := aliasIpRange["ipCidrRange"].(string) + if cidr == iPCidrRange || tpgcompute.IpCidrRangeDiffSuppress("ip_cidr_range", cidr, iPCidrRange, nil) { + return nil + } + } + } + + return fmt.Errorf("Alias ipv6 range with cidr %s not present", iPCidrRange) + } +} + +func testAccCheckComputeInstanceNoAliasIpv6Range(instance *map[string]interface{}) resource.TestCheckFunc { + return func(s *terraform.State) error { + nics, _ := (*instance)["networkInterfaces"].([]interface{}) + for _, rawNi := range nics { + ni, ok := rawNi.(map[string]interface{}) + if !ok { + continue + } + ranges, _ := ni["aliasIpv6Ranges"].([]interface{}) + if len(ranges) > 0 { + return fmt.Errorf("Alias ipv6 range still present on instance") + } + + } + return nil + } +} +{{- end }} + func testAccCheckComputeInstanceHasAssignedNatIP(s *terraform.State) error { for _, rs := range s.RootModule().Resources { if rs.Type != "google_compute_instance" { @@ -9926,6 +10035,103 @@ resource "google_compute_instance" "foobar" { `, network, subnet, instance) } +{{ if ne $.TargetVersionName `ga` -}} +func testAccComputeInstance_aliasIpv6Range_noAlias(network, subnet, instance string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_network" "test-network" { + name = "%s" + auto_create_subnetworks = false + enable_ula_internal_ipv6 = true +} + +resource "google_compute_subnetwork" "test-subnetwork" { + name = "%s" + region = "us-central1" + network = google_compute_network.test-network.id + stack_type = "IPV6_ONLY" + ipv6_access_type = "INTERNAL" + + secondary_ip_range { + range_name = "v6-ula" + ip_version = "IPV6" + } +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "e2-medium" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + subnetwork = google_compute_subnetwork.test-subnetwork.self_link + stack_type = "IPV6_ONLY" + } +} +`, network, subnet, instance) +} + +func testAccComputeInstance_aliasIpv6Range(network, subnet, instance string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_network" "test-network" { + name = "%s" + auto_create_subnetworks = false + enable_ula_internal_ipv6 = true +} + +resource "google_compute_subnetwork" "test-subnetwork" { + name = "%s" + region = "us-central1" + network = google_compute_network.test-network.id + stack_type = "IPV6_ONLY" + ipv6_access_type = "INTERNAL" + + secondary_ip_range { + range_name = "v6-ula" + ip_version = "IPV6" + } +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "e2-medium" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + subnetwork = google_compute_subnetwork.test-subnetwork.self_link + stack_type = "IPV6_ONLY" + + alias_ipv6_range { + subnetwork_range_name = "v6-ula" + ip_cidr_range = "/96" + } + } +} +`, network, subnet, instance) +} +{{- end }} + func testAccComputeInstance_secondaryAliasIpRangeUpdate(network, subnet, instance string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { @@ -14009,4 +14215,4 @@ resource "google_compute_instance" "foobar" { } `, context) } -{{- end }} \ No newline at end of file +{{- end }} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl index 6fef422b4f04..7bb8b72f8e35 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl @@ -600,6 +600,32 @@ Google Cloud KMS. Only one of kms_key_self_link, rsa_encrypted_key and raw_key m }, }, + {{ if ne $.TargetVersionName `ga` -}} + "alias_ipv6_range": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `An array of alias IPv6 ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ip_cidr_range": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: IpCidrRangeDiffSuppress, + Description: `The IP CIDR range represented by this alias IPv6 range. This IP CIDR range must belong to the specified subnetwork and cannot contain IP addresses reserved by system or used by other network interfaces. At the time of writing only a netmask (e.g. /96) may be supplied, with a CIDR format resulting in an API error.`, + }, + "subnetwork_range_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The subnetwork secondary range name specifying the secondary range from which to allocate the IP CIDR range for this alias IPv6 range. If left unspecified, the primary range of the subnetwork will be used.`, + }, + }, + }, + }, + {{- end }} + "stack_type": { Type: schema.TypeString, Optional: true, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_meta.yaml.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_meta.yaml.tmpl index 3f5339dcefaa..d88dca520810 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_meta.yaml.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_meta.yaml.tmpl @@ -129,6 +129,12 @@ fields: api_field: 'properties.networkInterfaces.aliasIpRanges.ipCidrRange' - field: 'network_interface.alias_ip_range.subnetwork_range_name' api_field: 'properties.networkInterfaces.aliasIpRanges.subnetworkRangeName' +{{- if ne $.TargetVersionName "ga" }} + - field: 'network_interface.alias_ipv6_range.ip_cidr_range' + api_field: 'properties.networkInterfaces.aliasIpv6Ranges.ipCidrRange' + - field: 'network_interface.alias_ipv6_range.subnetwork_range_name' + api_field: 'properties.networkInterfaces.aliasIpv6Ranges.subnetworkRangeName' +{{- end }} - field: 'network_interface.internal_ipv6_prefix_length' api_field: 'properties.networkInterfaces.internalIpv6PrefixLength' - field: 'network_interface.ipv6_access_config.external_ipv6' diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl index 361423630164..be8caadd4171 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl @@ -198,6 +198,35 @@ func TestAccComputeRegionInstanceTemplate_IPv6(t *testing.T) { }) } +{{ if ne $.TargetVersionName `ga` -}} +func TestAccComputeRegionInstanceTemplate_aliasIpv6Range(t *testing.T) { + t.Parallel() + + var instanceTemplate map[string]interface{} + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeRegionInstanceTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionInstanceTemplate_aliasIpv6Range(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionInstanceTemplateExists( + t, "google_compute_region_instance_template.foobar", &instanceTemplate), + testAccCheckComputeRegionInstanceTemplateHasAliasIpv6Range(&instanceTemplate, "/96"), + ), + }, + { + ResourceName: "google_compute_region_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} +{{- end }} + func TestAccComputeRegionInstanceTemplate_networkTier(t *testing.T) { t.Parallel() @@ -2423,6 +2452,31 @@ func testAccCheckComputeRegionInstanceTemplateContainsLabel(instanceTemplate *ma return nil } } +{{- if ne $.TargetVersionName `ga` }} +func testAccCheckComputeRegionInstanceTemplateHasAliasIpv6Range(instanceTemplate *map[string]interface{}, iPCidrRange string) resource.TestCheckFunc { + return func(s *terraform.State) error { + for _, rawNic := range instanceTemplateNetworkInterfaces(instanceTemplate) { + nic, ok := rawNic.(map[string]interface{}) + if !ok { + continue + } + aliasRanges, _ := nic["aliasIpv6Ranges"].([]interface{}) + for _, rawRange := range aliasRanges { + aliasIpRange, ok := rawRange.(map[string]interface{}) + if !ok { + continue + } + ipRange, _ := aliasIpRange["ipCidrRange"].(string) + if ipRange == iPCidrRange || tpgcompute.IpCidrRangeDiffSuppress("ip_cidr_range", ipRange, iPCidrRange, nil) { + return nil + } + } + } + + return fmt.Errorf("Alias ipv6 range with cidr %s not present", iPCidrRange) + } +} +{{- end }} func testAccCheckComputeRegionInstanceTemplateHasAliasIpRange(instanceTemplate *map[string]interface{}, subnetworkRangeName, iPCidrRange string) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -5271,4 +5325,47 @@ resource "google_compute_region_instance_template" "foobar" { } `, suffix) } + +func testAccComputeRegionInstanceTemplate_aliasIpv6Range(suffix string) string { + return fmt.Sprintf(` +resource "google_compute_network" "custom-test" { + name = "tf-test-network-%s" + auto_create_subnetworks = false + enable_ula_internal_ipv6 = true +} + +resource "google_compute_subnetwork" "custom-test" { + name = "tf-test-subnetwork-%s" + region = "us-central1" + network = google_compute_network.custom-test.id + stack_type = "IPV6_ONLY" + ipv6_access_type = "INTERNAL" + + secondary_ip_range { + range_name = "v6-ula" + ip_version = "IPV6" + } +} + +resource "google_compute_region_instance_template" "foobar" { + name = "tf-test-template-%s" + machine_type = "e2-medium" + region = "us-central1" + + disk { + source_image = "debian-cloud/debian-11" + auto_delete = true + boot = true + } + + network_interface { + subnetwork = google_compute_subnetwork.custom-test.name + stack_type = "IPV6_ONLY" + alias_ipv6_range { + ip_cidr_range = "/96" + } + } +} +`, suffix, suffix, suffix) +} {{- end }} diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index 3a74b1fefc1a..ef349f025174 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -479,6 +479,10 @@ is desired, you will need to modify your state file manually using array of alias IP ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). +* `alias_ipv6_range` - (Optional) [Beta] An + array of alias IPv6 ranges for this network interface. Can only be specified for network + interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). + * `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET, IDPF, MRDMA, IRDMA, IDPF * `network_attachment` - (Optional) The URL of the network attachment that this interface should connect to in the following format: `projects/{projectNumber}/regions/{region_name}/networkAttachments/{network_attachment_name}`. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_from_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_from_template.html.markdown index e5ba14b0ea69..e12b8a43fa9f 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_from_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_from_template.html.markdown @@ -83,6 +83,7 @@ are marked [Attributes as Blocks](/docs/configuration/attr-as-blocks.html): * `service_account` * `scratch_disk` * `network_interface.alias_ip_range` +* `network_interface.alias_ipv6_range` [Beta] * `network_interface.access_config` ## Attributes Reference diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index 200564aed15d..652037d5555b 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -600,6 +600,10 @@ The following arguments are supported: array of alias IP ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). +* `alias_ipv6_range` - (Optional) [Beta] An + array of alias IPv6 ranges for this network interface. Can only be specified for network + interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). + * `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET, MRDMA, IRDMA, IDPF. * `igmp_query` - (Optional) Indicates whether igmp query is enabled on the network interface or not. If enabled, also indicates the version of IGMP supported. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown index e8596de55e6f..9029da4c7196 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown @@ -569,6 +569,10 @@ The following arguments are supported: array of alias IP ranges for this network interface. Can only be specified for network interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). +* `alias_ipv6_range` - (Optional) [Beta] An + array of alias IPv6 ranges for this network interface. Can only be specified for network + interfaces on subnet-mode networks. Structure [documented below](#nested_alias_ip_range). + * `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET, MRDMA, IRDMA, IDPF. * `network_attachment` - (Optional) The URL of the network attachment that this interface should connect to in the following format: projects/{projectNumber}/regions/{region_name}/networkAttachments/{network_attachment_name}.