From 19be54a72fa9d46a3000585213d38916f01927e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Niesiob=C4=99dzki?= Date: Wed, 14 Feb 2024 19:54:32 +0000 Subject: [PATCH] Use Fabric modules when possibile --- .../networking/psc-glb-and-armor/README.md | 30 +- .../networking/psc-glb-and-armor/consumer.tf | 200 +++++++------ .../modules/producer/main.tf | 270 ++++++------------ .../modules/producer/outputs.tf | 4 +- .../modules/producer/variables.tf | 29 +- .../networking/psc-glb-and-armor/outputs.tf | 4 +- .../networking/psc-glb-and-armor/variables.tf | 23 +- 7 files changed, 245 insertions(+), 315 deletions(-) diff --git a/blueprints/networking/psc-glb-and-armor/README.md b/blueprints/networking/psc-glb-and-armor/README.md index d3ef518e..adecfdc0 100644 --- a/blueprints/networking/psc-glb-and-armor/README.md +++ b/blueprints/networking/psc-glb-and-armor/README.md @@ -74,7 +74,7 @@ Before we deploy the architecture, you will need the following information: 4. Copy the following command into a console and replace __[consumer-project-id]__ and __[producer-a-project-id]__ and __[producer-b-project-id]__ with your project’s IDs. Then run the following command to run the terraform script and create all relevant resources for this architecture: - terraform apply -var consumer_project_id=[consumer-project-id] -var producer_a_project_id=[producer-a-project-id] -var producer_b_project_id=[producer-b-project-id] + terraform apply -var consumer_project_id=[consumer-project-id] -var producer_a_project_id=[producer-a-project-id] -var producer_b_project_id=[producer-b-project-id] -var region=[gcp-region] The resource creation will take a few minutes… but when it’s complete, you should see an output stating the command completed successfully with a list of the created resources. @@ -85,13 +85,13 @@ __Congratulations__! You have successfully deployed an HTTP Load Balancer with C You can simply invoke the service by calling Check the default path (producer A): - curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$LB_IP/anything + curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$(terraform output -raw lb_ip)/uuid Specifically call the producer A path: - curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$LB_IP/anything/a/* + curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$(terraform output -raw lb_ip)/a/uuid Specifically call the producer B path: - curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$LB_IP/anything/b/* + curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" -H "Content-Type: application/json" http://$(terraform output -raw lb_ip)/b/uuid ## Cleaning up your environment @@ -106,12 +106,11 @@ The above command will delete the associated resources so there will be no billa | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [consumer_project_id](variables.tf#L17) | The consumer project, in which the GCLB and Cloud Armor should be created. | string | ✓ | | -| [prefix](variables.tf#L22) | Prefix used for resource names. | string | ✓ | | -| [producer_a_project_id](variables.tf#L31) | The producer A project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | string | ✓ | | -| [producer_b_project_id](variables.tf#L36) | The producer B project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | string | ✓ | | -| [project_create](variables.tf#L41) | Create project instead of using an existing one. | bool | | false | -| [region](variables.tf#L47) | The GCP region in which the resources should be deployed. | string | | "europe-west1" | -| [zone](variables.tf#L53) | The GCP zone for the VM. | string | | "europe-west1-b" | +| [producer_a_project_id](variables.tf#L28) | The producer A project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | string | ✓ | | +| [producer_b_project_id](variables.tf#L33) | The producer B project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | string | ✓ | | +| [region](variables.tf#L47) | The GCP region in which the resources should be deployed. | string | ✓ | | +| [prefix](variables.tf#L22) | Prefix used for resource names. | string | | "" | +| [project_create_config](variables.tf#L38) | Create project instead of using an existing one. | object({…}) | | null | ## Outputs @@ -123,12 +122,15 @@ The above command will delete the associated resources so there will be no billa ```hcl module "psc-glb-and-armor-test" { - source = "./fabric/blueprints/networking/psc-glb-and-armor" - prefix = "test" - project_create = true + source = "./fabric/blueprints/networking/psc-glb-and-armor" + prefix = "test" + project_create_config = { + billing_account = var.billing_account_id + } consumer_project_id = "project-1" producer_a_project_id = "project-2" producer_b_project_id = "project-3" + region = "europe-west2" } -# tftest modules=6 resources=57 +# tftest modules=14 resources=57 ``` diff --git a/blueprints/networking/psc-glb-and-armor/consumer.tf b/blueprints/networking/psc-glb-and-armor/consumer.tf index cae72245..39eb6537 100644 --- a/blueprints/networking/psc-glb-and-armor/consumer.tf +++ b/blueprints/networking/psc-glb-and-armor/consumer.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,95 +14,131 @@ * limitations under the License. */ -module "consumer_project" { +module "consumer-project" { source = "../../../modules/project" name = var.consumer_project_id - project_create = var.project_create + project_create = var.project_create_config != null + + billing_account = try(var.project_create_config.billing_account) + parent = try(var.project_create_config.parent) + prefix = var.prefix services = [ "iam.googleapis.com", "compute.googleapis.com", ] } -module "producer_a_project" { - source = "./modules/producer" - producer_project_id = var.producer_a_project_id - project_create = var.project_create +module "producer-a" { + source = "./modules/producer" + consumer_project_id = module.consumer-project.project_id + prefix = var.prefix + producer_project_id = var.producer_a_project_id + project_create_config = var.project_create_config } -module "producer_b_project" { - source = "./modules/producer" - producer_project_id = var.producer_b_project_id - project_create = var.project_create +module "producer-b" { + source = "./modules/producer" + consumer_project_id = module.consumer-project.project_id + prefix = var.prefix + producer_project_id = var.producer_b_project_id + project_create_config = var.project_create_config } -resource "google_compute_region_network_endpoint_group" "psc_neg_a" { - name = "psc-neg-a" - region = var.region - project = module.consumer_project.project_id - network_endpoint_type = "PRIVATE_SERVICE_CONNECT" - psc_target_service = module.producer_a_project.psc_ilb_service_attachment.self_link +module "consumer-vpc" { + source = "../../../modules/net-vpc" - network = "default" - subnetwork = "default" + name = "consumer" + project_id = module.consumer-project.project_id + subnets = [ + { + ip_cidr_range = "10.0.0.0/24" + name = "consumer" + region = var.region + }, + ] } -resource "google_compute_region_network_endpoint_group" "psc_neg_b" { - name = "psc-neg-b" - region = var.region - project = module.consumer_project.project_id - network_endpoint_type = "PRIVATE_SERVICE_CONNECT" - psc_target_service = module.producer_b_project.psc_ilb_service_attachment.self_link - - network = "default" - subnetwork = "default" -} - -resource "google_compute_global_forwarding_rule" "default" { - project = module.consumer_project.project_id - name = "global-rule" - load_balancing_scheme = "EXTERNAL_MANAGED" - target = google_compute_target_http_proxy.default.id - port_range = "80" -} - -resource "google_compute_target_http_proxy" "default" { - project = module.consumer_project.project_id - name = "target-proxy" - description = "a description" - url_map = google_compute_url_map.default.id -} - -resource "google_compute_url_map" "default" { - project = module.consumer_project.project_id - name = "url-map-target-proxy" - description = "A simple URL Map, routing all traffic to the PSC NEG" - default_service = google_compute_backend_service.backend-a.id - - host_rule { - hosts = ["*"] - path_matcher = "allpaths" - } - - path_matcher { - name = "allpaths" - default_service = google_compute_backend_service.backend-a.id - - path_rule { - paths = ["/anything/b/*"] - service = google_compute_backend_service.backend-b.id +module "glb" { + source = "./../../../modules/net-lb-app-ext" + name = "glb" + project_id = module.consumer-project.project_id + use_classic_version = false + backend_service_configs = { + default = { + backends = [ + { backend = "neg-a" } + ] + health_checks = [] + protocol = "HTTPS" + security_policy = google_compute_security_policy.cloud-armor-policy.name } - - path_rule { - paths = ["/anything/a/*"] - service = google_compute_backend_service.backend-a.id + other = { + backends = [ + { backend = "neg-b" } + ] + health_checks = [] + protocol = "HTTPS" + security_policy = google_compute_security_policy.cloud-armor-policy.name + } + } + # with a single serverless NEG the implied default health check is not needed + health_check_configs = {} + neg_configs = { + neg-a = { + psc = { + region = var.region + target_service = module.producer-a.exposed_service_psc_attachment.self_link + network = module.consumer-vpc.id + subnetwork = module.consumer-vpc.subnet_ids["${var.region}/consumer"] + } + } + neg-b = { + psc = { + region = var.region + target_service = module.producer-b.exposed_service_psc_attachment.self_link + network = module.consumer-vpc.id + subnetwork = module.consumer-vpc.subnet_ids["${var.region}/consumer"] + } + } + } + urlmap_config = { + default_service = "default" + host_rules = [{ + hosts = ["*"] + path_matcher = "pathmap" + }] + path_matchers = { + pathmap = { + default_service = "default" + path_rules = [ + { + paths = ["/b/*"] + service = "other" + route_action = { + url_rewrite = { + path_prefix = "/" # rewrite "/b/*" to "/*" + } + } + }, + { + paths = ["/a/*"] + service = "default" + route_action = { + url_rewrite = { + path_prefix = "/" # rewrite "/b/*" to "/*" + } + } + }, + ] + } } } } -resource "google_compute_security_policy" "policy" { + +resource "google_compute_security_policy" "cloud-armor-policy" { provider = google-beta - project = module.consumer_project.project_id + project = module.consumer-project.project_id name = "ddos-protection" adaptive_protection_config { layer_7_ddos_defense_config { @@ -110,29 +146,3 @@ resource "google_compute_security_policy" "policy" { } } } - -resource "google_compute_backend_service" "backend-a" { - provider = google-beta - project = module.consumer_project.project_id - name = "backend-a" - load_balancing_scheme = "EXTERNAL_MANAGED" - protocol = "HTTPS" - backend { - group = google_compute_region_network_endpoint_group.psc_neg_a.id - balancing_mode = "UTILIZATION" - capacity_scaler = 1.0 - } -} - -resource "google_compute_backend_service" "backend-b" { - provider = google-beta - project = module.consumer_project.project_id - name = "backend-b" - load_balancing_scheme = "EXTERNAL_MANAGED" - protocol = "HTTPS" - backend { - group = google_compute_region_network_endpoint_group.psc_neg_b.id - balancing_mode = "UTILIZATION" - capacity_scaler = 1.0 - } -} \ No newline at end of file diff --git a/blueprints/networking/psc-glb-and-armor/modules/producer/main.tf b/blueprints/networking/psc-glb-and-armor/modules/producer/main.tf index 58550b95..c457a106 100644 --- a/blueprints/networking/psc-glb-and-armor/modules/producer/main.tf +++ b/blueprints/networking/psc-glb-and-armor/modules/producer/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,14 @@ * limitations under the License. */ -module "producer_project" { +module "producer-project" { source = "../../../../../modules/project" name = var.producer_project_id - project_create = var.project_create + project_create = var.project_create_config != null + + billing_account = try(var.project_create_config.billing_account) + parent = try(var.project_create_config.parent) + prefix = var.prefix services = [ "iam.googleapis.com", "run.googleapis.com", @@ -25,90 +29,66 @@ module "producer_project" { ] } -resource "google_service_account" "app" { - project = module.producer_project.project_id - account_id = "example-app" - display_name = "Example App Service Account" +module "app" { + source = "../../../../../modules/cloud-run-v2" + + name = "example-app" + project_id = module.producer-project.project_id + region = var.region + containers = { + hello = { + image = "kennethreitz/httpbin:latest" + ports = { + http = { container_port = 80 } + } + } + } + ingress = "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER" + service_account_create = true } -resource "google_cloud_run_service" "app" { - name = "example-app" - location = var.region - project = module.producer_project.project_id +module "producer-ilb" { + source = "../../../../../modules/net-lb-app-int" + name = "example-app" + project_id = module.producer-project.project_id + region = var.region - template { - spec { - containers { - image = "kennethreitz/httpbin:latest" - ports { - container_port = 80 + backend_service_configs = { + default = { + backends = [{ + group = "my-neg" + }] + health_checks = [] + } + } + global_access = true + health_check_configs = {} + neg_configs = { + my-neg = { + cloudrun = { + region = var.region + target_service = { + name = module.app.service_name } } - service_account_name = google_service_account.app.email } } - - autogenerate_revision_name = true - traffic { - percent = 100 - latest_revision = true - } - metadata { - annotations = { - "run.googleapis.com/ingress" = "internal-and-cloud-load-balancing" + protocol = "HTTPS" + ssl_certificates = { + create_configs = { + default = { + # certificate and key could also be read via file() from external files + certificate = tls_self_signed_cert.example.cert_pem + private_key = tls_private_key.example.private_key_pem + } } } -} - -resource "google_compute_region_network_endpoint_group" "neg" { - name = "example-app-neg" - network_endpoint_type = "SERVERLESS" - region = var.region - project = module.producer_project.project_id - cloud_run { - service = google_cloud_run_service.app.name + vpc_config = { + network = module.producer-vpc.self_link + subnetwork = module.producer-vpc.subnets["${var.region}/ilb-subnetwork"].self_link } } -resource "google_compute_forwarding_rule" "psc_ilb_target_service" { - name = "producer-forwarding-rule" - region = var.region - project = module.producer_project.project_id - depends_on = [google_compute_subnetwork.proxy_subnet] - load_balancing_scheme = "INTERNAL_MANAGED" - port_range = "443" - allow_global_access = true - target = google_compute_region_target_https_proxy.default.id - - network = google_compute_network.psc_ilb_network.name - subnetwork = google_compute_subnetwork.ilb_subnetwork.name -} - -resource "google_compute_region_target_https_proxy" "default" { - name = "l7-ilb-target-http-proxy" - provider = google-beta - region = var.region - project = module.producer_project.project_id - url_map = google_compute_region_url_map.default.id - ssl_certificates = [google_compute_region_ssl_certificate.default.id] -} - -resource "google_compute_region_ssl_certificate" "default" { - region = var.region - project = module.producer_project.project_id - name = "my-certificate" - private_key = tls_private_key.example.private_key_pem - certificate = tls_self_signed_cert.example.cert_pem -} - -resource "google_compute_region_url_map" "default" { - name = "l7-ilb-regional-url-map" - provider = google-beta - region = var.region - project = module.producer_project.project_id - default_service = google_compute_region_backend_service.producer_service_backend.id -} - resource "tls_private_key" "example" { algorithm = "RSA" rsa_bits = 2048 @@ -130,114 +110,48 @@ resource "tls_self_signed_cert" "example" { "server_auth", ] } -resource "google_compute_region_backend_service" "producer_service_backend" { - name = "producer-service" - region = var.region - project = module.producer_project.project_id - load_balancing_scheme = "INTERNAL_MANAGED" - protocol = "HTTPS" - backend { - group = google_compute_region_network_endpoint_group.neg.id - balancing_mode = "UTILIZATION" - capacity_scaler = 1.0 - } +module "producer-vpc" { + source = "../../../../../modules/net-vpc" + + project_id = module.producer-project.project_id + name = "psc-ilb-network" + subnets = [ + { + ip_cidr_range = "10.0.0.0/24" + name = "ilb-subnetwork" + region = var.region + }, + ] + subnets_proxy_only = [ + { + ip_cidr_range = "10.0.1.0/24" + name = "l7-ilb-proxy-subnet" + region = var.region + active = true + }, + ] + subnets_psc = [ + { + ip_cidr_range = "10.3.0.0/16" + name = "psc-private-subnetwork" + region = var.region + } + ] } -resource "google_compute_network" "psc_ilb_network" { - name = "psc-ilb-network" - auto_create_subnetworks = false - project = module.producer_project.project_id -} - -resource "google_compute_subnetwork" "ilb_subnetwork" { - name = "ilb-subnetwork" - region = var.region - project = module.producer_project.project_id - - network = google_compute_network.psc_ilb_network.id - ip_cidr_range = "10.0.0.0/24" - - role = "ACTIVE" -} - -# proxy-only subnet -resource "google_compute_subnetwork" "proxy_subnet" { - name = "l7-ilb-proxy-subnet" - provider = google-beta - ip_cidr_range = "10.0.1.0/24" - region = var.region - project = module.producer_project.project_id - purpose = "REGIONAL_MANAGED_PROXY" - role = "ACTIVE" - network = google_compute_network.psc_ilb_network.id -} - -resource "google_compute_subnetwork" "psc_private_subnetwork" { - name = "psc-private-subnetwork" - region = var.region - project = module.producer_project.project_id - - network = google_compute_network.psc_ilb_network.id - ip_cidr_range = "10.3.0.0/16" - purpose = "PRIVATE" - role = "ACTIVE" -} - -resource "google_compute_subnetwork" "psc_ilb_nat" { - name = "psc-ilb-nat" - region = var.region - project = module.producer_project.project_id - - network = google_compute_network.psc_ilb_network.id - purpose = "PRIVATE_SERVICE_CONNECT" - ip_cidr_range = "10.1.0.0/16" -} - -resource "google_compute_subnetwork" "vms" { - name = "vms" - region = var.region - project = module.producer_project.project_id - - network = google_compute_network.psc_ilb_network.id - ip_cidr_range = "10.4.0.0/16" -} - -resource "google_compute_service_attachment" "psc_ilb_service_attachment" { - name = "my-psc-ilb" +resource "google_compute_service_attachment" "exposed-psc-service" { + name = "producer-app" region = var.region - project = module.producer_project.project_id + project = module.producer-project.project_id description = "A service attachment configured with Terraform" enable_proxy_protocol = false - connection_preference = "ACCEPT_AUTOMATIC" - nat_subnets = [google_compute_subnetwork.psc_ilb_nat.id] - target_service = google_compute_forwarding_rule.psc_ilb_target_service.id + connection_preference = "ACCEPT_MANUAL" + nat_subnets = [module.producer-vpc.subnets_psc["${var.region}/psc-private-subnetwork"].id] + target_service = module.producer-ilb.id + consumer_accept_lists { + connection_limit = 10 + project_id_or_num = var.consumer_project_id + } } - -resource "google_service_account" "noop" { - project = module.producer_project.project_id - account_id = "noop-sa" - display_name = "Service Account for NOOP VM" -} - -resource "google_compute_instance" "noop-vm" { - project = module.producer_project.project_id - name = "noop-ilb-vm" - machine_type = "e2-medium" - zone = var.zone - boot_disk { - initialize_params { - image = "debian-cloud/debian-11" - } - } - - network_interface { - network = google_compute_network.psc_ilb_network.id - subnetwork = google_compute_subnetwork.vms.id - } - service_account { - email = google_service_account.noop.email - scopes = [] - } -} \ No newline at end of file diff --git a/blueprints/networking/psc-glb-and-armor/modules/producer/outputs.tf b/blueprints/networking/psc-glb-and-armor/modules/producer/outputs.tf index f912a356..015abcfe 100644 --- a/blueprints/networking/psc-glb-and-armor/modules/producer/outputs.tf +++ b/blueprints/networking/psc-glb-and-armor/modules/producer/outputs.tf @@ -13,6 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -output "psc_ilb_service_attachment" { - value = google_compute_service_attachment.psc_ilb_service_attachment +output "exposed_service_psc_attachment" { + value = google_compute_service_attachment.exposed-psc-service } \ No newline at end of file diff --git a/blueprints/networking/psc-glb-and-armor/modules/producer/variables.tf b/blueprints/networking/psc-glb-and-armor/modules/producer/variables.tf index e9697bd8..356b6706 100644 --- a/blueprints/networking/psc-glb-and-armor/modules/producer/variables.tf +++ b/blueprints/networking/psc-glb-and-armor/modules/producer/variables.tf @@ -14,15 +14,32 @@ * limitations under the License. */ +variable "consumer_project_id" { + description = "The producer project, in which the LB, PSC Service Attachment and Cloud Run service should be created." + type = string +} + +variable "prefix" { + description = "Prefix used for resource names." + type = string + validation { + condition = var.prefix != "" + error_message = "Prefix cannot be empty." + } +} + variable "producer_project_id" { description = "The producer project, in which the LB, PSC Service Attachment and Cloud Run service should be created." type = string } -variable "project_create" { +variable "project_create_config" { description = "Create project instead of using an existing one." - type = bool - default = false + type = object({ + billing_account = string + parent = optional(string) + }) + default = null } variable "region" { @@ -30,9 +47,3 @@ variable "region" { type = string default = "europe-west1" } - -variable "zone" { - description = "The GCP zone for the VM." - type = string - default = "europe-west1-b" -} diff --git a/blueprints/networking/psc-glb-and-armor/outputs.tf b/blueprints/networking/psc-glb-and-armor/outputs.tf index b8e50ed4..8845f1b7 100644 --- a/blueprints/networking/psc-glb-and-armor/outputs.tf +++ b/blueprints/networking/psc-glb-and-armor/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,5 +16,5 @@ output "lb_ip" { description = "Load balancer IP address." - value = google_compute_global_forwarding_rule.default.ip_address + value = module.glb.address } diff --git a/blueprints/networking/psc-glb-and-armor/variables.tf b/blueprints/networking/psc-glb-and-armor/variables.tf index fdbcabf1..fb0f58fb 100644 --- a/blueprints/networking/psc-glb-and-armor/variables.tf +++ b/blueprints/networking/psc-glb-and-armor/variables.tf @@ -1,5 +1,5 @@ /** - * Copyright 2023 Google LLC + * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +22,7 @@ variable "consumer_project_id" { variable "prefix" { description = "Prefix used for resource names." type = string - validation { - condition = var.prefix != "" - error_message = "Prefix cannot be empty." - } + default = "" } variable "producer_a_project_id" { @@ -38,20 +35,16 @@ variable "producer_b_project_id" { type = string } -variable "project_create" { +variable "project_create_config" { description = "Create project instead of using an existing one." - type = bool - default = false + type = object({ + billing_account = string + parent = optional(string) + }) + default = null } variable "region" { description = "The GCP region in which the resources should be deployed." type = string - default = "europe-west1" -} - -variable "zone" { - description = "The GCP zone for the VM." - type = string - default = "europe-west1-b" }