Skip to content

Commit be52b2d

Browse files
authored
feat: Adding suport for PSC NEGs in terraform-google-lb-http/modules/backend (#539)
1 parent 9bf7720 commit be52b2d

File tree

14 files changed

+347
-6
lines changed

14 files changed

+347
-6
lines changed

build/int.cloudbuild.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,27 @@ steps:
179179
- verify backend-with-iap
180180
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
181181
args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceIap --stage teardown --verbose']
182+
# backend-with-psc-negs example
183+
- id: init backend-with-psc-negs
184+
waitFor:
185+
- teardown backend-with-iap
186+
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
187+
args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceWithPscNeg --stage init --verbose']
188+
- id: apply backend-with-psc-negs
189+
waitFor:
190+
- init backend-with-psc-negs
191+
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
192+
args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceWithPscNeg --stage apply --verbose']
193+
- id: verify backend-with-psc-negs
194+
waitFor:
195+
- apply backend-with-psc-negs
196+
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
197+
args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceWithPscNeg --stage verify --verbose']
198+
- id: teardown backend-with-psc-negs
199+
waitFor:
200+
- verify backend-with-psc-negs
201+
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
202+
args: ['/bin/bash', '-c', 'cft test run TestLbBackendServiceWithPscNeg --stage teardown --verbose']
182203
tags:
183204
- 'ci'
184205
- 'integration'
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
18+
module "producer-network" {
19+
source = "terraform-google-modules/network/google//modules/vpc"
20+
version = "~> 10.0.0"
21+
project_id = var.project_id
22+
network_name = "producer-network"
23+
auto_create_subnetworks = false
24+
}
25+
26+
module "producer-subnet" {
27+
source = "terraform-google-modules/network/google//modules/subnets"
28+
version = "~> 10.0.0"
29+
30+
subnets = [
31+
{
32+
subnet_name = "producer-subnet-a"
33+
subnet_ip = "10.1.2.0/24"
34+
subnet_region = "us-central1"
35+
},
36+
{
37+
subnet_name = "producer-subnet-b"
38+
subnet_ip = "10.1.3.0/24"
39+
subnet_region = "us-central1"
40+
purpose = "PRIVATE_SERVICE_CONNECT"
41+
}
42+
]
43+
44+
network_name = module.producer-network.network_name
45+
project_id = var.project_id
46+
depends_on = [module.producer-network]
47+
}
48+
49+
module "gce-ilb" {
50+
source = "GoogleCloudPlatform/lb-internal/google"
51+
version = "~> 6.0"
52+
project = var.project_id
53+
region = "us-central1"
54+
name = "group2-ilb"
55+
ports = ["80"]
56+
57+
source_tags = ["allow-group1"]
58+
target_tags = ["allow-group2"]
59+
60+
global_access = true
61+
62+
network = module.producer-network.network_name
63+
subnetwork = module.producer-subnet.subnets["us-central1/producer-subnet-a"].name
64+
65+
health_check = {
66+
type = "http"
67+
check_interval_sec = 1
68+
healthy_threshold = 4
69+
timeout_sec = 1
70+
unhealthy_threshold = 5
71+
response = ""
72+
proxy_header = "NONE"
73+
port = 80
74+
port_name = "health-check-port"
75+
request = ""
76+
request_path = "/"
77+
host = "1.2.3.4"
78+
enable_log = false
79+
}
80+
81+
backends = []
82+
depends_on = [module.producer-subnet]
83+
84+
}
85+
86+
resource "google_compute_service_attachment" "minimal_sa" {
87+
project = var.project_id
88+
name = "sa"
89+
region = "us-central1"
90+
enable_proxy_protocol = false
91+
connection_preference = "ACCEPT_AUTOMATIC"
92+
nat_subnets = [module.producer-subnet.subnets["us-central1/producer-subnet-b"].name]
93+
target_service = module.gce-ilb.forwarding_rule
94+
95+
depends_on = [module.gce-ilb]
96+
}
97+
98+
99+
module "psc-neg-network" {
100+
source = "terraform-google-modules/network/google//modules/vpc"
101+
version = "~> 10.0.0"
102+
project_id = var.project_id
103+
network_name = "psc-neg-network"
104+
auto_create_subnetworks = false
105+
}
106+
107+
module "psc-neg-subnet" {
108+
source = "terraform-google-modules/network/google//modules/subnets"
109+
version = "~> 10.0.0"
110+
111+
subnets = [
112+
{
113+
subnet_name = "psc-neg-subnet-a"
114+
subnet_ip = "10.1.2.0/24"
115+
subnet_region = "us-central1"
116+
}
117+
]
118+
119+
network_name = module.psc-neg-network.network_name
120+
project_id = var.project_id
121+
depends_on = [module.psc-neg-network]
122+
}
123+
124+
module "lb-backend-psc-neg" {
125+
source = "terraform-google-modules/lb-http/google//modules/backend"
126+
version = "~> 12.0"
127+
128+
project_id = var.project_id
129+
name = "backend-with-psc-negs"
130+
psc_neg_backends = [{
131+
name = "test-psc-1"
132+
region = "us-central1"
133+
psc_target_service = google_compute_service_attachment.minimal_sa.self_link
134+
network = module.psc-neg-network.network_name
135+
subnetwork = module.psc-neg-subnet.subnets["us-central1/psc-neg-subnet-a"].name
136+
producer_port = "80"
137+
}]
138+
139+
depends_on = [google_compute_service_attachment.minimal_sa]
140+
}
141+
142+
module "lb-frontend" {
143+
source = "terraform-google-modules/lb-http/google//modules/frontend"
144+
version = "~> 12.0"
145+
146+
project_id = var.project_id
147+
name = "global-lb-fe-psc-neg"
148+
url_map_input = module.lb-backend-psc-neg.backend_service_info
149+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
18+
output "project_id" {
19+
value = var.project_id
20+
description = "Project ID of the service"
21+
}
22+
23+
output "psc_negs" {
24+
value = module.lb-backend-psc-neg.psc_negs
25+
description = "Psc Neg created for this load balancer"
26+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
variable "project_id" {
18+
type = string
19+
}

metadata.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ spec:
4242
examples:
4343
- name: backend-with-iap
4444
location: examples/backend-with-iap
45+
- name: backend-with-psc-negs
46+
location: examples/backend-with-psc-negs
4547
- name: cdn-policy
4648
location: examples/cdn-policy
4749
- name: certificate-map
@@ -338,13 +340,13 @@ spec:
338340
roles:
339341
- level: Project
340342
roles:
343+
- roles/run.admin
341344
- roles/iam.serviceAccountUser
342345
- roles/certificatemanager.owner
343346
- roles/vpcaccess.admin
344347
- roles/iam.serviceAccountAdmin
345348
- roles/storage.admin
346349
- roles/compute.admin
347-
- roles/run.admin
348350
services:
349351
- certificatemanager.googleapis.com
350352
- cloudresourcemanager.googleapis.com

modules/backend/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ This module creates `google_compute_backend_service` resource and its dependenci
3131
| port\_name | Name of backend port. The same name should appear in the instance groups referenced by this service. Required when the load balancing scheme is EXTERNAL. | `string` | `"http"` | no |
3232
| project\_id | The project to deploy to, if not set the default provider project is used. | `string` | n/a | yes |
3333
| protocol | The protocol this BackendService uses to communicate with backends. | `string` | `"HTTP"` | no |
34+
| psc\_neg\_backends | The list of Private Service Connect backends which serve the traffic. | <pre>list(object({<br> name = string<br> region = string<br> psc_target_service = string<br> network = string<br> subnetwork = string<br> producer_port = optional(string)<br> }))</pre> | `[]` | no |
3435
| security\_policy | The resource URL for the security policy to associate with the backend service | `string` | `null` | no |
3536
| serverless\_neg\_backends | The list of serverless backend which serves the traffic. | <pre>list(object({<br> region = string<br> type = string // cloud-run, cloud-function, and app-engine<br> service_name = string<br> service_version = optional(string)<br> }))</pre> | `[]` | no |
3637
| session\_affinity | Type of session affinity to use. Possible values are: NONE, CLIENT\_IP, CLIENT\_IP\_PORT\_PROTO, CLIENT\_IP\_PROTO, GENERATED\_COOKIE, HEADER\_FIELD, HTTP\_COOKIE, STRONG\_COOKIE\_AFFINITY. | `string` | `null` | no |
@@ -44,5 +45,6 @@ This module creates `google_compute_backend_service` resource and its dependenci
4445
|------|-------------|
4546
| apphub\_service\_uri | Service URI in CAIS style to be used by Apphub. |
4647
| backend\_service\_info | Host, path and backend service mapping |
48+
| psc\_negs | Private Service Connect backends that were created for this backend service |
4749

4850
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

modules/backend/main.tf

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
locals {
1818
is_backend_bucket = var.backend_bucket_name != null && var.backend_bucket_name != ""
1919
serverless_neg_backends = local.is_backend_bucket ? [] : var.serverless_neg_backends
20+
psc_neg_backends = local.is_backend_bucket ? [] : var.psc_neg_backends
2021
iap_access_members = var.iap_config.enable ? coalesce(var.iap_config.iap_members, []) : []
2122
}
2223

@@ -72,6 +73,13 @@ resource "google_compute_backend_service" "default" {
7273
}
7374
}
7475

76+
dynamic "backend" {
77+
for_each = toset(var.psc_neg_backends)
78+
content {
79+
group = google_compute_region_network_endpoint_group.psc_negs[backend.value.name].id
80+
}
81+
}
82+
7583
dynamic "log_config" {
7684
for_each = var.log_config.enable ? [1] : []
7785
content {
@@ -200,6 +208,29 @@ resource "google_compute_region_network_endpoint_group" "serverless_negs" {
200208
}
201209
}
202210

211+
resource "google_compute_region_network_endpoint_group" "psc_negs" {
212+
for_each = { for psc_neg_backend in local.psc_neg_backends :
213+
psc_neg_backend.name => psc_neg_backend
214+
}
215+
216+
provider = google-beta
217+
project = var.project_id
218+
name = each.key
219+
network_endpoint_type = "PRIVATE_SERVICE_CONNECT"
220+
region = each.value.region
221+
psc_target_service = each.value.psc_target_service
222+
network = each.value.network
223+
subnetwork = each.value.subnetwork
224+
225+
psc_data {
226+
producer_port = try(each.value.producer_port, null)
227+
}
228+
229+
lifecycle {
230+
create_before_destroy = true
231+
}
232+
}
233+
203234
resource "google_compute_health_check" "default" {
204235
provider = google-beta
205236
count = var.health_check != null ? 1 : 0

modules/backend/metadata.yaml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ spec:
3434
examples:
3535
- name: backend-with-iap
3636
location: examples/backend-with-iap
37+
- name: backend-with-psc-negs
38+
location: examples/backend-with-psc-negs
3739
- name: cdn-policy
3840
location: examples/cdn-policy
3941
- name: certificate-map
@@ -180,6 +182,18 @@ spec:
180182
version: ">= 0.13"
181183
spec:
182184
outputExpr: "{\"region\": location, \"service_name\": service_name, \"type\": \"cloud-run\", \"service_version\": \"\"}"
185+
- name: psc_neg_backends
186+
description: The list of Private Service Connect backends which serve the traffic.
187+
varType: |-
188+
list(object({
189+
name = string
190+
region = string
191+
psc_target_service = string
192+
network = string
193+
subnetwork = string
194+
producer_port = optional(string)
195+
}))
196+
defaultValue: []
183197
- name: backend_bucket_name
184198
description: The name of GCS bucket which serves the traffic.
185199
varType: string
@@ -330,17 +344,19 @@ spec:
330344
- backend_service: string
331345
host: string
332346
path: string
347+
- name: psc_negs
348+
description: Private Service Connect backends that were created for this backend service
333349
requirements:
334350
roles:
335351
- level: Project
336352
roles:
337-
- roles/iam.serviceAccountUser
338-
- roles/iam.serviceAccountAdmin
339353
- roles/compute.admin
340354
- roles/storage.admin
341355
- roles/run.admin
342356
- roles/compute.networkAdmin
343357
- roles/iap.admin
358+
- roles/iam.serviceAccountUser
359+
- roles/iam.serviceAccountAdmin
344360
services:
345361
- cloudresourcemanager.googleapis.com
346362
- compute.googleapis.com

modules/backend/outputs.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,10 @@ output "apphub_service_uri" {
4343
)
4444
description = "Service URI in CAIS style to be used by Apphub."
4545
}
46+
47+
output "psc_negs" {
48+
value = !local.is_backend_bucket ? [
49+
for neg_key, neg in google_compute_region_network_endpoint_group.psc_negs : neg.self_link
50+
] : []
51+
description = "Private Service Connect backends that were created for this backend service"
52+
}

0 commit comments

Comments
 (0)