Skip to content

Commit 05bb095

Browse files
Added support for NAT64 when configuring Router NAT (#13522) (#23078)
[upstream:00ab6404f070cb339d540ed2f594eb0afc28b889] Signed-off-by: Modular Magician <[email protected]>
1 parent 5d42a91 commit 05bb095

9 files changed

+552
-1
lines changed

.changelog/13522.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:enhancement
2+
compute: added `source_subnetwork_ip_ranges_to_nat64` and `nat64_subnetwork` fields to `google_compute_router_nat` resource
3+
```
4+
```release-note:enhancement
5+
dns: added `dns64_config` field to `google_dns_policy` resource
6+
```

google/services/compute/resource_compute_router_nat.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,14 @@ This field can only be set when enableDynamicPortAllocation is enabled.`,
351351
Optional: true,
352352
Description: `Minimum number of ports allocated to a VM from this NAT. Defaults to 64 for static port allocation and 32 dynamic port allocation if not set.`,
353353
},
354+
"nat64_subnetwork": {
355+
Type: schema.TypeSet,
356+
Optional: true,
357+
Description: `One or more subnetwork NAT configurations whose traffic should be translated by NAT64 Gateway.
358+
Only used if 'source_subnetwork_ip_ranges_to_nat64' is set to 'LIST_OF_IPV6_SUBNETWORKS'`,
359+
Elem: computeRouterNatNat64SubnetworkSchema(),
360+
Set: computeRouterNatSubnetworkHash,
361+
},
354362
"nat_ip_allocate_option": {
355363
Type: schema.TypeString,
356364
Optional: true,
@@ -389,6 +397,16 @@ the number of resources can be increased/decreased without triggering the 'resou
389397
Elem: computeRouterNatRulesSchema(),
390398
Set: computeRouterNatRulesHash,
391399
},
400+
"source_subnetwork_ip_ranges_to_nat64": {
401+
Type: schema.TypeString,
402+
Optional: true,
403+
ValidateFunc: verify.ValidateEnum([]string{"ALL_IPV6_SUBNETWORKS", "LIST_OF_IPV6_SUBNETWORKS", ""}),
404+
Description: `Specify the Nat option for NAT64, which can take one of the following values:
405+
ALL_IPV6_SUBNETWORKS: All of the IP ranges in every Subnetwork are allowed to Nat.
406+
LIST_OF_IPV6_SUBNETWORKS: A list of Subnetworks are allowed to Nat (specified in the field nat64Subnetwork below).
407+
Note that if this field contains NAT64_ALL_V6_SUBNETWORKS no other Router.Nat section in this region can also enable NAT64 for any Subnetworks in this network.
408+
Other Router.Nat sections can still be present to enable NAT44 only. Possible values: ["ALL_IPV6_SUBNETWORKS", "LIST_OF_IPV6_SUBNETWORKS"]`,
409+
},
392410
"subnetwork": {
393411
Type: schema.TypeSet,
394412
Optional: true,
@@ -484,6 +502,19 @@ sourceIpRangesToNat`,
484502
}
485503
}
486504

505+
func computeRouterNatNat64SubnetworkSchema() *schema.Resource {
506+
return &schema.Resource{
507+
Schema: map[string]*schema.Schema{
508+
"name": {
509+
Type: schema.TypeString,
510+
Required: true,
511+
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
512+
Description: `Self-link of the subnetwork resource that will use NAT64`,
513+
},
514+
},
515+
}
516+
}
517+
487518
func computeRouterNatRulesSchema() *schema.Resource {
488519
return &schema.Resource{
489520
Schema: map[string]*schema.Schema{
@@ -629,6 +660,18 @@ func resourceComputeRouterNatCreate(d *schema.ResourceData, meta interface{}) er
629660
} else if v, ok := d.GetOkExists("subnetwork"); ok || !reflect.DeepEqual(v, subnetworksProp) {
630661
obj["subnetworks"] = subnetworksProp
631662
}
663+
sourceSubnetworkIpRangesToNat64Prop, err := expandNestedComputeRouterNatSourceSubnetworkIpRangesToNat64(d.Get("source_subnetwork_ip_ranges_to_nat64"), d, config)
664+
if err != nil {
665+
return err
666+
} else if v, ok := d.GetOkExists("source_subnetwork_ip_ranges_to_nat64"); !tpgresource.IsEmptyValue(reflect.ValueOf(sourceSubnetworkIpRangesToNat64Prop)) && (ok || !reflect.DeepEqual(v, sourceSubnetworkIpRangesToNat64Prop)) {
667+
obj["sourceSubnetworkIpRangesToNat64"] = sourceSubnetworkIpRangesToNat64Prop
668+
}
669+
nat64SubnetworksProp, err := expandNestedComputeRouterNatNat64Subnetwork(d.Get("nat64_subnetwork"), d, config)
670+
if err != nil {
671+
return err
672+
} else if v, ok := d.GetOkExists("nat64_subnetwork"); ok || !reflect.DeepEqual(v, nat64SubnetworksProp) {
673+
obj["nat64Subnetworks"] = nat64SubnetworksProp
674+
}
632675
minPortsPerVmProp, err := expandNestedComputeRouterNatMinPortsPerVm(d.Get("min_ports_per_vm"), d, config)
633676
if err != nil {
634677
return err
@@ -885,6 +928,12 @@ func resourceComputeRouterNatRead(d *schema.ResourceData, meta interface{}) erro
885928
if err := d.Set("subnetwork", flattenNestedComputeRouterNatSubnetwork(res["subnetworks"], d, config)); err != nil {
886929
return fmt.Errorf("Error reading RouterNat: %s", err)
887930
}
931+
if err := d.Set("source_subnetwork_ip_ranges_to_nat64", flattenNestedComputeRouterNatSourceSubnetworkIpRangesToNat64(res["sourceSubnetworkIpRangesToNat64"], d, config)); err != nil {
932+
return fmt.Errorf("Error reading RouterNat: %s", err)
933+
}
934+
if err := d.Set("nat64_subnetwork", flattenNestedComputeRouterNatNat64Subnetwork(res["nat64Subnetworks"], d, config)); err != nil {
935+
return fmt.Errorf("Error reading RouterNat: %s", err)
936+
}
888937
if err := d.Set("min_ports_per_vm", flattenNestedComputeRouterNatMinPortsPerVm(res["minPortsPerVm"], d, config)); err != nil {
889938
return fmt.Errorf("Error reading RouterNat: %s", err)
890939
}
@@ -977,6 +1026,18 @@ func resourceComputeRouterNatUpdate(d *schema.ResourceData, meta interface{}) er
9771026
} else if v, ok := d.GetOkExists("subnetwork"); ok || !reflect.DeepEqual(v, subnetworksProp) {
9781027
obj["subnetworks"] = subnetworksProp
9791028
}
1029+
sourceSubnetworkIpRangesToNat64Prop, err := expandNestedComputeRouterNatSourceSubnetworkIpRangesToNat64(d.Get("source_subnetwork_ip_ranges_to_nat64"), d, config)
1030+
if err != nil {
1031+
return err
1032+
} else if v, ok := d.GetOkExists("source_subnetwork_ip_ranges_to_nat64"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, sourceSubnetworkIpRangesToNat64Prop)) {
1033+
obj["sourceSubnetworkIpRangesToNat64"] = sourceSubnetworkIpRangesToNat64Prop
1034+
}
1035+
nat64SubnetworksProp, err := expandNestedComputeRouterNatNat64Subnetwork(d.Get("nat64_subnetwork"), d, config)
1036+
if err != nil {
1037+
return err
1038+
} else if v, ok := d.GetOkExists("nat64_subnetwork"); ok || !reflect.DeepEqual(v, nat64SubnetworksProp) {
1039+
obj["nat64Subnetworks"] = nat64SubnetworksProp
1040+
}
9801041
minPortsPerVmProp, err := expandNestedComputeRouterNatMinPortsPerVm(d.Get("min_ports_per_vm"), d, config)
9811042
if err != nil {
9821043
return err
@@ -1290,6 +1351,35 @@ func flattenNestedComputeRouterNatSubnetworkSecondaryIpRangeNames(v interface{},
12901351
return schema.NewSet(schema.HashString, v.([]interface{}))
12911352
}
12921353

1354+
func flattenNestedComputeRouterNatSourceSubnetworkIpRangesToNat64(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1355+
return v
1356+
}
1357+
1358+
func flattenNestedComputeRouterNatNat64Subnetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1359+
if v == nil {
1360+
return v
1361+
}
1362+
l := v.([]interface{})
1363+
transformed := schema.NewSet(computeRouterNatSubnetworkHash, []interface{}{})
1364+
for _, raw := range l {
1365+
original := raw.(map[string]interface{})
1366+
if len(original) < 1 {
1367+
// Do not include empty json objects coming back from the api
1368+
continue
1369+
}
1370+
transformed.Add(map[string]interface{}{
1371+
"name": flattenNestedComputeRouterNatNat64SubnetworkName(original["name"], d, config),
1372+
})
1373+
}
1374+
return transformed
1375+
}
1376+
func flattenNestedComputeRouterNatNat64SubnetworkName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1377+
if v == nil {
1378+
return v
1379+
}
1380+
return tpgresource.ConvertSelfLinkToV1(v.(string))
1381+
}
1382+
12931383
func flattenNestedComputeRouterNatMinPortsPerVm(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
12941384
// Handles the string fixed64 format
12951385
if strVal, ok := v.(string); ok {
@@ -1648,6 +1738,41 @@ func expandNestedComputeRouterNatSubnetworkSecondaryIpRangeNames(v interface{},
16481738
return v, nil
16491739
}
16501740

1741+
func expandNestedComputeRouterNatSourceSubnetworkIpRangesToNat64(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1742+
return v, nil
1743+
}
1744+
1745+
func expandNestedComputeRouterNatNat64Subnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1746+
v = v.(*schema.Set).List()
1747+
l := v.([]interface{})
1748+
req := make([]interface{}, 0, len(l))
1749+
for _, raw := range l {
1750+
if raw == nil {
1751+
continue
1752+
}
1753+
original := raw.(map[string]interface{})
1754+
transformed := make(map[string]interface{})
1755+
1756+
transformedName, err := expandNestedComputeRouterNatNat64SubnetworkName(original["name"], d, config)
1757+
if err != nil {
1758+
return nil, err
1759+
} else if val := reflect.ValueOf(transformedName); val.IsValid() && !tpgresource.IsEmptyValue(val) {
1760+
transformed["name"] = transformedName
1761+
}
1762+
1763+
req = append(req, transformed)
1764+
}
1765+
return req, nil
1766+
}
1767+
1768+
func expandNestedComputeRouterNatNat64SubnetworkName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1769+
f, err := tpgresource.ParseRegionalFieldValue("subnetworks", v.(string), "project", "region", "zone", d, config, true)
1770+
if err != nil {
1771+
return nil, fmt.Errorf("Invalid value for name: %s", err)
1772+
}
1773+
return f.RelativeLink(), nil
1774+
}
1775+
16511776
func expandNestedComputeRouterNatMinPortsPerVm(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
16521777
return v, nil
16531778
}
@@ -2021,6 +2146,8 @@ func resourceComputeRouterNatPatchUpdateEncoder(d *schema.ResourceData, meta int
20212146
"drainNatIps": struct{}{},
20222147
"sourceSubnetworkIpRangesToNat": struct{}{},
20232148
"subnetworks": struct{}{},
2149+
"sourceSubnetworkIpRangesToNat64": struct{}{},
2150+
"nat64Subnetworks": struct{}{},
20242151
"minPortsPerVm": struct{}{},
20252152
"maxPortsPerVm": struct{}{},
20262153
"enableDynamicPortAllocation": struct{}{},

google/services/compute/resource_compute_router_nat_generated_meta.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ fields:
1717
- field: 'max_ports_per_vm'
1818
- field: 'min_ports_per_vm'
1919
- field: 'name'
20+
- field: 'nat64_subnetwork.name'
21+
api_field: 'nat64_subnetworks.name'
2022
- field: 'nat_ip_allocate_option'
2123
- field: 'nat_ips'
2224
- field: 'region'
@@ -31,6 +33,7 @@ fields:
3133
- field: 'rules.match'
3234
- field: 'rules.rule_number'
3335
- field: 'source_subnetwork_ip_ranges_to_nat'
36+
- field: 'source_subnetwork_ip_ranges_to_nat64'
3437
- field: 'subnetwork.name'
3538
api_field: 'subnetworks.name'
3639
- field: 'subnetwork.secondary_ip_range_names'

google/services/compute/resource_compute_router_nat_test.go

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,38 @@ func testAccCheckComputeRouterNatDelete(t *testing.T, n string) resource.TestChe
813813
}
814814
}
815815

816+
func TestAccComputeRouterNat_withNat64Configuration(t *testing.T) {
817+
t.Parallel()
818+
819+
context := map[string]interface{}{
820+
"random_suffix": acctest.RandString(t, 10),
821+
}
822+
823+
acctest.VcrTest(t, resource.TestCase{
824+
PreCheck: func() { acctest.AccTestPreCheck(t) },
825+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
826+
CheckDestroy: testAccCheckComputeRouterNatDestroyProducer(t),
827+
Steps: []resource.TestStep{
828+
{
829+
Config: testAccComputeRouterNatWithNat64Configuration(context),
830+
},
831+
{
832+
ResourceName: "google_compute_router_nat.foobar",
833+
ImportState: true,
834+
ImportStateVerify: true,
835+
},
836+
{
837+
Config: testAccComputeRouterNatWithNat64ConfigurationUpdate(context),
838+
},
839+
{
840+
ResourceName: "google_compute_router_nat.foobar",
841+
ImportState: true,
842+
ImportStateVerify: true,
843+
},
844+
},
845+
})
846+
}
847+
816848
func testAccComputeRouterNatBasic(routerName string) string {
817849
return fmt.Sprintf(`
818850
resource "google_compute_network" "foobar" {
@@ -2063,3 +2095,136 @@ resource "google_compute_router_nat" "foobar" {
20632095
}
20642096
`, testAccComputeRouterNatBaseResourcesWithPrivateNatSubnetworks(routerName, hubName), routerName)
20652097
}
2098+
2099+
func testAccComputeRouterNatWithNat64Configuration(context map[string]interface{}) string {
2100+
return acctest.Nprintf(`
2101+
resource "google_dns_policy" "foobar" {
2102+
name = "tf-test-example-policy%{random_suffix}"
2103+
enable_inbound_forwarding = false
2104+
enable_logging = false
2105+
2106+
dns64_config {
2107+
scope {
2108+
all_queries = true
2109+
}
2110+
}
2111+
networks {
2112+
network_url = google_compute_network.foobar.id
2113+
}
2114+
}
2115+
2116+
resource "google_compute_network" "foobar" {
2117+
name = "tf-test-network%{random_suffix}"
2118+
enable_ula_internal_ipv6 = true
2119+
auto_create_subnetworks = false
2120+
}
2121+
2122+
resource "google_compute_subnetwork" "foobar" {
2123+
name = "tf-test-subnetwork-%{random_suffix}"
2124+
network = google_compute_network.foobar.self_link
2125+
ip_cidr_range = "10.0.0.0/16"
2126+
region = "us-central1"
2127+
}
2128+
2129+
resource "google_compute_subnetwork" "foobar2" {
2130+
name = "tf-test-subnetwork-2-%{random_suffix}"
2131+
network = google_compute_network.foobar.self_link
2132+
ip_cidr_range = "10.182.0.0/20"
2133+
ipv6_access_type = "EXTERNAL"
2134+
stack_type = "IPV4_IPV6"
2135+
region = "us-central1"
2136+
}
2137+
2138+
resource "google_compute_router" "foobar" {
2139+
name = "tf-test-router%{random_suffix}"
2140+
region = google_compute_subnetwork.foobar.region
2141+
network = google_compute_network.foobar.self_link
2142+
bgp {
2143+
asn = 64514
2144+
}
2145+
}
2146+
2147+
resource "google_compute_router_nat" "foobar" {
2148+
name = "tf-test-router-nat%{random_suffix}"
2149+
router = google_compute_router.foobar.name
2150+
region = google_compute_router.foobar.region
2151+
nat_ip_allocate_option = "AUTO_ONLY"
2152+
2153+
source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS"
2154+
subnetwork {
2155+
name = google_compute_subnetwork.foobar.name
2156+
source_ip_ranges_to_nat = ["ALL_IP_RANGES"]
2157+
}
2158+
2159+
source_subnetwork_ip_ranges_to_nat64 = "ALL_IPV6_SUBNETWORKS"
2160+
}
2161+
`, context)
2162+
}
2163+
2164+
func testAccComputeRouterNatWithNat64ConfigurationUpdate(context map[string]interface{}) string {
2165+
return acctest.Nprintf(`
2166+
resource "google_dns_policy" "foobar" {
2167+
name = "tf-test-example-policy%{random_suffix}"
2168+
enable_inbound_forwarding = false
2169+
enable_logging = false
2170+
2171+
dns64_config {
2172+
scope {
2173+
all_queries = true
2174+
}
2175+
}
2176+
networks {
2177+
network_url = google_compute_network.foobar.id
2178+
}
2179+
}
2180+
2181+
resource "google_compute_network" "foobar" {
2182+
name = "tf-test-network%{random_suffix}"
2183+
enable_ula_internal_ipv6 = true
2184+
auto_create_subnetworks = false
2185+
}
2186+
2187+
resource "google_compute_subnetwork" "foobar" {
2188+
name = "tf-test-subnetwork-%{random_suffix}"
2189+
network = google_compute_network.foobar.self_link
2190+
ip_cidr_range = "10.0.0.0/16"
2191+
region = "us-central1"
2192+
}
2193+
2194+
resource "google_compute_subnetwork" "foobar2" {
2195+
name = "tf-test-subnetwork-2-%{random_suffix}"
2196+
network = google_compute_network.foobar.self_link
2197+
ip_cidr_range = "10.182.0.0/20"
2198+
ipv6_access_type = "EXTERNAL"
2199+
stack_type = "IPV4_IPV6"
2200+
region = "us-central1"
2201+
}
2202+
2203+
resource "google_compute_router" "foobar" {
2204+
name = "tf-test-router%{random_suffix}"
2205+
region = google_compute_subnetwork.foobar.region
2206+
network = google_compute_network.foobar.self_link
2207+
bgp {
2208+
asn = 64514
2209+
}
2210+
}
2211+
2212+
resource "google_compute_router_nat" "foobar" {
2213+
name = "tf-test-router-nat%{random_suffix}"
2214+
router = google_compute_router.foobar.name
2215+
region = google_compute_router.foobar.region
2216+
nat_ip_allocate_option = "AUTO_ONLY"
2217+
2218+
source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS"
2219+
subnetwork {
2220+
name = google_compute_subnetwork.foobar.name
2221+
source_ip_ranges_to_nat = ["ALL_IP_RANGES"]
2222+
}
2223+
2224+
source_subnetwork_ip_ranges_to_nat64 = "LIST_OF_IPV6_SUBNETWORKS"
2225+
nat64_subnetwork {
2226+
name = google_compute_subnetwork.foobar2.name
2227+
}
2228+
}
2229+
`, context)
2230+
}

0 commit comments

Comments
 (0)