Skip to content

Commit 0854b1f

Browse files
authored
add support for inter-VPC communications in router_nat resource (#9007)
* add support for type field in router_nat resource * fixing existing tests by sending default_value in the new type field * adding support for sourceNatActiveRanges to rulesAction field * adding support for sourceNatDrainRanges to rulesAction field * enhancing doc test to use private inter vpc
1 parent a6650bd commit 0854b1f

File tree

5 files changed

+460
-3
lines changed

5 files changed

+460
-3
lines changed

mmv1/products/compute/RouterNat.yaml

+60-1
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,18 @@ examples:
9191
address_name1: 'nat-address1'
9292
address_name2: 'nat-address2'
9393
address_name3: 'nat-address3'
94+
- !ruby/object:Provider::Terraform::Examples
95+
name: 'router_nat_private'
96+
primary_resource_id: 'nat_type'
97+
skip_test: true
98+
min_version: beta
99+
vars:
100+
router_name: 'my-router'
101+
nat_name: 'my-router-nat'
102+
network_name: 'my-network'
103+
subnet_name: 'my-subnetwork'
104+
hub_name: 'my-hub'
105+
spoke_name: 'my-spoke'
94106
custom_code: !ruby/object:Provider::Terraform::CustomCode
95107
constants: 'templates/terraform/constants/router_nat.go.erb'
96108
custom_diff: [
@@ -128,7 +140,7 @@ properties:
128140
function: 'verify.ValidateRFC1035Name(2, 63)'
129141
- !ruby/object:Api::Type::Enum
130142
name: 'natIpAllocateOption'
131-
required: true
143+
required: false
132144
description: |
133145
How external IPs should be allocated for this NAT. Valid values are
134146
`AUTO_ONLY` for only allowing NAT IPs allocated by Google Cloud
@@ -368,10 +380,57 @@ properties:
368380
description:
369381
'A reference to an address associated with this NAT'
370382
custom_expand: 'templates/terraform/custom_expand/array_resourceref_with_validation.go.erb'
383+
- !ruby/object:Api::Type::Array
384+
name: 'sourceNatActiveRanges'
385+
min_version: beta
386+
description: |
387+
A list of URLs of the subnetworks used as source ranges for this NAT Rule.
388+
These subnetworks must have purpose set to PRIVATE_NAT.
389+
This field is used for private NAT.
390+
is_set: true
391+
set_hash_func: computeRouterNatRulesSubnetHash
392+
custom_flatten: 'templates/terraform/custom_flatten/nat_rules_subnets_set.erb'
393+
item_type: !ruby/object:Api::Type::ResourceRef
394+
name: 'subnet'
395+
resource: 'Subnetwork'
396+
imports: 'selfLink'
397+
description:
398+
'A reference to a subnetwork address associated with this NAT'
399+
custom_expand: 'templates/terraform/custom_expand/array_resourceref_with_validation.go.erb'
400+
- !ruby/object:Api::Type::Array
401+
name: 'sourceNatDrainRanges'
402+
min_version: beta
403+
description: |
404+
A list of URLs of subnetworks representing source ranges to be drained.
405+
This is only supported on patch/update, and these subnetworks must have previously been used as active ranges in this NAT Rule.
406+
This field is used for private NAT.
407+
is_set: true
408+
set_hash_func: computeRouterNatRulesSubnetHash
409+
custom_flatten: 'templates/terraform/custom_flatten/nat_rules_subnets_set.erb'
410+
item_type: !ruby/object:Api::Type::ResourceRef
411+
name: 'subnet'
412+
resource: 'Subnetwork'
413+
imports: 'selfLink'
414+
description:
415+
'A reference to a subnetwork address associated with this NAT'
416+
custom_expand: 'templates/terraform/custom_expand/array_resourceref_with_validation.go.erb'
371417
- !ruby/object:Api::Type::Boolean
372418
name: enableEndpointIndependentMapping
373419
description: |
374420
Specifies if endpoint independent mapping is enabled. This is enabled by default. For more information
375421
see the [official documentation](https://cloud.google.com/nat/docs/overview#specs-rfcs).
376422
default_value: true
377423
send_empty_value: true
424+
- !ruby/object:Api::Type::Enum
425+
name: 'type'
426+
immutable: true
427+
min_version: beta
428+
description: |
429+
Indicates whether this NAT is used for public or private IP translation.
430+
If unspecified, it defaults to PUBLIC.
431+
If `PUBLIC` NAT used for public IP translation.
432+
If `PRIVATE` NAT used for private IP translation.
433+
values:
434+
- :PUBLIC
435+
- :PRIVATE
436+
default_value: :PUBLIC

mmv1/templates/terraform/constants/router_nat.go.erb

+37-1
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,12 @@ func computeRouterNatIPsHash(v interface{}) int {
9898
return schema.HashString(tpgresource.GetResourceNameFromSelfLink(val))
9999
}
100100

101+
<% unless version == 'ga' -%>
102+
func computeRouterNatRulesSubnetHash(v interface{}) int {
103+
return computeRouterNatIPsHash(v)
104+
}
105+
<% end -%>
106+
101107
func computeRouterNatRulesHash(v interface{}) int {
102108
obj := v.(map[string]interface{})
103109
ruleNumber := obj["rule_number"].(int)
@@ -112,6 +118,12 @@ func computeRouterNatRulesHash(v interface{}) int {
112118

113119
sourceNatActiveIpHash := 0
114120
sourceNatDrainIpHash := 0
121+
<% unless version == 'ga' -%>
122+
sourceNatActiveRangeHash := 0
123+
sourceNatDrainRangeHash := 0
124+
<% end -%>
125+
routerNatRulesHash := 0
126+
115127
if obj["action"] != nil {
116128
actions := obj["action"].([]interface{})
117129
if len(actions) != 0 && actions[0] != nil {
@@ -134,8 +146,32 @@ func computeRouterNatRulesHash(v interface{}) int {
134146
sourceNatDrainIpHash += schema.HashString(sourceNatDrainIpStr)
135147
}
136148
}
149+
150+
<% unless version == 'ga' -%>
151+
sourceNatActiveRanges := action["source_nat_active_ranges"]
152+
if sourceNatActiveRanges != nil {
153+
sourceNatActiveRangesSet := sourceNatActiveRanges.(*schema.Set)
154+
for _, sourceNatActiveRange := range sourceNatActiveRangesSet.List() {
155+
sourceNatActiveRangeStr := fmt.Sprintf("source_nat_active_ranges-%d", computeRouterNatRulesSubnetHash(sourceNatActiveRange.(string)))
156+
sourceNatActiveRangeHash += schema.HashString(sourceNatActiveRangeStr)
157+
}
158+
}
159+
160+
sourceNatDrainRanges := action["source_nat_drain_ranges"]
161+
if sourceNatDrainRanges != nil {
162+
sourceNatDrainRangesSet := sourceNatDrainRanges.(*schema.Set)
163+
for _, sourceNatDrainRange := range sourceNatDrainRangesSet.List() {
164+
sourceNatDrainRangeStr := fmt.Sprintf("source_nat_drain_ranges-%d", computeRouterNatRulesSubnetHash(sourceNatDrainRange.(string)))
165+
sourceNatDrainRangeHash += schema.HashString(sourceNatDrainRangeStr)
166+
}
167+
}
168+
<% end -%>
137169
}
138170
}
139171

140-
return ruleNumber + descriptionHash + schema.HashString(match) + sourceNatActiveIpHash + sourceNatDrainIpHash
172+
routerNatRulesHash = ruleNumber + descriptionHash + schema.HashString(match) + sourceNatActiveIpHash + sourceNatDrainIpHash
173+
<% unless version == 'ga' -%>
174+
routerNatRulesHash += sourceNatActiveRangeHash + sourceNatDrainRangeHash
175+
<% end -%>
176+
return routerNatRulesHash
141177
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
2+
if v == nil {
3+
return v
4+
}
5+
return schema.NewSet(computeRouterNatRulesSubnetHash, tpgresource.ConvertStringArrToInterface(tpgresource.ConvertAndMapStringArr(v.([]interface{}), tpgresource.ConvertSelfLinkToV1)))
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
resource "google_compute_network" "net" {
2+
provider = google-beta
3+
4+
name = "<%= ctx[:vars]['network_name'] %>"
5+
}
6+
7+
resource "google_compute_subnetwork" "subnet" {
8+
provider = google-beta
9+
10+
name = "<%= ctx[:vars]['subnet_name'] %>"
11+
network = google_compute_network.net.id
12+
ip_cidr_range = "10.0.0.0/16"
13+
region = "us-central1"
14+
purpose = "PRIVATE_NAT"
15+
}
16+
17+
resource "google_compute_router" "router" {
18+
provider = google-beta
19+
20+
name = "<%= ctx[:vars]['router_name'] %>"
21+
region = google_compute_subnetwork.subnet.region
22+
network = google_compute_network.net.id
23+
}
24+
25+
resource "google_network_connectivity_hub" "hub" {
26+
provider = google-beta
27+
28+
name = "<%= ctx[:vars]['hub_name'] %>"
29+
description = "vpc hub for inter vpc nat"
30+
}
31+
32+
resource "google_network_connectivity_spoke" "spoke" {
33+
provider = google-beta
34+
35+
name = "<%= ctx[:vars]['spoke_name'] %>"
36+
location = "global"
37+
description = "vpc spoke for inter vpc nat"
38+
hub = google_network_connectivity_hub.hub.id
39+
linked_vpc_network {
40+
exclude_export_ranges = [
41+
"198.51.100.0/24",
42+
"10.10.0.0/16"
43+
]
44+
uri = google_compute_network.net.self_link
45+
}
46+
}
47+
48+
resource "google_compute_router_nat" "<%= ctx[:primary_resource_id] %>" {
49+
provider = google-beta
50+
51+
name = "<%= ctx[:vars]['nat_name'] %>"
52+
router = google_compute_router.router.name
53+
region = google_compute_router.router.region
54+
source_subnetwork_ip_ranges_to_nat = "LIST_OF_SUBNETWORKS"
55+
enable_dynamic_port_allocation = false
56+
enable_endpoint_independent_mapping = false
57+
min_ports_per_vm = 32
58+
type = "PRIVATE"
59+
subnetwork {
60+
name = google_compute_subnetwork.subnet.id
61+
source_ip_ranges_to_nat = ["ALL_IP_RANGES"]
62+
}
63+
rules {
64+
rule_number = 100
65+
description = "rule for private nat"
66+
match = "nexthop.hub == \"//networkconnectivity.googleapis.com/projects/acm-test-proj-123/locations/global/hubs/<%= ctx[:vars]['hub_name'] %>\""
67+
action {
68+
source_nat_active_ranges = [
69+
google_compute_subnetwork.subnet.self_link
70+
]
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)