From 15ae95df90cd1ad5a2c100c5dabe68916d3748e5 Mon Sep 17 00:00:00 2001 From: Alejandro Leal Date: Fri, 23 Jun 2023 00:14:02 -0400 Subject: [PATCH 01/16] Fixing typos - modules/organization/variables.tf - modules/organization/README.md - blueprints/data-solutions/shielded-folder/main.tf --- blueprints/data-solutions/shielded-folder/main.tf | 2 +- modules/organization/README.md | 2 +- modules/organization/variables.tf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/blueprints/data-solutions/shielded-folder/main.tf b/blueprints/data-solutions/shielded-folder/main.tf index 52fa0db2ec..3868ec96ce 100644 --- a/blueprints/data-solutions/shielded-folder/main.tf +++ b/blueprints/data-solutions/shielded-folder/main.tf @@ -121,7 +121,7 @@ module "vpc-sc" { service_perimeters_regular = { shielded = { # Move `spec` definition to `status` and comment `use_explicit_dry_run_spec` variable to enforce VPC-SC configuration - # Before enforing configuration check logs and create Access Level, Ingress/Egress policy as needed + # Before enforcing configuration check logs and create Access Level, Ingress/Egress policy as needed status = null spec = { diff --git a/modules/organization/README.md b/modules/organization/README.md index 585847d028..6286f3f3f8 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -491,7 +491,7 @@ module "org" { | [network_tags](variables.tf#L159) | Network tags by key name. If `id` is provided, key creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} | | [org_policies](variables.tf#L181) | Organization policies applied to this organization keyed by policy name. | map(object({…})) | | {} | | [org_policies_data_path](variables.tf#L208) | Path containing org policies in YAML format. | string | | null | -| [org_policy_custom_constraints](variables.tf#L214) | Organization policiy custom constraints keyed by constraint name. | map(object({…})) | | {} | +| [org_policy_custom_constraints](variables.tf#L214) | Organization policy custom constraints keyed by constraint name. | map(object({…})) | | {} | | [org_policy_custom_constraints_data_path](variables.tf#L228) | Path containing org policy custom constraints in YAML format. | string | | null | | [tag_bindings](variables.tf#L243) | Tag bindings for this organization, in key => tag value id format. | map(string) | | null | | [tags](variables.tf#L249) | Tags by key name. If `id` is provided, key or value creation is skipped. The `iam` attribute behaves like the similarly named one at module level. | map(object({…})) | | {} | diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 619056a0af..524b6588ff 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -212,7 +212,7 @@ variable "org_policies_data_path" { } variable "org_policy_custom_constraints" { - description = "Organization policiy custom constraints keyed by constraint name." + description = "Organization policy custom constraints keyed by constraint name." type = map(object({ display_name = optional(string) description = optional(string) From ad25b1a31c60beaf156a55c2b4efe2d265d732b5 Mon Sep 17 00:00:00 2001 From: Miren Esnaola Date: Fri, 23 Jun 2023 12:08:15 +0200 Subject: [PATCH 02/16] Added validation for edge_availability_domain value --- modules/net-vlan-attachment/README.md | 14 +++++++------- modules/net-vlan-attachment/variables.tf | 6 +++++- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/modules/net-vlan-attachment/README.md b/modules/net-vlan-attachment/README.md index f324a036d0..6c3fb92cd4 100644 --- a/modules/net-vlan-attachment/README.md +++ b/modules/net-vlan-attachment/README.md @@ -503,16 +503,16 @@ module "example-va-b" { | [description](variables.tf#L35) | VLAN attachment description. | string | ✓ | | | [name](variables.tf#L52) | The common resources name, used after resource type prefix and suffix. | string | ✓ | | | [network](variables.tf#L57) | The VPC name to which resources are associated to. | string | ✓ | | -| [peer_asn](variables.tf#L70) | The on-premises underlay router ASN. | string | ✓ | | -| [project_id](variables.tf#L75) | The project id where resources are created. | string | ✓ | | -| [region](variables.tf#L80) | The region where resources are created. | string | ✓ | | -| [router_config](variables.tf#L85) | Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router. | object({…}) | ✓ | | +| [peer_asn](variables.tf#L74) | The on-premises underlay router ASN. | string | ✓ | | +| [project_id](variables.tf#L79) | The project id where resources are created. | string | ✓ | | +| [region](variables.tf#L84) | The region where resources are created. | string | ✓ | | +| [router_config](variables.tf#L89) | Cloud Router configuration for the VPN. If you want to reuse an existing router, set create to false and use name to specify the desired router. | object({…}) | ✓ | | | [admin_enabled](variables.tf#L17) | Whether the VLAN attachment is enabled. | bool | | true | | [dedicated_interconnect_config](variables.tf#L23) | Partner interconnect configuration. | object({…}) | | null | | [ipsec_gateway_ip_ranges](variables.tf#L40) | IPSec Gateway IP Ranges. | map(string) | | {} | | [mtu](variables.tf#L46) | The MTU associated to the VLAN attachment (1440 / 1500). | number | | 1500 | -| [partner_interconnect_config](variables.tf#L62) | Partner interconnect configuration. | object({…}) | | null | -| [vlan_tag](variables.tf#L106) | The VLAN id to be used for this VLAN attachment. | number | | null | -| [vpn_gateways_ip_range](variables.tf#L112) | The IP range (cidr notation) to be used for the GCP VPN gateways. If null IPSec over Interconnect is not enabled. | string | | null | +| [partner_interconnect_config](variables.tf#L62) | Partner interconnect configuration. | object({…}) | | null | +| [vlan_tag](variables.tf#L110) | The VLAN id to be used for this VLAN attachment. | number | | null | +| [vpn_gateways_ip_range](variables.tf#L116) | The IP range (cidr notation) to be used for the GCP VPN gateways. If null IPSec over Interconnect is not enabled. | string | | null | diff --git a/modules/net-vlan-attachment/variables.tf b/modules/net-vlan-attachment/variables.tf index dacc3b4d7d..941003f923 100644 --- a/modules/net-vlan-attachment/variables.tf +++ b/modules/net-vlan-attachment/variables.tf @@ -62,8 +62,12 @@ variable "network" { variable "partner_interconnect_config" { description = "Partner interconnect configuration." type = object({ - edge_availability_domain = optional(string, "AVAILABILITY_DOMAIN_ANY") + edge_availability_domain = string }) + validation { + condition = var.partner_interconnect_config == null ? true : contains(["AVAILABILITY_DOMAIN_1", "AVAILABILITY_DOMAIN_2", "AVAILABILITY_DOMAIN_ANY"], var.partner_interconnect_config.edge_availability_domain) + error_message = "The edge_availability_domain must have one of these values: AVAILABILITY_DOMAIN_1, AVAILABILITY_DOMAIN_2, AVAILABILITY_DOMAIN_ANY." + } default = null } From 45adcf11870df96bd47da8e4c9f1d3e339a88e15 Mon Sep 17 00:00:00 2001 From: lcaggio Date: Fri, 23 Jun 2023 15:52:08 +0200 Subject: [PATCH 03/16] First commit. --- blueprints/data-solutions/shielded-folder/README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/blueprints/data-solutions/shielded-folder/README.md b/blueprints/data-solutions/shielded-folder/README.md index 30c230dc55..86d3c62cb2 100644 --- a/blueprints/data-solutions/shielded-folder/README.md +++ b/blueprints/data-solutions/shielded-folder/README.md @@ -104,17 +104,20 @@ To deploy this blueprint in your GCP organization, you will need - a folder or organization where resources will be created - a billing account that will be associated with the new projects -The Shielded Folder blueprint is meant to be executed by a Service Account (or a regular user) having this minimal set of permission: +The Shielded Folder blueprint is meant to be executed by a Service Account having this minimal set of permission: -- Billing account +- **Billing account** - `roles/billing.user` -- Folder level +- **Organization level**: + - `roles/logging.configWriter` - `roles/resourcemanager.folderAdmin` + - `roles/compute.orgFirewallPolicyAdmin` - `roles/resourcemanager.projectCreator` + - `roles/orgpolicy.policyAdmin` -The shielded Folder blueprint assumes [groups described](#user-groups) are created in your GCP organization. +The shielded Folder blueprint assumes [groups described](#user-groups) are created in your GCP organization. Please create them from the [https://admin.google.com/][Google Admin] console. -### Variable configuration PIPPO +### Variable configuration There are several sets of variables you will need to fill in: From 32b347b104280e48db4a66eca93f8b74bb4a06c5 Mon Sep 17 00:00:00 2001 From: LudovicEmo <42294753+LudovicEmo@users.noreply.github.com> Date: Sun, 25 Jun 2023 08:45:37 +0200 Subject: [PATCH 04/16] modules/vpc-sc: add support for method_selectors/permission (#1439) Co-authored-by: Ludovico Magnocavallo --- modules/vpc-sc/README.md | 8 +++---- modules/vpc-sc/service-perimeters-regular.tf | 24 ++++++++++++++++++++ modules/vpc-sc/variables.tf | 10 ++++---- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/modules/vpc-sc/README.md b/modules/vpc-sc/README.md index 83991361a2..21abff9d0b 100644 --- a/modules/vpc-sc/README.md +++ b/modules/vpc-sc/README.md @@ -205,10 +205,10 @@ module "test" { | [access_policy](variables.tf#L56) | Access Policy name, set to null if creating one. | string | ✓ | | | [access_levels](variables.tf#L17) | Access level definitions. | map(object({…})) | | {} | | [access_policy_create](variables.tf#L61) | Access Policy configuration, fill in to create. Parent is in 'organizations/123456' format, scopes are in 'folders/456789' or 'projects/project_id' format. | object({…}) | | null | -| [egress_policies](variables.tf#L71) | Egress policy definitions that can be referenced in perimeters. | map(object({…})) | | {} | -| [ingress_policies](variables.tf#L100) | Ingress policy definitions that can be referenced in perimeters. | map(object({…})) | | {} | -| [service_perimeters_bridge](variables.tf#L131) | Bridge service perimeters. | map(object({…})) | | {} | -| [service_perimeters_regular](variables.tf#L141) | Regular service perimeters. | map(object({…})) | | {} | +| [egress_policies](variables.tf#L71) | Egress policy definitions that can be referenced in perimeters. | map(object({…})) | | {} | +| [ingress_policies](variables.tf#L101) | Ingress policy definitions that can be referenced in perimeters. | map(object({…})) | | {} | +| [service_perimeters_bridge](variables.tf#L133) | Bridge service perimeters. | map(object({…})) | | {} | +| [service_perimeters_regular](variables.tf#L143) | Regular service perimeters. | map(object({…})) | | {} | ## Outputs diff --git a/modules/vpc-sc/service-perimeters-regular.tf b/modules/vpc-sc/service-perimeters-regular.tf index 5b87ca3ff8..6742a1c2a0 100644 --- a/modules/vpc-sc/service-perimeters-regular.tf +++ b/modules/vpc-sc/service-perimeters-regular.tf @@ -70,6 +70,12 @@ resource "google_access_context_manager_service_perimeter" "regular" { method = method_selectors.key } } + dynamic "method_selectors" { + for_each = toset(coalesce(o.value.permission_selectors, [])) + content { + permission = method_selectors.key + } + } } } } @@ -122,6 +128,12 @@ resource "google_access_context_manager_service_perimeter" "regular" { method = method_selectors.value } } + dynamic "method_selectors" { + for_each = toset(coalesce(o.value.permission_selectors, [])) + content { + permission = method_selectors.value + } + } } } } @@ -182,6 +194,12 @@ resource "google_access_context_manager_service_perimeter" "regular" { method = method_selectors.key } } + dynamic "method_selectors" { + for_each = toset(coalesce(o.value.permission_selectors, [])) + content { + permission = method_selectors.key + } + } } } } @@ -235,6 +253,12 @@ resource "google_access_context_manager_service_perimeter" "regular" { method = method_selectors.value } } + dynamic "method_selectors" { + for_each = toset(coalesce(o.value.permission_selectors, [])) + content { + permission = method_selectors.value + } + } } } } diff --git a/modules/vpc-sc/variables.tf b/modules/vpc-sc/variables.tf index 9a145cda6c..ff4e7dec76 100644 --- a/modules/vpc-sc/variables.tf +++ b/modules/vpc-sc/variables.tf @@ -77,8 +77,9 @@ variable "egress_policies" { }) to = object({ operations = optional(list(object({ - method_selectors = optional(list(string)) - service_name = string + method_selectors = optional(list(string)) + permission_selectors = optional(list(string)) + service_name = string })), []) resources = optional(list(string)) resource_type_external = optional(bool, false) @@ -108,8 +109,9 @@ variable "ingress_policies" { }) to = object({ operations = optional(list(object({ - method_selectors = optional(list(string)) - service_name = string + method_selectors = optional(list(string)) + permission_selectors = optional(list(string)) + service_name = string })), []) resources = optional(list(string)) }) From ce647647cc733e138dd7c2ae21086af6dda9578b Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 26 Jun 2023 08:49:05 +0200 Subject: [PATCH 05/16] Add support for resource policies to compute vm module (#1467) * instance schedule * snapshot resource policy variable and resource * tfdoc * snapshot schedules --- modules/compute-vm/README.md | 148 ++++++++++++--- modules/compute-vm/main.tf | 19 +- modules/compute-vm/resource-policies.tf | 174 ++++++++++++++++++ modules/compute-vm/tags.tf | 2 + modules/compute-vm/variables.tf | 94 +++++++++- .../examples/instance-schedule-create.yaml | 31 ++++ .../examples/instance-schedule-id.yaml | 21 +++ .../examples/snapshot-schedule-create.yaml | 19 ++ 8 files changed, 469 insertions(+), 39 deletions(-) create mode 100644 modules/compute-vm/resource-policies.tf create mode 100644 tests/modules/compute_vm/examples/instance-schedule-create.yaml create mode 100644 tests/modules/compute_vm/examples/instance-schedule-id.yaml create mode 100644 tests/modules/compute_vm/examples/snapshot-schedule-create.yaml diff --git a/modules/compute-vm/README.md b/modules/compute-vm/README.md index 1e22e8ddd7..826912544f 100644 --- a/modules/compute-vm/README.md +++ b/modules/compute-vm/README.md @@ -25,6 +25,8 @@ In both modes, an optional service account can be created and assigned to either - [Disk encryption with Cloud KMS](#disk-encryption-with-cloud-kms) - [Instance template](#instance-template) - [Instance group](#instance-group) +- [Instance Schedule](#instance-schedule) +- [Snapshot Schedules](#snapshot-schedules) ### Instance using defaults @@ -500,40 +502,132 @@ module "instance-group" { } # tftest modules=1 resources=2 inventory=group.yaml ``` + +### Instance Schedule + +Instance start and stop schedules can be defined via an existing or auto-created resource policy. + +To use an existing policy pass its id to the `instance_schedule` variable: + +```hcl +module "instance" { + source = "./fabric/modules/compute-vm" + project_id = "my-project" + zone = "europe-west1-b" + name = "schedule-test" + network_interfaces = [{ + network = var.vpc.self_link + subnetwork = var.subnet.self_link + }] + boot_disk = { + image = "projects/cos-cloud/global/images/family/cos-stable" + } + instance_schedule = { + resource_policy_id = "projects/my-project/regions/europe-west1/resourcePolicies/test" + } +} +# tftest modules=1 resources=1 inventory=instance-schedule-id.yaml +``` + +To create a new policy set its configuration in the `instance_schedule` variable. When removing the policy follow a two-step process by first setting `active = false` in the schedule configuration, which will unattach the policy, then removing the variable so the policy is destroyed. + +```hcl +module "instance" { + source = "./fabric/modules/compute-vm" + project_id = "my-project" + zone = "europe-west1-b" + name = "schedule-test" + network_interfaces = [{ + network = var.vpc.self_link + subnetwork = var.subnet.self_link + }] + boot_disk = { + image = "projects/cos-cloud/global/images/family/cos-stable" + } + instance_schedule = { + create_config = { + vm_start = "0 8 * * *" + vm_stop = "0 17 * * *" + } + } +} +# tftest modules=1 resources=2 inventory=instance-schedule-create.yaml +``` + +### Snapshot Schedules + +Snapshot policies can be attached to disks with optional creation managed by the module. + +```hcl +module "instance" { + source = "./fabric/modules/compute-vm" + project_id = "my-project" + zone = "europe-west1-b" + name = "schedule-test" + network_interfaces = [{ + network = var.vpc.self_link + subnetwork = var.subnet.self_link + }] + boot_disk = { + image = "projects/cos-cloud/global/images/family/cos-stable" + snapshot_schedule = "boot" + } + attached_disks = [ + { + name = "disk-1" + size = 10 + snapshot_schedule = "generic-vm" + } + ] + snapshot_schedules = { + boot = { + schedule = { + daily = { + days_in_cycle = 1 + start_time = "03:00" + } + } + } + } +} +# tftest modules=1 resources=5 inventory=snapshot-schedule-create.yaml +``` ## Variables | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [name](variables.tf#L182) | Instance name. | string | ✓ | | -| [network_interfaces](variables.tf#L187) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | list(object({…})) | ✓ | | -| [project_id](variables.tf#L224) | Project id. | string | ✓ | | -| [zone](variables.tf#L283) | Compute zone. | string | ✓ | | +| [name](variables.tf#L219) | Instance name. | string | ✓ | | +| [network_interfaces](variables.tf#L224) | Network interfaces configuration. Use self links for Shared VPC, set addresses to null if not needed. | list(object({…})) | ✓ | | +| [project_id](variables.tf#L261) | Project id. | string | ✓ | | +| [zone](variables.tf#L363) | Compute zone. | string | ✓ | | | [attached_disk_defaults](variables.tf#L17) | Defaults for attached disks options. | object({…}) | | {…} | -| [attached_disks](variables.tf#L38) | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | list(object({…})) | | [] | -| [boot_disk](variables.tf#L82) | Boot disk properties. | object({…}) | | {…} | -| [can_ip_forward](variables.tf#L99) | Enable IP forwarding. | bool | | false | -| [confidential_compute](variables.tf#L105) | Enable Confidential Compute for these instances. | bool | | false | -| [create_template](variables.tf#L111) | Create instance template instead of instances. | bool | | false | -| [description](variables.tf#L116) | Description of a Compute Instance. | string | | "Managed by the compute-vm Terraform module." | -| [enable_display](variables.tf#L122) | Enable virtual display on the instances. | bool | | false | -| [encryption](variables.tf#L128) | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | object({…}) | | null | -| [group](variables.tf#L138) | Define this variable to create an instance group for instances. Disabled for template use. | object({…}) | | null | -| [hostname](variables.tf#L146) | Instance FQDN name. | string | | null | -| [iam](variables.tf#L152) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | -| [instance_type](variables.tf#L158) | Instance type. | string | | "f1-micro" | -| [labels](variables.tf#L164) | Instance labels. | map(string) | | {} | -| [metadata](variables.tf#L170) | Instance metadata. | map(string) | | {} | -| [min_cpu_platform](variables.tf#L176) | Minimum CPU platform. | string | | null | -| [options](variables.tf#L202) | Instance options. | object({…}) | | {…} | -| [scratch_disks](variables.tf#L229) | Scratch disks configuration. | object({…}) | | {…} | -| [service_account](variables.tf#L241) | Service account email. Unused if service account is auto-created. | string | | null | -| [service_account_create](variables.tf#L247) | Auto-create service account. | bool | | false | -| [service_account_scopes](variables.tf#L255) | Scopes applied to service account. | list(string) | | [] | -| [shielded_config](variables.tf#L261) | Shielded VM configuration of the instances. | object({…}) | | null | -| [tag_bindings](variables.tf#L271) | Tag bindings for this instance, in key => tag value id format. | map(string) | | null | -| [tags](variables.tf#L277) | Instance network tags for firewall rule targets. | list(string) | | [] | +| [attached_disks](variables.tf#L38) | Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null. | list(object({…})) | | [] | +| [boot_disk](variables.tf#L83) | Boot disk properties. | object({…}) | | {…} | +| [can_ip_forward](variables.tf#L101) | Enable IP forwarding. | bool | | false | +| [confidential_compute](variables.tf#L107) | Enable Confidential Compute for these instances. | bool | | false | +| [create_template](variables.tf#L113) | Create instance template instead of instances. | bool | | false | +| [description](variables.tf#L118) | Description of a Compute Instance. | string | | "Managed by the compute-vm Terraform module." | +| [enable_display](variables.tf#L124) | Enable virtual display on the instances. | bool | | false | +| [encryption](variables.tf#L130) | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | object({…}) | | null | +| [group](variables.tf#L140) | Define this variable to create an instance group for instances. Disabled for template use. | object({…}) | | null | +| [hostname](variables.tf#L148) | Instance FQDN name. | string | | null | +| [iam](variables.tf#L154) | IAM bindings in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | +| [instance_schedule](variables.tf#L160) | Assign or create and assign an instance schedule policy. Either resource policy id or create_config must be specified if not null. Set active to null to dtach a policy from vm before destroying. | object({…}) | | null | +| [instance_type](variables.tf#L195) | Instance type. | string | | "f1-micro" | +| [labels](variables.tf#L201) | Instance labels. | map(string) | | {} | +| [metadata](variables.tf#L207) | Instance metadata. | map(string) | | {} | +| [min_cpu_platform](variables.tf#L213) | Minimum CPU platform. | string | | null | +| [options](variables.tf#L239) | Instance options. | object({…}) | | {…} | +| [scratch_disks](variables.tf#L266) | Scratch disks configuration. | object({…}) | | {…} | +| [service_account](variables.tf#L278) | Service account email. Unused if service account is auto-created. | string | | null | +| [service_account_create](variables.tf#L284) | Auto-create service account. | bool | | false | +| [service_account_scopes](variables.tf#L292) | Scopes applied to service account. | list(string) | | [] | +| [shielded_config](variables.tf#L298) | Shielded VM configuration of the instances. | object({…}) | | null | +| [snapshot_schedules](variables.tf#L308) | Snapshot schedule resource policies that can be attached to disks. | map(object({…})) | | {} | +| [tag_bindings](variables.tf#L351) | Tag bindings for this instance, in key => tag value id format. | map(string) | | null | +| [tags](variables.tf#L357) | Instance network tags for firewall rule targets. | list(string) | | [] | ## Outputs diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf index cf0077e523..0172ebb053 100644 --- a/modules/compute-vm/main.tf +++ b/modules/compute-vm/main.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 Google LLC + * Copyright 2023 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -133,13 +133,18 @@ resource "google_compute_instance" "default" { enable_display = var.enable_display labels = var.labels metadata = var.metadata + resource_policies = local.ischedule_attach dynamic "attached_disk" { for_each = local.attached_disks_zonal iterator = config content { - device_name = config.value.device_name != null ? config.value.device_name : config.value.name - mode = config.value.options.mode + device_name = ( + config.value.device_name != null + ? config.value.device_name + : config.value.name + ) + mode = config.value.options.mode source = ( config.value.source_type == "attach" ? config.value.source @@ -152,8 +157,12 @@ resource "google_compute_instance" "default" { for_each = local.attached_disks_regional iterator = config content { - device_name = config.value.device_name != null ? config.value.device_name : config.value.name - mode = config.value.options.mode + device_name = ( + config.value.device_name != null + ? config.value.device_name + : config.value.name + ) + mode = config.value.options.mode source = ( config.value.source_type == "attach" ? config.value.source diff --git a/modules/compute-vm/resource-policies.tf b/modules/compute-vm/resource-policies.tf new file mode 100644 index 0000000000..1aaf6eccfe --- /dev/null +++ b/modules/compute-vm/resource-policies.tf @@ -0,0 +1,174 @@ +/** + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +# tfdoc:file:description Resource policies. + +locals { + ischedule = try(var.instance_schedule.create_config, null) + ischedule_attach = var.instance_schedule == null ? null : ( + var.instance_schedule.create_config != null + # created policy with optional attach to allow policy destroy + ? ( + var.instance_schedule.create_config.active + ? [google_compute_resource_policy.schedule.0.id] + : null + ) + # externally managed policy + : [var.instance_schedule.resource_policy_id] + ) +} + +resource "google_compute_resource_policy" "schedule" { + count = local.ischedule != null ? 1 : 0 + project = var.project_id + region = substr(var.zone, 0, length(var.zone) - 2) + name = var.name + description = coalesce( + local.ischedule.description, "Schedule policy for ${var.name}." + ) + instance_schedule_policy { + expiration_time = local.ischedule.expiration_time + start_time = local.ischedule.start_time + time_zone = local.ischedule.timezone + dynamic "vm_start_schedule" { + for_each = local.ischedule.vm_start != null ? [""] : [] + content { + schedule = local.ischedule.vm_start + } + } + dynamic "vm_stop_schedule" { + for_each = local.ischedule.vm_stop != null ? [""] : [] + content { + schedule = local.ischedule.vm_stop + } + } + } +} + +resource "google_compute_resource_policy" "snapshot" { + for_each = var.snapshot_schedules + project = var.project_id + region = substr(var.zone, 0, length(var.zone) - 2) + name = "${var.name}-${each.key}" + description = coalesce( + each.value.description, "Schedule policy ${each.key} for ${var.name}." + ) + snapshot_schedule_policy { + schedule { + dynamic "daily_schedule" { + for_each = each.value.schedule.daily != null ? [""] : [] + content { + days_in_cycle = each.value.schedule.daily.days_in_cycle + start_time = each.value.schedule.daily.start_time + } + } + dynamic "hourly_schedule" { + for_each = each.value.schedule.hourly != null ? [""] : [] + content { + hours_in_cycle = each.value.schedule.hourly.hours_in_cycle + start_time = each.value.schedule.hourly.start_time + } + } + dynamic "weekly_schedule" { + for_each = each.value.schedule.weekly != null ? [""] : [] + content { + dynamic "day_of_weeks" { + for_each = each.value.schedule.weekly + content { + day = day_of_weeks.value.day + start_time = day_of_weeks.value.start_time + } + } + } + } + } + dynamic "retention_policy" { + for_each = each.value.retention_policy != null ? [""] : [] + content { + max_retention_days = each.value.retention_policy.max_retention_days + on_source_disk_delete = ( + each.value.retention_policy.on_source_disk_delete_keep == false + ? "APPLY_RETENTION_POLICY" + : "KEEP_AUTO_SNAPSHOTS" + ) + } + } + dynamic "snapshot_properties" { + for_each = each.value.snapshot_properties != null ? [""] : [] + content { + labels = each.value.snapshot_properties.labels + storage_locations = each.value.snapshot_properties.storage_locations + guest_flush = each.value.snapshot_properties.guest_flush + } + } + } +} + +resource "google_compute_disk_resource_policy_attachment" "boot" { + count = var.boot_disk.snapshot_schedule != null ? 1 : 0 + project = var.project_id + zone = var.zone + name = try( + google_compute_resource_policy.snapshot[var.boot_disk.snapshot_schedule].name, + var.boot_disk.snapshot_schedule + ) + disk = var.name + depends_on = [google_compute_instance.default] +} + +resource "google_compute_disk_resource_policy_attachment" "attached" { + for_each = { + for k, v in local.attached_disks_zonal : + k => v if v.snapshot_schedule != null + } + project = var.project_id + zone = var.zone + name = try( + google_compute_resource_policy.snapshot[each.value.snapshot_schedule].name, + each.value.snapshot_schedule + ) + disk = ( + each.value.source_type == "attach" + ? each.value.source + : google_compute_disk.disks[each.key].name + ) + depends_on = [ + google_compute_instance.default, + google_compute_disk.disks + ] +} + +resource "google_compute_region_disk_resource_policy_attachment" "attached" { + for_each = { + for k, v in local.attached_disks_regional : + k => v if v.snapshot_schedule != null + } + project = var.project_id + region = substr(var.zone, 0, length(var.zone) - 2) + name = try( + google_compute_resource_policy.snapshot[each.value.snapshot_schedule].name, + each.value.snapshot_schedule + ) + disk = ( + each.value.source_type == "attach" + ? each.value.source + : google_compute_region_disk.disks[each.key].name + ) + depends_on = [ + google_compute_instance.default, + google_compute_region_disk.disks + ] +} diff --git a/modules/compute-vm/tags.tf b/modules/compute-vm/tags.tf index a9001323ea..95be8318fd 100644 --- a/modules/compute-vm/tags.tf +++ b/modules/compute-vm/tags.tf @@ -14,6 +14,8 @@ * limitations under the License. */ +# tfdoc:file:description Tag bindings. + resource "google_tags_tag_binding" "binding" { for_each = var.create_template ? {} : coalesce(var.tag_bindings, {}) parent = "//compute.googleapis.com/${google_compute_instance.default.0.id}" diff --git a/modules/compute-vm/variables.tf b/modules/compute-vm/variables.tf index 8ec1e7163d..f76cf7e2f4 100644 --- a/modules/compute-vm/variables.tf +++ b/modules/compute-vm/variables.tf @@ -38,11 +38,12 @@ variable "attached_disk_defaults" { variable "attached_disks" { description = "Additional disks, if options is null defaults will be used in its place. Source type is one of 'image' (zonal disks in vms and template), 'snapshot' (vm), 'existing', and null." type = list(object({ - name = string - device_name = optional(string) - size = string - source = optional(string) - source_type = optional(string) + name = string + device_name = optional(string) + size = string + snapshot_schedule = optional(string) + source = optional(string) + source_type = optional(string) options = optional( object({ auto_delete = optional(bool, false) @@ -82,8 +83,9 @@ variable "attached_disks" { variable "boot_disk" { description = "Boot disk properties." type = object({ - auto_delete = optional(bool, true) - source = optional(string) + auto_delete = optional(bool, true) + snapshot_schedule = optional(string) + source = optional(string) initialize_params = optional(object({ image = optional(string, "projects/debian-cloud/global/images/family/debian-11") size = optional(number, 10) @@ -155,6 +157,41 @@ variable "iam" { default = {} } +variable "instance_schedule" { + description = "Assign or create and assign an instance schedule policy. Either resource policy id or create_config must be specified if not null. Set active to null to dtach a policy from vm before destroying." + type = object({ + resource_policy_id = optional(string) + create_config = optional(object({ + active = optional(bool, true) + description = optional(string) + expiration_time = optional(string) + start_time = optional(string) + timezone = optional(string, "UTC") + vm_start = optional(string) + vm_stop = optional(string) + })) + }) + default = null + validation { + condition = ( + var.instance_schedule == null || + try(var.instance_schedule.resource_policy_id, null) != null || + try(var.instance_schedule.create_config, null) != null + ) + error_message = "A resource policy name or configuration must be specified when not null." + } + validation { + condition = ( + try(var.instance_schedule.create_config, null) == null || + length(compact([ + try(var.instance_schedule.create_config.vm_start, null), + try(var.instance_schedule.create_config.vm_stop, null) + ])) > 0 + ) + error_message = "A resource policy configuration must contain at least one schedule." + } +} + variable "instance_type" { description = "Instance type." type = string @@ -268,6 +305,49 @@ variable "shielded_config" { default = null } +variable "snapshot_schedules" { + description = "Snapshot schedule resource policies that can be attached to disks." + type = map(object({ + schedule = object({ + daily = optional(object({ + days_in_cycle = number + start_time = string + })) + hourly = optional(object({ + hours_in_cycle = number + start_time = string + })) + weekly = optional(list(object({ + day = string + start_time = string + }))) + }) + description = optional(string) + retention_policy = optional(object({ + max_retention_days = number + on_source_disk_delete_keep = optional(bool) + })) + snapshot_properties = optional(object({ + chain_name = optional(string) + guest_flush = optional(bool) + labels = optional(map(string)) + storage_locations = optional(list(string)) + })) + })) + nullable = false + default = {} + validation { + condition = alltrue([ + for k, v in var.snapshot_schedules : ( + (v.schedule.daily != null ? 1 : 0) + + (v.schedule.hourly != null ? 1 : 0) + + (v.schedule.weekly != null ? 1 : 0) + ) == 1 + ]) + error_message = "Schedule must contain exactly one of daily, hourly, or weekly schedule." + } +} + variable "tag_bindings" { description = "Tag bindings for this instance, in key => tag value id format." type = map(string) diff --git a/tests/modules/compute_vm/examples/instance-schedule-create.yaml b/tests/modules/compute_vm/examples/instance-schedule-create.yaml new file mode 100644 index 0000000000..26917c45ee --- /dev/null +++ b/tests/modules/compute_vm/examples/instance-schedule-create.yaml @@ -0,0 +1,31 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.instance.google_compute_resource_policy.schedule[0]: + description: Schedule policy for schedule-test. + instance_schedule_policy: + - expiration_time: null + start_time: null + time_zone: UTC + vm_start_schedule: + - schedule: 0 8 * * * + vm_stop_schedule: + - schedule: 0 17 * * * + name: schedule-test + region: europe-west1 + +counts: + google_compute_instance: 1 + google_compute_resource_policy: 1 diff --git a/tests/modules/compute_vm/examples/instance-schedule-id.yaml b/tests/modules/compute_vm/examples/instance-schedule-id.yaml new file mode 100644 index 0000000000..409e9ddb02 --- /dev/null +++ b/tests/modules/compute_vm/examples/instance-schedule-id.yaml @@ -0,0 +1,21 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +values: + module.instance.google_compute_instance.default[0]: + resource_policies: + - projects/my-project/regions/europe-west1/resourcePolicies/test + +counts: + google_compute_instance: 1 diff --git a/tests/modules/compute_vm/examples/snapshot-schedule-create.yaml b/tests/modules/compute_vm/examples/snapshot-schedule-create.yaml new file mode 100644 index 0000000000..daf659c6c4 --- /dev/null +++ b/tests/modules/compute_vm/examples/snapshot-schedule-create.yaml @@ -0,0 +1,19 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +counts: + google_compute_disk: 1 + google_compute_disk_resource_policy_attachment: 2 + google_compute_instance: 1 + google_compute_resource_policy: 1 From 8a6555c581af0e47edfdc79b8ce989c2661ab047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Niesiob=C4=99dzki?= Date: Fri, 23 Jun 2023 07:38:07 +0000 Subject: [PATCH 06/16] Add preliminary support for partner interconnect --- .../networking/ha-vpn-over-interconnect/README.md | 2 +- .../ha-vpn-over-interconnect/underlay.tf | 14 ++++++++++---- .../ha-vpn-over-interconnect/variables.tf | 5 +++++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/blueprints/networking/ha-vpn-over-interconnect/README.md b/blueprints/networking/ha-vpn-over-interconnect/README.md index db89d87e85..a4b29ca1f3 100644 --- a/blueprints/networking/ha-vpn-over-interconnect/README.md +++ b/blueprints/networking/ha-vpn-over-interconnect/README.md @@ -32,7 +32,7 @@ The two Dedicated Interconnect connections should already exist, either in the s | [overlay_config](variables.tf#L24) | Configuration for the overlay resources. | object({…}) | ✓ | | | [project_id](variables.tf#L66) | The project id. | string | ✓ | | | [region](variables.tf#L71) | GCP Region. | string | ✓ | | -| [underlay_config](variables.tf#L76) | Configuration for the underlay resources. | object({…}) | ✓ | | +| [underlay_config](variables.tf#L76) | Configuration for the underlay resources. | object({…}) | ✓ | | ## Outputs diff --git a/blueprints/networking/ha-vpn-over-interconnect/underlay.tf b/blueprints/networking/ha-vpn-over-interconnect/underlay.tf index 6ad9c4501d..bb8709cc11 100644 --- a/blueprints/networking/ha-vpn-over-interconnect/underlay.tf +++ b/blueprints/networking/ha-vpn-over-interconnect/underlay.tf @@ -38,13 +38,16 @@ module "va-a" { create = false name = google_compute_router.encrypted-interconnect-underlay-router.name } - dedicated_interconnect_config = { + vpn_gateways_ip_range = var.underlay_config.attachments.a.vpn_gateways_ip_range + dedicated_interconnect_config = var.underlay_config.interconnect_type != "DEDICATED" ? null : { bandwidth = var.underlay_config.attachments.a.bandwidth bgp_range = var.underlay_config.attachments.a.bgp_range interconnect = var.underlay_config.attachments.a.interconnect_self_link vlan_tag = var.underlay_config.attachments.a.vlan_tag } - vpn_gateways_ip_range = var.underlay_config.attachments.a.vpn_gateways_ip_range + partner_interconnect_config = var.underlay_config.interconnect_type != "PARTNER" ? null : { + edge_availability_domain = "zone1" + } } module "va-b" { @@ -59,11 +62,14 @@ module "va-b" { create = false name = google_compute_router.encrypted-interconnect-underlay-router.name } - dedicated_interconnect_config = { + vpn_gateways_ip_range = var.underlay_config.attachments.b.vpn_gateways_ip_range + dedicated_interconnect_config = var.underlay_config.interconnect_type != "DEDICATED" ? null : { bandwidth = var.underlay_config.attachments.b.bandwidth bgp_range = var.underlay_config.attachments.b.bgp_range interconnect = var.underlay_config.attachments.b.interconnect_self_link vlan_tag = var.underlay_config.attachments.b.vlan_tag } - vpn_gateways_ip_range = var.underlay_config.attachments.b.vpn_gateways_ip_range + partner_interconnect_config = var.underlay_config.interconnect_type != "PARTNER" ? null : { + edge_availability_domain = "zone2" + } } diff --git a/blueprints/networking/ha-vpn-over-interconnect/variables.tf b/blueprints/networking/ha-vpn-over-interconnect/variables.tf index 163ea1ac86..196ef26956 100644 --- a/blueprints/networking/ha-vpn-over-interconnect/variables.tf +++ b/blueprints/networking/ha-vpn-over-interconnect/variables.tf @@ -88,5 +88,10 @@ variable "underlay_config" { gcp_bgp = object({ asn = number }) + interconnect_type = optional(string, "DEDICATED") }) + validation { + condition = var.underlay_config.interconnect_type == "DEDICATED" || var.underlay_config.interconnect_type == "PARTNER" + error_message = "var.underlay_config.interconnect_type must by either \"DEDICATED\" or \"PARTNER\"" + } } From 173a00d7956fe12379002191e67b45dc3d527417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Niesiob=C4=99dzki?= Date: Fri, 23 Jun 2023 08:10:19 +0000 Subject: [PATCH 07/16] Use EAD per enum https://cloud.google.com/compute/docs/reference/rest/v1/interconnectAttachments#InterconnectAttachment.FIELDS.edge_availability_domain --- blueprints/networking/ha-vpn-over-interconnect/underlay.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/blueprints/networking/ha-vpn-over-interconnect/underlay.tf b/blueprints/networking/ha-vpn-over-interconnect/underlay.tf index bb8709cc11..2a15605031 100644 --- a/blueprints/networking/ha-vpn-over-interconnect/underlay.tf +++ b/blueprints/networking/ha-vpn-over-interconnect/underlay.tf @@ -46,7 +46,7 @@ module "va-a" { vlan_tag = var.underlay_config.attachments.a.vlan_tag } partner_interconnect_config = var.underlay_config.interconnect_type != "PARTNER" ? null : { - edge_availability_domain = "zone1" + edge_availability_domain = "AVAILABILITY_DOMAIN_1" } } @@ -70,6 +70,6 @@ module "va-b" { vlan_tag = var.underlay_config.attachments.b.vlan_tag } partner_interconnect_config = var.underlay_config.interconnect_type != "PARTNER" ? null : { - edge_availability_domain = "zone2" + edge_availability_domain = "AVAILABILITY_DOMAIN_2" } } From 4b6552a6f6ee64fce6f49880b40b4ed8cf1e2970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Niesiob=C4=99dzki?= Date: Fri, 23 Jun 2023 08:29:34 +0000 Subject: [PATCH 08/16] Update README --- blueprints/networking/ha-vpn-over-interconnect/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/blueprints/networking/ha-vpn-over-interconnect/README.md b/blueprints/networking/ha-vpn-over-interconnect/README.md index a4b29ca1f3..e2bab6e188 100644 --- a/blueprints/networking/ha-vpn-over-interconnect/README.md +++ b/blueprints/networking/ha-vpn-over-interconnect/README.md @@ -2,7 +2,9 @@ This blueprint creates a complete HA VPN over Interconnect setup, which leverages IPSec to encrypt all traffic transiting through purposely-created VLAN Attachments. -This blueprint supports Dedicated Interconnect - in case Partner Interconnect is used instead (hence the VLAN Attachments are already created), simply refer to the [net-ipsec-over-interconnect](../../../modules/net-ipsec-over-interconnect/) module documentation. +This blueprint supports Dedicated Interconnect and Partner Interconnect. + +In case of Partner Interconnect only partial apply is possible at first, which creates the VLAN Attachments. Only once the partner connection is established it is possible to deploy HA VPN Gateway and all dependant resources. ## Managed resources and services @@ -22,6 +24,8 @@ A single pre-existing project and a VPC is used in this blueprint to keep variab The provided project needs a valid billing account and the Compute APIs enabled. The two Dedicated Interconnect connections should already exist, either in the same project or in any other project belonging to the same GCP Organization. + + ## Variables From 638841c8d16994ebd8e6db6cba652b419f91c058 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 26 Jun 2023 09:50:10 +0200 Subject: [PATCH 09/16] Rename network load balancer modules (#1466) * update LB modules to new names * update LB modules names * update test paths --- CHANGELOG.md | 38 ++++++------- CONTRIBUTING.md | 56 ++++++++++--------- README.md | 2 +- blueprints/apigee/README.md | 5 +- blueprints/apigee/bigquery-analytics/main.tf | 2 +- blueprints/apigee/network-patterns/README.md | 5 +- .../README.md | 2 +- .../apigee_nb.tf | 2 +- .../apigee_sb.tf | 2 +- .../onprem.tf | 2 +- blueprints/cloud-operations/adfs/main.tf | 2 +- .../network-dashboard/README.md | 2 +- .../sqlserver-alwayson/README.md | 16 +++--- .../data-solutions/sqlserver-alwayson/vpc.tf | 4 +- blueprints/networking/README.md | 6 +- .../nginx-reverse-proxy-cluster/main.tf | 2 +- .../networking/filtering-proxy-psc/main.tf | 2 +- blueprints/networking/filtering-proxy/main.tf | 2 +- blueprints/networking/glb-and-armor/main.tf | 2 +- .../glb-hybrid-neg-internal/README.md | 33 +++++------ .../networking/glb-hybrid-neg-internal/glb.tf | 2 +- .../networking/glb-hybrid-neg-internal/nva.tf | 2 +- .../glb-hybrid-neg-internal/spoke.tf | 2 +- blueprints/networking/ilb-next-hop/README.md | 8 +-- .../networking/ilb-next-hop/gateways.tf | 4 +- .../networking/psc-glb-and-armor/README.md | 4 +- .../networking/psc-glb-and-armor/variables.tf | 4 +- blueprints/serverless/api-gateway/main.tf | 2 +- .../serverless/cloud-run-corporate/README.md | 18 +++++- .../serverless/cloud-run-corporate/main.tf | 2 +- .../serverless/cloud-run-explore/main.tf | 2 +- fast/stages/2-networking-a-peering/README.md | 2 +- fast/stages/2-networking-b-vpn/README.md | 2 +- fast/stages/2-networking-c-nva/README.md | 4 +- fast/stages/2-networking-c-nva/nva.tf | 4 +- .../2-networking-d-separate-envs/README.md | 2 +- fast/stages/2-networking-e-nva-bgp/README.md | 2 +- modules/README.md | 8 +-- modules/compute-mig/README.md | 2 +- .../{net-glb => net-lb-app-ext}/.gitignore | 0 modules/{net-glb => net-lb-app-ext}/README.md | 40 ++++++------- .../backend-service.tf | 0 .../{net-glb => net-lb-app-ext}/backends.tf | 0 .../health-check.tf | 0 modules/{net-glb => net-lb-app-ext}/main.tf | 0 modules/{net-glb => net-lb-app-ext}/negs.tf | 0 .../{net-glb => net-lb-app-ext}/outputs.tf | 0 modules/{net-glb => net-lb-app-ext}/urlmap.tf | 0 .../variables-backend-service.tf | 0 .../variables-health-check.tf | 0 .../variables-urlmap.tf | 0 .../{net-glb => net-lb-app-ext}/variables.tf | 0 .../{net-glb => net-lb-app-ext}/versions.tf | 0 .../{net-ilb-l7 => net-lb-app-int}/README.md | 30 +++++----- .../backend-service.tf | 0 .../health-check.tf | 0 .../{net-ilb-l7 => net-lb-app-int}/main.tf | 0 .../{net-ilb-l7 => net-lb-app-int}/outputs.tf | 0 .../{net-ilb-l7 => net-lb-app-int}/urlmap.tf | 0 .../variables-backend-service.tf | 0 .../variables-health-check.tf | 0 .../variables-urlmap.tf | 0 .../variables.tf | 0 .../versions.tf | 0 modules/{net-nlb => net-lb-ext}/README.md | 8 +-- modules/{net-nlb => net-lb-ext}/groups.tf | 0 .../{net-nlb => net-lb-ext}/health-check.tf | 0 modules/{net-nlb => net-lb-ext}/main.tf | 0 modules/{net-nlb => net-lb-ext}/outputs.tf | 0 modules/{net-nlb => net-lb-ext}/variables.tf | 0 modules/{net-ilb => net-lb-ext}/versions.tf | 0 modules/{net-ilb => net-lb-int}/README.md | 8 +-- modules/{net-ilb => net-lb-int}/groups.tf | 0 .../{net-ilb => net-lb-int}/health-check.tf | 0 modules/{net-ilb => net-lb-int}/main.tf | 0 modules/{net-ilb => net-lb-int}/outputs.tf | 0 modules/{net-ilb => net-lb-int}/variables.tf | 0 modules/{net-nlb => net-lb-int}/versions.tf | 0 .../examples/https-sneg.yaml | 0 .../test-plan.tfvars | 0 .../test-plan.yaml | 0 .../{net_glb => net_lb_app_ext}/tftest.yaml | 2 +- .../__init__.py | 0 .../common.tfvars | 0 .../defaults.tfvars | 0 .../defaults.yaml | 0 .../groups.tfvars | 0 .../groups.yaml | 0 .../health-checks-custom.tfvars | 0 .../health-checks-custom.yaml | 0 .../health-checks-external.tfvars | 0 .../health-checks-external.yaml | 0 .../https.tfvars | 0 .../{net_ilb_l7 => net_lb_app_int}/https.yaml | 0 .../negs.tfvars | 0 .../{net_ilb_l7 => net_lb_app_int}/negs.yaml | 0 .../{net_ilb_l7 => net_lb_app_int}/ssl.tfvars | 0 .../{net_ilb_l7 => net_lb_app_int}/ssl.yaml | 0 .../tftest.yaml | 2 +- .../urlmaps.tfvars | 0 .../urlmaps.yaml | 0 .../{net_ilb => net_lb_int}/defaults.tfvars | 0 .../{net_ilb => net_lb_int}/defaults.yaml | 0 .../forwarding-rule.tfvars | 0 .../forwarding-rule.yaml | 0 .../{net_ilb => net_lb_int}/tftest.yaml | 2 +- 106 files changed, 189 insertions(+), 166 deletions(-) rename modules/{net-glb => net-lb-app-ext}/.gitignore (100%) rename modules/{net-glb => net-lb-app-ext}/README.md (98%) rename modules/{net-glb => net-lb-app-ext}/backend-service.tf (100%) rename modules/{net-glb => net-lb-app-ext}/backends.tf (100%) rename modules/{net-glb => net-lb-app-ext}/health-check.tf (100%) rename modules/{net-glb => net-lb-app-ext}/main.tf (100%) rename modules/{net-glb => net-lb-app-ext}/negs.tf (100%) rename modules/{net-glb => net-lb-app-ext}/outputs.tf (100%) rename modules/{net-glb => net-lb-app-ext}/urlmap.tf (100%) rename modules/{net-glb => net-lb-app-ext}/variables-backend-service.tf (100%) rename modules/{net-glb => net-lb-app-ext}/variables-health-check.tf (100%) rename modules/{net-glb => net-lb-app-ext}/variables-urlmap.tf (100%) rename modules/{net-glb => net-lb-app-ext}/variables.tf (100%) rename modules/{net-glb => net-lb-app-ext}/versions.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/README.md (98%) rename modules/{net-ilb-l7 => net-lb-app-int}/backend-service.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/health-check.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/main.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/outputs.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/urlmap.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/variables-backend-service.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/variables-health-check.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/variables-urlmap.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/variables.tf (100%) rename modules/{net-ilb-l7 => net-lb-app-int}/versions.tf (100%) rename modules/{net-nlb => net-lb-ext}/README.md (98%) rename modules/{net-nlb => net-lb-ext}/groups.tf (100%) rename modules/{net-nlb => net-lb-ext}/health-check.tf (100%) rename modules/{net-nlb => net-lb-ext}/main.tf (100%) rename modules/{net-nlb => net-lb-ext}/outputs.tf (100%) rename modules/{net-nlb => net-lb-ext}/variables.tf (100%) rename modules/{net-ilb => net-lb-ext}/versions.tf (100%) rename modules/{net-ilb => net-lb-int}/README.md (98%) rename modules/{net-ilb => net-lb-int}/groups.tf (100%) rename modules/{net-ilb => net-lb-int}/health-check.tf (100%) rename modules/{net-ilb => net-lb-int}/main.tf (100%) rename modules/{net-ilb => net-lb-int}/outputs.tf (100%) rename modules/{net-ilb => net-lb-int}/variables.tf (100%) rename modules/{net-nlb => net-lb-int}/versions.tf (100%) rename tests/modules/{net_glb => net_lb_app_ext}/examples/https-sneg.yaml (100%) rename tests/modules/{net_glb => net_lb_app_ext}/test-plan.tfvars (100%) rename tests/modules/{net_glb => net_lb_app_ext}/test-plan.yaml (100%) rename tests/modules/{net_glb => net_lb_app_ext}/tftest.yaml (95%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/__init__.py (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/common.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/defaults.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/defaults.yaml (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/groups.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/groups.yaml (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/health-checks-custom.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/health-checks-custom.yaml (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/health-checks-external.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/health-checks-external.yaml (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/https.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/https.yaml (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/negs.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/negs.yaml (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/ssl.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/ssl.yaml (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/tftest.yaml (95%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/urlmaps.tfvars (100%) rename tests/modules/{net_ilb_l7 => net_lb_app_int}/urlmaps.yaml (100%) rename tests/modules/{net_ilb => net_lb_int}/defaults.tfvars (100%) rename tests/modules/{net_ilb => net_lb_int}/defaults.yaml (100%) rename tests/modules/{net_ilb => net_lb_int}/forwarding-rule.tfvars (100%) rename tests/modules/{net_ilb => net_lb_int}/forwarding-rule.yaml (100%) rename tests/modules/{net_ilb => net_lb_int}/tftest.yaml (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 637e131236..24d420bd6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,8 +51,8 @@ All notable changes to this project will be documented in this file. ### MODULES -- [[#1417](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1417)] Remove hardcoded description from instance groups created under net-ilb ([LucaPrete](https://github.com/LucaPrete)) -- [[#1415](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1415)] Add notice to net-ilb module on routes ([ludoo](https://github.com/ludoo)) +- [[#1417](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1417)] Remove hardcoded description from instance groups created under net-lb-int ([LucaPrete](https://github.com/LucaPrete)) +- [[#1415](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1415)] Add notice to net-lb-int module on routes ([ludoo](https://github.com/ludoo)) - [[#1403](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1403)] add alloydb module ([prabhaarya](https://github.com/prabhaarya)) - [[#1411](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1411)] Add networksecurity to JIT identity list ([rosmo](https://github.com/rosmo)) - [[#1410](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1410)] **incompatible change:** Ensure all modules have an `id` output ([ludoo](https://github.com/ludoo)) @@ -156,7 +156,7 @@ All notable changes to this project will be documented in this file. - [[#1365](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1365)] feat(net-cloudnat): add toggle for independent endpoint mapping and dynamic port allocation ([JSchwerberg](https://github.com/JSchwerberg)) - [[#1367](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1367)] fix routes priority typo ([fawzihmouda](https://github.com/fawzihmouda)) - [[#1360](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1360)] Add support for Shared VPC in Cloud Run ([juliodiez](https://github.com/juliodiez)) -- [[#1329](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1329)] fix: Change net-glb serve_while_stale type to number ([tobbbles](https://github.com/tobbbles)) +- [[#1329](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1329)] fix: Change net-lb-app-ext serve_while_stale type to number ([tobbbles](https://github.com/tobbbles)) - [[#1308](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1308)] Add cloud dataplex module ([prabhaarya](https://github.com/prabhaarya)) - [[#1352](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1352)] **incompatible change:** Switch FAST networking stages to network policies for Google domains ([ludoo](https://github.com/ludoo)) - [[#1349](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1349)] Enhance GKE Backup Configuration Support ([tacchino](https://github.com/tacchino)) @@ -294,7 +294,7 @@ All notable changes to this project will be documented in this file. - [[#1269](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1269)] Ignore changes to metadata.0.annotations in Cloud Run module ([juliocc](https://github.com/juliocc)) - [[#1267](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1267)] Improvements to NCC-RA spoke module. ([LucaPrete](https://github.com/LucaPrete)) - [[#1268](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1268)] simple-nva: add ability to parse BGP configs as strings. ([LucaPrete](https://github.com/LucaPrete)) -- [[#1258](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1258)] Add backend service names to outputs for net-glb and net-ilb-l7 ([rosmo](https://github.com/rosmo)) +- [[#1258](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1258)] Add backend service names to outputs for net-lb-app-ext and net-lb-app-int ([rosmo](https://github.com/rosmo)) - [[#1259](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1259)] Add support for `iam_additive` and simplify factory interface in net VPC module ([ludoo](https://github.com/ludoo)) - [[#1255](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1255)] **incompatible change:** Change `target_vpcs` variable in firewall policy module to support dynamic values ([ludoo](https://github.com/ludoo)) - [[#1256](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1256)] **incompatible change:** Pin local provider ([ludoo](https://github.com/ludoo)) @@ -302,7 +302,7 @@ All notable changes to this project will be documented in this file. - [[#1241](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1241)] **incompatible change:** Allow using existing boot disk in compute-vm module ([ludoo](https://github.com/ludoo)) - [[#1239](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1239)] Allow overriding name in net-vpc subnet factory ([ludoo](https://github.com/ludoo)) - [[#1226](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1226)] Fix policy_based_routing.sh script on simple-nva module ([simonebruzzechesse](https://github.com/simonebruzzechesse)) -- [[#1234](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1234)] Fixed connection tracking configuration on LB backend in net-ilb module ([simonebruzzechesse](https://github.com/simonebruzzechesse)) +- [[#1234](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1234)] Fixed connection tracking configuration on LB backend in net-lb-int module ([simonebruzzechesse](https://github.com/simonebruzzechesse)) - [[#1232](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1232)] Network firewall policy module ([ludoo](https://github.com/ludoo)) - [[#1219](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1219)] Network Connectivity Center module ([juliodiez](https://github.com/juliodiez)) - [[#1227](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1227)] Add CMEK support on BQML blueprint ([lcaggio](https://github.com/lcaggio)) @@ -311,12 +311,12 @@ All notable changes to this project will be documented in this file. - [[#1211](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1211)] **incompatible change:** Add support for proxy and psc subnets to net-vpc module factory ([ludoo](https://github.com/ludoo)) - [[#1206](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1206)] Dataproc module. Fix output. ([lcaggio](https://github.com/lcaggio)) - [[#1205](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1205)] Fix issue with GKE cluster notifications topic & static output for pubsub module ([rosmo](https://github.com/rosmo)) -- [[#1204](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1204)] Fix url_redirect issue on net-glb module ([erabusi](https://github.com/erabusi)) +- [[#1204](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1204)] Fix url_redirect issue on net-lb-app-ext module ([erabusi](https://github.com/erabusi)) - [[#1199](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1199)] [Dataproc module] Fix Variables ([lcaggio](https://github.com/lcaggio)) - [[#1200](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1200)] Add test for #1197 ([juliocc](https://github.com/juliocc)) - [[#1198](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1198)] Fix secondary ranges in net-vpc readme ([ludoo](https://github.com/ludoo)) - [[#1196](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1196)] Fix compute-vm:CloudKMS test for provider>=4.54.0 ([dan-farmer](https://github.com/dan-farmer)) -- [[#1194](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1194)] Fix HTTPS health check mismapped to HTTP in compute-mig and net-ilb modules ([jogoldberg](https://github.com/jogoldberg)) +- [[#1194](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1194)] Fix HTTPS health check mismapped to HTTP in compute-mig and net-lb-int modules ([jogoldberg](https://github.com/jogoldberg)) - [[#1192](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1192)] Dataproc module: Fix outputs ([lcaggio](https://github.com/lcaggio)) - [[#1190](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1190)] Dataproc Module ([lcaggio](https://github.com/lcaggio)) - [[#1191](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1191)] Fix external gateway in VPN HA module ([ludoo](https://github.com/ludoo)) @@ -335,7 +335,7 @@ All notable changes to this project will be documented in this file. - [[#1160](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1160)] Allow additive IAM grants by robots name ([wiktorn](https://github.com/wiktorn)) - [[#1158](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1158)] changed pod_range reference to include secondary_pod_range issue #1157 ([chemapolo](https://github.com/chemapolo)) - [[#1156](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1156)] Add 'max_time_travel_hours ' support on BQ module ([lcaggio](https://github.com/lcaggio)) -- [[#1151](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1151)] Add example about referencing existing MIGs to net-ilb module readme ([LucaPrete](https://github.com/LucaPrete)) +- [[#1151](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1151)] Add example about referencing existing MIGs to net-lb-int module readme ([LucaPrete](https://github.com/LucaPrete)) - [[#1149](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1149)] Add documentation about JIT-ed service accounts ([wiktorn](https://github.com/wiktorn)) - [[#1131](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1131)] Add Autopilot Support for cluster_autoscaling Configuration in GKE Module ([tacchino](https://github.com/tacchino)) - [[#1140](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1140)] CloudSQL Backup Configuration: Support Point In Time Recovery ([tacchino](https://github.com/tacchino)) @@ -449,7 +449,7 @@ All notable changes to this project will be documented in this file. ### BLUEPRINTS - [[#1045](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1045)] Assorted module fixes ([ludoo](https://github.com/ludoo)) -- [[#1044](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1044)] **incompatible change:** Refactor net-glb module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) +- [[#1044](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1044)] **incompatible change:** Refactor net-lb-app-ext module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) - [[#982](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/982)] Adding Secondary IP Utilization calculation ([brianhmj](https://github.com/brianhmj)) - [[#1037](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1037)] Bump qs and formidable in /blueprints/cloud-operations/apigee/functions/export ([dependabot[bot]]()) - [[#1034](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1034)] feat(blueprints): get audience from tfc environment variable ([Thomgrus](https://github.com/Thomgrus)) @@ -513,7 +513,7 @@ All notable changes to this project will be documented in this file. - [[#1048](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1048)] Document new testing approach ([ludoo](https://github.com/ludoo)) - [[#1045](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1045)] Assorted module fixes ([ludoo](https://github.com/ludoo)) - [[#1014](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1014)] Update typos in `net-vpc-firewall` README.md ([aymanfarhat](https://github.com/aymanfarhat)) -- [[#1044](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1044)] **incompatible change:** Refactor net-glb module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) +- [[#1044](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1044)] **incompatible change:** Refactor net-lb-app-ext module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) - [[#1009](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1009)] Fix encryption in Data Playground blueprint ([lcaggio](https://github.com/lcaggio)) - [[#1006](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1006)] Add settings for autoscaling to Bigtable module. ([iht](https://github.com/iht)) - [[#1007](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1007)] fast README, one line fix: 00-cicd stage got moved to extras/ ([skalolazka](https://github.com/skalolazka)) @@ -570,7 +570,7 @@ All notable changes to this project will be documented in this file. - [[#1045](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1045)] Assorted module fixes ([ludoo](https://github.com/ludoo)) - [[#1040](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1040)] Fix name in google_pubsub_schema resource ([VictorCavalcanteLG](https://github.com/VictorCavalcanteLG)) - [[#1043](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1043)] added reverse lookup feature to module dns #1042 ([chemapolo](https://github.com/chemapolo)) -- [[#1044](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1044)] **incompatible change:** Refactor net-glb module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) +- [[#1044](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1044)] **incompatible change:** Refactor net-lb-app-ext module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) - [[#1036](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1036)] **incompatible change:** Fix status ingress/egress policies in vpc-sc module ([ludoo](https://github.com/ludoo)) - [[#1033](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1033)] strongSwan: switch base image to debian-slim ([kunzese](https://github.com/kunzese)) - [[#1026](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1026)] add lifecycle ignore_changes for apigee PAYG env ([g-greatdevaks](https://github.com/g-greatdevaks)) @@ -599,7 +599,7 @@ All notable changes to this project will be documented in this file. - [[#978](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/978)] Worker pool support for `cloud-function` ([maunope](https://github.com/maunope)) - [[#977](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/977)] Replace Docker's `gcplogs` driver with the GCP COS logging agent ([kunzese](https://github.com/kunzese)) - [[#975](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/975)] Add validation for health check port specification to ILB L7 module ([ludoo](https://github.com/ludoo)) -- [[#974](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/974)] **incompatible change:** Refactor net-ilb-l7 module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) +- [[#974](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/974)] **incompatible change:** Refactor net-lb-app-int module for Terraform 1.3 ([ludoo](https://github.com/ludoo)) - [[#970](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/970)] Update logging sinks to tf1.3 in resman modules ([juliocc](https://github.com/juliocc)) - [[#969](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/969)] Update folder and project org policy tests ([juliocc](https://github.com/juliocc)) - [[#964](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/964)] prefix variable consistency across modules ([skalolazka](https://github.com/skalolazka)) @@ -749,7 +749,7 @@ All notable changes to this project will be documented in this file. - [[#805](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/805)] Change `modules/project` service_config default ([juliocc](https://github.com/juliocc)) - [[#787](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/787)] Support manager role in cloud identity group module ([lcaggio](https://github.com/lcaggio)) - [[#786](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/786)] Secret manager flag sensitive output ([ddaluka](https://github.com/ddaluka)) -- [[#775](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/775)] net-glb: Added support for regional external HTTP(s) load balancing ([rosmo](https://github.com/rosmo)) +- [[#775](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/775)] net-lb-app-ext: Added support for regional external HTTP(s) load balancing ([rosmo](https://github.com/rosmo)) - [[#784](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/784)] fix envoy-traffic-director config for xDS v3 ([drebes](https://github.com/drebes)) - [[#785](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/785)] nginx-tls module ([drebes](https://github.com/drebes)) - [[#783](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/783)] fix service unit indent on cloud-config-container module ([drebes](https://github.com/drebes)) @@ -774,7 +774,7 @@ All notable changes to this project will be documented in this file. - [[#729](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/729)] Fix connector create logic in cloud run module ([ludoo](https://github.com/ludoo)) - [[#726](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/726)] Fix documentation for organization-policy module ([averbuks](https://github.com/averbuks)) - [[#722](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/722)] OrgPolicy module (factory) using new org-policy API, #698 ([averbuks](https://github.com/averbuks)) -- [[#695](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/695)] Modified reserved IP address outputs in net-glb module ([apichick](https://github.com/apichick)) +- [[#695](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/695)] Modified reserved IP address outputs in net-lb-app-ext module ([apichick](https://github.com/apichick)) - [[#709](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/709)] Fix incompatibility between logging and monitor config/service arguments in GKE module ([psabhishekgoogle](https://github.com/psabhishekgoogle)) - [[#708](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/708)] Fix incompatibility between backup and autopilot in GKE module ([ludoo](https://github.com/ludoo)) - [[#707](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/707)] Fix addons for autopilot clusters and add specific tests in GKE module ([juliocc](https://github.com/juliocc)) @@ -832,7 +832,7 @@ All notable changes to this project will be documented in this file. - optionally turn off gcplogs driver in COS modules - fix `tag` output on `data-catalog-policy-tag` module - add shared-vpc support on `gcs-to-bq-with-least-privileges` -- new `net-ilb-l7` module +- new `net-lb-app-int` module - new `02-networking-peering` networking stage - **incompatible change** the variable for PSA ranges in networking stages have changed @@ -866,7 +866,7 @@ All notable changes to this project will be documented in this file. ## [13.0.0] - 2022-01-27 - **initial Fabric FAST implementation** -- new `net-glb` module for Global External Load balancer +- new `net-lb-app-ext` module for Global External Load balancer - new `project-factory` module in [`blueprints/factories`](./blueprints/factories) - add missing service identity accounts (artifactregistry, composer) in project module - new "Cloud Storage to Bigquery with Cloud Dataflow with least privileges" example @@ -1197,7 +1197,7 @@ All notable changes to this project will be documented in this file. - **incompatible change** routes in the `net-vpc` module now interpolate the VPC name to ensure uniqueness, upgrading from a previous version will drop and recreate routes - the top-level `docker-images` folder has been moved inside `modules/cloud-config-container/onprem` - `dns_keys` output added to the `dns` module -- add `group-config` variable, `groups` and `group_self_links` outputs to `net-ilb` module to allow creating ILBs for externally managed instances +- add `group-config` variable, `groups` and `group_self_links` outputs to `net-lb-int` module to allow creating ILBs for externally managed instances - make the IAM bindings depend on the compute instance in the `compute-vm` module ## [2.0.0] - 2020-06-11 @@ -1245,7 +1245,7 @@ All notable changes to this project will be documented in this file. - **incompatible change** subnets in the `net-vpc` modules are now passed as a list instead of map, and all related variables for IAM and flow logs use `region/name` instead of `name` keys; it's now possible to have the same subnet name in different regions - replace all references to the removed `resourceviews.googleapis.com` API with `container.googleapis.com` - fix advanced options in `gke-nodepool` module -- fix health checks in `compute-mig` and `net-ilb` modules +- fix health checks in `compute-mig` and `net-lb-int` modules - new `cos-generic-metadata` module in the `cloud-config-container` suite - new `envoy-traffic-director` module in the `cloud-config-container` suite - new `pubsub` module @@ -1263,7 +1263,7 @@ All notable changes to this project will be documented in this file. - add peering route configuration for private clusters to GKE cluster module - **incompatible changes** in the GKE nodepool module: rename `node_config_workload_metadata_config` variable to `workload_metadata_config`, new default for `workload_metadata_config` is `GKE_METADATA_SERVER` - **incompatible change** in the `compute-vm` module: removed support for MIG and the `group_manager` variable -- add `compute-mig` and `net-ilb` modules +- add `compute-mig` and `net-lb-int` modules - **incompatible change** in `net-vpc`: a new `name` attribute has been added to the `subnets` variable, allowing to directly set subnet name, to update to the new module add an extra `name = false` attribute to each subnet ## [1.3.0] - 2020-04-08 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 28a7c5b64d..7396f875ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,22 +7,22 @@ Contributors are the engine that keeps Fabric alive so if you were or are planni - [I just found a bug / have a feature request](#i-just-found-a-bug--have-a-feature-request) - [Quick developer workflow](#quick-developer-workflow) - [Developer's handbook](#developers-handbook) - * [The Zen of Fabric](#the-zen-of-fabric) - * [Design principles in action](#design-principles-in-action) - * [FAST stage design](#fast-stage-design) - * [Style guide reference](#style-guide-reference) - * [Interacting with checks and tools](#interacting-with-checks-and-tools) + - [The Zen of Fabric](#the-zen-of-fabric) + - [Design principles in action](#design-principles-in-action) + - [FAST stage design](#fast-stage-design) + - [Style guide reference](#style-guide-reference) + - [Interacting with checks and tools](#interacting-with-checks-and-tools) - [Using and writing tests](#using-and-writing-tests) - * [Testing via README.md example blocks.](#testing-via-readmemd-example-blocks) - + [Testing examples against an inventory YAML](#testing-examples-against-an-inventory-yaml) - + [Using external files](#using-external-files) - + [Running tests for specific examples](#running-tests-for-specific-examples) - + [Generating the inventory automatically](#generating-the-inventory-automatically) - + [Building tests for blueprints](#building-tests-for-blueprints) - * [Testing via `tfvars` and `yaml` (aka `tftest`-based tests)](#testing-via-tfvars-and-yaml-aka-tftest-based-tests) - + [Generating the inventory for `tftest`-based tests](#generating-the-inventory-for-tftest-based-tests) - * [Writing tests in Python (legacy approach)](#writing-tests-in-python-legacy-approach) - * [Running tests from a temporary directory](#running-tests-from-a-temporary-directory) + - [Testing via README.md example blocks.](#testing-via-readmemd-example-blocks) + - [Testing examples against an inventory YAML](#testing-examples-against-an-inventory-yaml) + - [Using external files](#using-external-files) + - [Running tests for specific examples](#running-tests-for-specific-examples) + - [Generating the inventory automatically](#generating-the-inventory-automatically) + - [Building tests for blueprints](#building-tests-for-blueprints) + - [Testing via `tfvars` and `yaml` (aka `tftest`-based tests)](#testing-via-tfvars-and-yaml-aka-tftest-based-tests) + - [Generating the inventory for `tftest`-based tests](#generating-the-inventory-for-tftest-based-tests) + - [Writing tests in Python (legacy approach)](#writing-tests-in-python-legacy-approach) + - [Running tests from a temporary directory](#running-tests-from-a-temporary-directory) - [Fabric tools](#fabric-tools) ## I just found a bug / have a feature request @@ -205,11 +205,11 @@ We have several such interfaces defined for IAM, log sinks, organizational polic #### Design interfaces to support actual usage > “When developing a module, look for opportunities to take a little bit of extra suffering upon yourself in order to reduce the suffering of your users.” -> +> > “Providing choice is good, but interfaces should be designed to make the common case as simple as possible” -> +> > — John Ousterhout in "A Philosophy of Software Design" - + Variables should not simply map to the underlying resource attributes, but their **interfaces should be designed to match common use cases** to reduce friction and offer the highest possible degree of legibility. This translates into different practical approaches: @@ -300,7 +300,6 @@ module "project" { > > — John Ousterhout in "A Philosophy of Software Design" - Designing variable spaces is one of the most complex aspects to get right, as they are the main entry point through which users consume modules, examples and FAST stages. We always strive to **design small variable spaces by leveraging objects and implementing defaults** so that users can quickly produce highly readable code. One of many examples of this approach comes from disk support in the `compute-vm` module, where preset defaults allow quick VM management with very few lines of code, and optional variables allow progressively expanding the code when more control is needed. @@ -688,7 +687,7 @@ In the following sections we describe the three testing approaches we currently - [tfvars-based tests](#testing-via-tfvars-and-yaml): allows you to test a module or blueprint by providing variables via tfvar files and an expected plan result in form of an inventory. This type of test is useful, for example, for FAST stages that don't have any examples within their READMEs. - [Python-based (legacy) tests](#writing-tests-in-python--legacy-approach-): in some situations you might still want to interact directly with `tftest` via Python, if that's the case, use this method to write custom Python logic to test your module in any way you see fit. -### Testing via README.md example blocks. +### Testing via README.md example blocks This is the preferred method to write tests for modules and blueprints. Example-based tests are triggered from [HCL Markdown fenced code blocks](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#syntax-highlighting) in any file named README.md, hence there's no need to create any additional files or revert to Python to write a test. Most of our documentation examples are using this method. @@ -795,6 +794,7 @@ module "private-dns" { } # tftest modules=1 resources=2 files=records ``` + ```yaml # tftest-file id=records path=records/example.yaml A localhost: @@ -814,6 +814,7 @@ As mentioned before, we use `pytest` as our test runner, so you can use any of t Example-based test are named based on the section within the README.md that contains them. You can use this name to select specific tests. Here we show a few commonly used selection commands: + - Run all examples: - `pytest tests/examples/` - Run all examples for modules: @@ -919,7 +920,7 @@ The second approach to testing requires you to: - define `yaml` "inventory" files with the plan and output results you want to test - declare which of these files need to be run as tests in a `tftest.yaml` file -Let's go through each step in succession, assuming you are testing the new `net-glb` module. +Let's go through each step in succession, assuming you are testing the new `net-lb-app-ext` module. First create a new folder under `tests/modules` replacing any dash in the module name with underscores. Note that if you were testing a blueprint the folder would go in `tests/blueprints`. @@ -973,7 +974,7 @@ Create as many pairs of `tfvars`/`yaml` files as you need to test every scenario ```yaml # file: tests/modules/net_glb/tftest.yaml -module: modules/net-glb +module: modules/net-lb-app-ext # if there are variables shared among all tests you can define a common file # common_tfvars: # - defaults.tfvars @@ -1052,12 +1053,13 @@ You can now use this output to create the inventory file for your test. As menti Where possible, we recommend using the testing methods described in the previous sections. However, if you need it, you can still write tests using Python directly. In general, you should try to use the `plan_summary` fixture, which runs a a terraform plan and returns a `PlanSummary` object. The most important arguments to `plan_summary` are: + - the path of the Terraform module you want to test, relative to the root of the repository - a list of paths representing the tfvars file to pass in to terraform. These paths are relative to the python file defining the test. If successful, `plan_summary` will return a `PlanSummary` object with the `values`, `counts` and `outputs` attributes following the same semantics described in the previous section. You can use this fields to write your custom tests. -Like before let's imagine we're writing a (python) test for `net-glb` module. First create a new folder under `tests/modules` replacing any dash in the module name with underscores. You also need to create an empty `__init__.py` file in it, to ensure `pytest` discovers you new tests automatically. +Like before let's imagine we're writing a (python) test for `net-lb-app-ext` module. First create a new folder under `tests/modules` replacing any dash in the module name with underscores. You also need to create an empty `__init__.py` file in it, to ensure `pytest` discovers you new tests automatically. ```bash mkdir tests/modules/net_glb @@ -1065,9 +1067,10 @@ touch tests/modules/net_glb/__init__.py ``` Now create a file containing your tests, e.g. `test_plan.py`: + ```python def test_name(plan_summary, tfvars_to_yaml, tmp_path): - s = plan_summary('modules/net-glb', tf_var_files=['test-plan.tfvars']) + s = plan_summary('modules/net-lb-app-ext', tf_var_files=['test-plan.tfvars']) address = 'google_compute_url_map.default' assert s.values[address]['project'] == 'my-project' ``` @@ -1081,16 +1084,19 @@ Most of the time you can run tests using the `pytest` command as described in pr To enable this option, just define the environment variable `TFTEST_COPY` and any tests using the `plan_summary` fixture will automatically run from a temporary directory. Running tests from temporary directories is useful if: + - you're running tests in parallel using `pytest-xdist`. In this case, just run you tests as follows: + ```bash TFTEST_COPY=1 pytest -n 4 ``` + - you're running tests for the `fast/` directory which contain tfvars and auto.tfvars files (which are read by terraform automatically) making your tests fail. In this case, you can run + ``` TFTEST_COPY=1 pytest fast/ ``` - ## Fabric tools The main tool you will interact with in development is `tfdoc`, used to generate file, output and variable tables in README documents. diff --git a/README.md b/README.md index 6a64bc68db..3e00d0f676 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ The current list of modules supports most of the core foundational and networkin Currently available modules: - **foundational** - [billing budget](./modules/billing-budget), [Cloud Identity group](./modules/cloud-identity-group/), [folder](./modules/folder), [service accounts](./modules/iam-service-account), [logging bucket](./modules/logging-bucket), [organization](./modules/organization), [project](./modules/project), [projects-data-source](./modules/projects-data-source) -- **networking** - [DNS](./modules/dns), [DNS Response Policy](./modules/dns-response-policy/), [Cloud Endpoints](./modules/endpoints), [address reservation](./modules/net-address), [NAT](./modules/net-cloudnat), [VLAN Attachment](./modules/net-vlan-attachment/), [Global Load Balancer (classic)](./modules/net-glb/), [L4 ILB](./modules/net-ilb), [L7 ILB](./modules/net-ilb-l7), [IPSec over Interconnect](./modules/net-ipsec-over-interconnect), [Network LB](./modules/net-nlb), [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC firewall policy](./modules/net-vpc-firewall-policy), [VPC peering](./modules/net-vpc-peering), [VPN dynamic](./modules/net-vpn-dynamic), [HA VPN](./modules/net-vpn-ha), [VPN static](./modules/net-vpn-static), [Service Directory](./modules/service-directory) +- **networking** - [DNS](./modules/dns), [DNS Response Policy](./modules/dns-response-policy/), [Cloud Endpoints](./modules/endpoints), [address reservation](./modules/net-address), [NAT](./modules/net-cloudnat), [VLAN Attachment](./modules/net-vlan-attachment/), [External Application LB](./modules/net-lb-app-ext/), [External Network Passthrough LB](./modules/net-lb-ext), [Internal Application LB](./modules/net-lb-app-int), [Internal Network Passthrough LB](./modules/net-lb-int), [IPSec over Interconnect](./modules/net-ipsec-over-interconnect), [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC firewall policy](./modules/net-vpc-firewall-policy), [VPC peering](./modules/net-vpc-peering), [VPN dynamic](./modules/net-vpn-dynamic), [HA VPN](./modules/net-vpn-ha), [VPN static](./modules/net-vpn-static), [Service Directory](./modules/service-directory) - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [COS container](./modules/cloud-config-container/cos-generic-metadata/) (coredns, mysql, onprem, squid), [GKE cluster](./modules/gke-cluster-standard), [GKE hub](./modules/gke-hub), [GKE nodepool](./modules/gke-nodepool) - **data** - [AlloyDB instance](./modules/alloydb-instance), [BigQuery dataset](./modules/bigquery-dataset), [Bigtable instance](./modules/bigtable-instance), [Cloud Dataplex](./modules/cloud-dataplex), [Cloud SQL instance](./modules/cloudsql-instance), [Data Catalog Policy Tag](./modules/data-catalog-policy-tag), [Datafusion](./modules/datafusion), [Dataproc](./modules/dataproc), [GCS](./modules/gcs), [Pub/Sub](./modules/pubsub) - **development** - [API Gateway](./modules/api-gateway), [Apigee](./modules/apigee), [Artifact Registry](./modules/artifact-registry), [Container Registry](./modules/container-registry), [Cloud Source Repository](./modules/source-repository) diff --git a/blueprints/apigee/README.md b/blueprints/apigee/README.md index 4cec9de9cf..5f77147df3 100644 --- a/blueprints/apigee/README.md +++ b/blueprints/apigee/README.md @@ -20,5 +20,6 @@ The blueprints in this folder contain a variety of deployment scenarios for Apig The following blueprints demonstrate a set of networking scenarios that can be implemented for Apigee X deployments. -#### Apigee X - Northbound: GLB with PSC Neg, Southbouth: PSC with ILB (L7) and Hybrid NEG -This [blueprint](./network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/) shows how to expose an on-prem target backend to clients in the Internet. \ No newline at end of file +#### Apigee X - Northbound: External Application LB with PSC Neg, Southbouth: PSC with Internal Application LB and Hybrid NEG + +This [blueprint](./network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/) shows how to expose an on-prem target backend to clients in the Internet. diff --git a/blueprints/apigee/bigquery-analytics/main.tf b/blueprints/apigee/bigquery-analytics/main.tf index 97b42be8c7..0aea7bbc64 100644 --- a/blueprints/apigee/bigquery-analytics/main.tf +++ b/blueprints/apigee/bigquery-analytics/main.tf @@ -88,7 +88,7 @@ module "apigee" { } module "glb" { - source = "../../../modules/net-glb" + source = "../../../modules/net-lb-app-ext" name = "glb" project_id = module.project.project_id protocol = "HTTPS" diff --git a/blueprints/apigee/network-patterns/README.md b/blueprints/apigee/network-patterns/README.md index 241c412d4c..27944a6cfe 100644 --- a/blueprints/apigee/network-patterns/README.md +++ b/blueprints/apigee/network-patterns/README.md @@ -2,5 +2,6 @@ The blueprints in this folder demonstrate a set of networking scenarios that can be implemented for Apigee X deployments. -## Apigee X - Northbound: GLB with PSC Neg, Southbouth: PSC with ILB (L7) and Hybrid NEG -This [blueprint](./nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/) shows how to expose an on-prem target backend to clients in the Internet.g \ No newline at end of file +## Northbound: External Application LB with PSC Neg, Southbouth: PSC with Internal Application LB and Hybrid NEG + +This [blueprint](./nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/) shows how to expose an on-prem target backend to clients in the Internet.g diff --git a/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/README.md b/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/README.md index b568bd8eb8..51534dda0e 100644 --- a/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/README.md +++ b/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/README.md @@ -1,4 +1,4 @@ -# Apigee X - Northbound GLB with PSC Neg, Southbouth PSC with ILB (L7) and Hybrid NEG +# Apigee X - Northbound: External Application LB with PSC Neg, Southbouth: PSC with Internal Application LB and Hybrid NEG The following blueprint shows how to expose an on-prem target backend to clients in the Internet. diff --git a/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/apigee_nb.tf b/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/apigee_nb.tf index b568da9a05..f4e7d5ee14 100644 --- a/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/apigee_nb.tf +++ b/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/apigee_nb.tf @@ -15,7 +15,7 @@ */ module "glb" { - source = "../../../../modules/net-glb" + source = "../../../../modules/net-lb-app-ext" name = "glb" project_id = module.apigee_project.project_id protocol = "HTTPS" diff --git a/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/apigee_sb.tf b/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/apigee_sb.tf index e6df149b2c..f08fd69798 100644 --- a/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/apigee_sb.tf +++ b/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/apigee_sb.tf @@ -15,7 +15,7 @@ */ module "apigee_ilb_l7" { - source = "../../../../modules/net-ilb-l7" + source = "../../../../modules/net-lb-app-int" name = "apigee-ilb" project_id = module.apigee_project.project_id region = var.region diff --git a/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/onprem.tf b/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/onprem.tf index b923a38189..3a82a81ef4 100644 --- a/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/onprem.tf +++ b/blueprints/apigee/network-patterns/nb-glb-psc-neg-sb-psc-ilbl7-hybrid-neg/onprem.tf @@ -116,7 +116,7 @@ module "mig" { } module "onprem_ilb_l7" { - source = "../../../../modules/net-ilb-l7" + source = "../../../../modules/net-lb-app-int" name = "ilb" project_id = module.onprem_project.project_id region = var.region diff --git a/blueprints/cloud-operations/adfs/main.tf b/blueprints/cloud-operations/adfs/main.tf index b05d09aa35..686e9fc6e6 100644 --- a/blueprints/cloud-operations/adfs/main.tf +++ b/blueprints/cloud-operations/adfs/main.tf @@ -96,7 +96,7 @@ module "server" { } module "glb" { - source = "../../../modules/net-glb" + source = "../../../modules/net-lb-app-ext" name = "${var.prefix}-glb" project_id = module.project.project_id protocol = "HTTPS" diff --git a/blueprints/cloud-operations/network-dashboard/README.md b/blueprints/cloud-operations/network-dashboard/README.md index 01bc6bf6d6..fd7a682118 100644 --- a/blueprints/cloud-operations/network-dashboard/README.md +++ b/blueprints/cloud-operations/network-dashboard/README.md @@ -72,7 +72,7 @@ Refer to the [Cloud Function deployment instructions](./deploy-cloud-function/) ## Assumptions and limitations - The tool assumes all VPCs in peering groups are within the same organization, except for PSA peerings. -- The tool will only fetch subnet utilization data from the PSA peerings (not the VMs, ILB or routes usage). +- The tool will only fetch subnet utilization data from the PSA peerings (not the VMs, LB or routes usage). - The tool assumes global routing is ON, this impacts dynamic routes usage calculation. - The tool assumes custom routes importing/exporting is ON, this impacts static and dynamic routes usage calculation. - The tool assumes all networks in peering groups have the same global routing and custom routes sharing configuration. diff --git a/blueprints/data-solutions/sqlserver-alwayson/README.md b/blueprints/data-solutions/sqlserver-alwayson/README.md index 85ab8385c8..7fd3231b53 100644 --- a/blueprints/data-solutions/sqlserver-alwayson/README.md +++ b/blueprints/data-solutions/sqlserver-alwayson/README.md @@ -1,16 +1,16 @@ ## SQL Server Always On Groups blueprint -This is an blueprint of building [SQL Server Always On Availability Groups](https://cloud.google.com/compute/docs/instances/sql-server/configure-availability) -using Fabric modules. It builds a two node cluster with a fileshare witness instance in an existing VPC and adds the necessary firewalling. +This is an blueprint of building [SQL Server Always On Availability Groups](https://cloud.google.com/compute/docs/instances/sql-server/configure-availability) +using Fabric modules. It builds a two node cluster with a fileshare witness instance in an existing VPC and adds the necessary firewalling. ![Architecture diagram](https://cloud.google.com/compute/images/sqlserver-ag-architecture.svg) -The actual setup process (apart from Active Directory operations) has been scripted, so that least amount of -manual works needs to performed: +The actual setup process (apart from Active Directory operations) has been scripted, so that least amount of +manual works needs to performed: - - Joining the domain using appropriate credentials - - Running an automatically generated initialization script (`C:\InitializeCluster.ps1`) - - Creating the [Availability Groups using the wizard](https://cloud.google.com/compute/docs/instances/sql-server/configure-availability#creating_an_availability_group) +- Joining the domain using appropriate credentials +- Running an automatically generated initialization script (`C:\InitializeCluster.ps1`) +- Creating the [Availability Groups using the wizard](https://cloud.google.com/compute/docs/instances/sql-server/configure-availability#creating_an_availability_group) (please note that healthchecks are automatically configured when the appropriate AGs are created) To monitor the installation process, the startup scripts log output to Application Log (visible under Windows Logs in Event Viewer) @@ -29,7 +29,7 @@ and to `C:\GcpSetupLog.txt` file. | [secrets.tf](./secrets.tf) | Creates SQL admin user password secret. | secret-manager | | [service-accounts.tf](./service-accounts.tf) | Creates service accounts for the instances. | iam-service-account | | [variables.tf](./variables.tf) | Module variables. | | -| [vpc.tf](./vpc.tf) | Creates the VPC and manages the firewall rules and ILB. | net-address · net-ilb · net-vpc · net-vpc-firewall | +| [vpc.tf](./vpc.tf) | Creates the VPC and manages the firewall rules and LB. | net-address · net-lb-int · net-vpc · net-vpc-firewall | ## Variables diff --git a/blueprints/data-solutions/sqlserver-alwayson/vpc.tf b/blueprints/data-solutions/sqlserver-alwayson/vpc.tf index 0f1e425e18..5c4a15b01a 100644 --- a/blueprints/data-solutions/sqlserver-alwayson/vpc.tf +++ b/blueprints/data-solutions/sqlserver-alwayson/vpc.tf @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# tfdoc:file:description Creates the VPC and manages the firewall rules and ILB. +# tfdoc:file:description Creates the VPC and manages the firewall rules and LB. locals { internal_addresses = merge( @@ -135,7 +135,7 @@ module "ip-addresses" { } module "listener-ilb" { - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" for_each = toset(var.always_on_groups) project_id = var.project_id region = var.region diff --git a/blueprints/networking/README.md b/blueprints/networking/README.md index b67f8e259a..40660022d9 100644 --- a/blueprints/networking/README.md +++ b/blueprints/networking/README.md @@ -52,9 +52,9 @@ The sample highlights the lack of transitivity in peering: the absence of connec
-### ILB as next hop +### Internal Network LB as next hop - This [blueprint](./ilb-next-hop/) allows testing [ILB as next hop](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview) using simple Linux gateway VMS between two VPCs, to emulate virtual appliances. An optional additional ILB can be enabled to test multiple load balancer configurations and hashing. + This [blueprint](./ilb-next-hop/) allows testing [Internal Network LB as next hop](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview) using simple Linux gateway VMS between two VPCs, to emulate virtual appliances. An optional additional Internal Network LB can be enabled to test multiple load balancer configurations and hashing.
@@ -95,4 +95,4 @@ It is meant to be used as a starting point for most Shared VPC configurations, a It is meant to be used as a starting point for users that want to explore PSC to reduce some of the complexity in their network setup. -
\ No newline at end of file +
diff --git a/blueprints/networking/__need_fixing/nginx-reverse-proxy-cluster/main.tf b/blueprints/networking/__need_fixing/nginx-reverse-proxy-cluster/main.tf index ad2d0e482e..2d40721bfe 100644 --- a/blueprints/networking/__need_fixing/nginx-reverse-proxy-cluster/main.tf +++ b/blueprints/networking/__need_fixing/nginx-reverse-proxy-cluster/main.tf @@ -303,7 +303,7 @@ module "proxy-vm" { } module "glb" { - source = "../../../modules/net-glb" + source = "../../../modules/net-lb-app-ext" project_id = module.project.project_id name = "${var.prefix}-reverse-proxy-glb" health_check_configs = { diff --git a/blueprints/networking/filtering-proxy-psc/main.tf b/blueprints/networking/filtering-proxy-psc/main.tf index f51d49418f..457522a4d0 100644 --- a/blueprints/networking/filtering-proxy-psc/main.tf +++ b/blueprints/networking/filtering-proxy-psc/main.tf @@ -201,7 +201,7 @@ module "squid-mig" { } module "squid-ilb" { - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" project_id = module.project.project_id region = var.region name = "squid-ilb" diff --git a/blueprints/networking/filtering-proxy/main.tf b/blueprints/networking/filtering-proxy/main.tf index 9851d8e9ad..1273693203 100644 --- a/blueprints/networking/filtering-proxy/main.tf +++ b/blueprints/networking/filtering-proxy/main.tf @@ -202,7 +202,7 @@ module "squid-mig" { module "squid-ilb" { count = var.mig ? 1 : 0 - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" project_id = module.project-host.project_id region = var.region name = "squid-ilb" diff --git a/blueprints/networking/glb-and-armor/main.tf b/blueprints/networking/glb-and-armor/main.tf index b85cdbaa8b..22a7c3c7c4 100644 --- a/blueprints/networking/glb-and-armor/main.tf +++ b/blueprints/networking/glb-and-armor/main.tf @@ -192,7 +192,7 @@ module "mig_ue1" { } module "glb" { - source = "../../../modules/net-glb" + source = "../../../modules/net-lb-app-ext" name = "${var.prefix}-http-lb" project_id = module.project.project_id backend_service_configs = { diff --git a/blueprints/networking/glb-hybrid-neg-internal/README.md b/blueprints/networking/glb-hybrid-neg-internal/README.md index 253dc4c448..ec27f19255 100644 --- a/blueprints/networking/glb-hybrid-neg-internal/README.md +++ b/blueprints/networking/glb-hybrid-neg-internal/README.md @@ -1,12 +1,12 @@ -# GLB and multi-regional daisy-chaining through hybrid NEGs +# External Application LB and multi-regional daisy-chaining through hybrid NEGs -The blueprint shows the experimental use of hybrid NEGs behind eXternal Global Load Balancers (GLBs) to connect to GCP instances living in spoke VPCs and behind Network Virtual Appliances (NVAs). +The blueprint shows the experimental use of hybrid NEGs behind External Application Load Balancers to connect to GCP instances living in spoke VPCs and behind Network Virtual Appliances (NVAs).

This allows users to not configure per-destination-VM NAT rules in the NVAs. -The user traffic will enter the GLB, it will go across the NVAs and it will be routed to the destination VMs (or the ILBs behind the VMs) in the spokes. +The user traffic will enter the External Application LB, it will go across the NVAs and it will be routed to the destination VMs (or the LBs behind the VMs) in the spokes. ## What the blueprint creates @@ -16,23 +16,23 @@ The ids `primary` and `secondary` are used to identify two regions. By default, - Projects: landing, spoke-01 - VPCs and subnets - + landing-untrusted: primary - 192.168.1.0/24 and secondary - 192.168.2.0/24 - + landing-trusted: primary - 192.168.11.0/24 and secondary - 192.168.22.0/24 - + spoke-01: primary - 192.168.101.0/24 and secondary - 192.168.102.0/24 + - landing-untrusted: primary - 192.168.1.0/24 and secondary - 192.168.2.0/24 + - landing-trusted: primary - 192.168.11.0/24 and secondary - 192.168.22.0/24 + - spoke-01: primary - 192.168.101.0/24 and secondary - 192.168.102.0/24 - Cloud NAT - + landing-untrusted (both for primary and secondary) - + in spoke-01 (both for primary and secondary) - this is just for test purposes, so you VMs can automatically install nginx, even if NVAs are still not ready + - landing-untrusted (both for primary and secondary) + - in spoke-01 (both for primary and secondary) - this is just for test purposes, so you VMs can automatically install nginx, even if NVAs are still not ready - VMs - + NVAs in MIGs in the landing project, both in primary and secondary, with NICs in the untrusted and in the trusted VPCs - + Test VMs, in spoke-01, both in primary and secondary. Optionally, deployed in MIGs + - NVAs in MIGs in the landing project, both in primary and secondary, with NICs in the untrusted and in the trusted VPCs + - Test VMs, in spoke-01, both in primary and secondary. Optionally, deployed in MIGs -- Hybrid NEGs in the untrusted VPC, both in primary and secondary, either pointing to the test VMs in the spoke or -optionally- to ILBs in the spokes (if test VMs are deployed as MIGs) +- Hybrid NEGs in the untrusted VPC, both in primary and secondary, either pointing to the test VMs in the spoke or -optionally- to LBs in the spokes (if test VMs are deployed as MIGs) -- Internal Load balancers (L4 ILBs) - + in the untrusted VPC, pointing to NVA MIGs, both in primary and secondary. Their VIPs are used by custom routes in the untrusted VPC, so that all traffic that arrives in the untrusted VPC destined for the test VMs in the spoke is sent through the NVAs - + optionally, in the spokes. They are created if the user decides to deploy the test VMs as MIGs +- Internal Network Load balancers (L4 LBs) + - in the untrusted VPC pointing to NVA MIGs, both in primary and secondary. Their VIPs are used by custom routes in the untrusted VPC, so that all traffic that arrives in the untrusted VPC destined for the test VMs in the spoke is sent through the NVAs + - optionally, in the spokes. They are created if the user decides to deploy the test VMs as MIGs - External Global Load balancer (GLB) in the untrusted VPC, using the hybrid NEGs as its backends @@ -48,7 +48,7 @@ The blueprint configures some custom routes in the untrusted VPC and routing/NAT Specifically: -- we create two custom routes in the untrusted VPC (one per region) so that traffic for the spoke subnets is sent to the VIP of the L4 ILBs in front of the NVAs +- we create two custom routes in the untrusted VPC (one per region) so that traffic for the spoke subnets is sent to the VIP of the L4 LBs in front of the NVAs - we configure the NVAs so they know how to route traffic to the spokes via the trusted VPC gateway @@ -56,7 +56,7 @@ Specifically: ## Change the ilb_create variable -Through the `ilb_create` variable you can decide whether test VMs in the spoke will be deployed as MIGs with ILBs in front. This will also configure NEGs, so they point to the ILB VIPs, instead of the VM IPs. +Through the `ilb_create` variable you can decide whether test VMs in the spoke will be deployed as MIGs with LBs in front. This will also configure NEGs, so they point to the LB VIPs, instead of the VM IPs. At the moment, every time a user changes the configuration of a NEG, the NEG is recreated. When this happens, the provider doesn't check if it is used by other resources, such as GLB backend services. Until this doesn't get fixed, every time you'll need to change the NEG configuration (i.e. when changing the variable `ilb_create`) you'll have to workaround it. Here is how: @@ -86,6 +86,7 @@ At the moment, every time a user changes the configuration of a NEG, the NEG is ## Test + ```hcl module "test" { source = "./fabric/blueprints/networking/glb-hybrid-neg-internal" diff --git a/blueprints/networking/glb-hybrid-neg-internal/glb.tf b/blueprints/networking/glb-hybrid-neg-internal/glb.tf index 4d67d68a30..e071e7e6c8 100644 --- a/blueprints/networking/glb-hybrid-neg-internal/glb.tf +++ b/blueprints/networking/glb-hybrid-neg-internal/glb.tf @@ -17,7 +17,7 @@ # tfdoc:file:description External Global Load Balancer. module "hybrid-glb" { - source = "../../../modules/net-glb" + source = "../../../modules/net-lb-app-ext" project_id = module.project_landing.project_id name = "hybrid-glb" backend_service_configs = { diff --git a/blueprints/networking/glb-hybrid-neg-internal/nva.tf b/blueprints/networking/glb-hybrid-neg-internal/nva.tf index 1d2a508f87..5db9b54887 100644 --- a/blueprints/networking/glb-hybrid-neg-internal/nva.tf +++ b/blueprints/networking/glb-hybrid-neg-internal/nva.tf @@ -67,7 +67,7 @@ module "nva_migs" { module "nva_untrusted_ilbs" { for_each = var.regions - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" project_id = module.project_landing.project_id region = each.value name = "nva-ilb-${local.zones[each.key]}" diff --git a/blueprints/networking/glb-hybrid-neg-internal/spoke.tf b/blueprints/networking/glb-hybrid-neg-internal/spoke.tf index 1769d4c682..ceaa2b181f 100644 --- a/blueprints/networking/glb-hybrid-neg-internal/spoke.tf +++ b/blueprints/networking/glb-hybrid-neg-internal/spoke.tf @@ -126,7 +126,7 @@ module "test_vm_migs" { module "test_vm_ilbs" { for_each = var.ilb_create ? var.regions : {} - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" project_id = module.project_spoke_01.project_id region = each.value name = "test-vm-ilb-${each.value}" diff --git a/blueprints/networking/ilb-next-hop/README.md b/blueprints/networking/ilb-next-hop/README.md index 1200d9d27b..7bb3a4bdac 100644 --- a/blueprints/networking/ilb-next-hop/README.md +++ b/blueprints/networking/ilb-next-hop/README.md @@ -1,4 +1,4 @@ -# Internal Load Balancer as Next Hop +# Internal Network Load Balancer as Next Hop This blueprint bootstraps a minimal infrastructure for testing [ILB as next hop](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview), using simple Linux gateway VMS between two VPCs to emulate virtual appliances. @@ -10,13 +10,13 @@ Two ILBs are configured on the primary and secondary interfaces of gateway VMs w ## Testing -This setup can be used to test and verify new ILB features like [forwards all protocols on ILB as next hops](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview#all-traffic) and [symmetric hashing](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview#symmetric-hashing), using simple `curl` and `ping` tests on clients. To make this practical, test VMs on both VPCs have `nginx` pre-installed and active on port 80. +This setup can be used to test and verify new Internal Network LB features like [forwards all protocols on Internal Network LB as next hops](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview#all-traffic) and [symmetric hashing](https://cloud.google.com/load-balancing/docs/internal/ilb-next-hop-overview#symmetric-hashing), using simple `curl` and `ping` tests on clients. To make this practical, test VMs on both VPCs have `nginx` pre-installed and active on port 80. On the gateways, `iftop` and `tcpdump` are installed by default to quickly monitor traffic passing forwarded across VPCs. -Session affinity on the ILB backend services can be changed using `gcloud compute backend-services update` on each of the ILBs, or by setting the `ilb_session_affinity` variable to update both ILBs. +Session affinity on the Internal Network LB backend services can be changed using `gcloud compute backend-services update` on each of the Internal Network LBs, or by setting the `ilb_session_affinity` variable to update both Internal Network LBs. -Simple `/root/start.sh` and `/root/stop.sh` scripts are pre-installed on both gateways to configure `iptables` so that health check requests are rejected and re-enabled, to quickly simulate removing instances from the ILB backends. +Simple `/root/start.sh` and `/root/stop.sh` scripts are pre-installed on both gateways to configure `iptables` so that health check requests are rejected and re-enabled, to quickly simulate removing instances from the Internal Network LB backends. Some scenarios to test: diff --git a/blueprints/networking/ilb-next-hop/gateways.tf b/blueprints/networking/ilb-next-hop/gateways.tf index 97f69fef25..e57e83c8e8 100644 --- a/blueprints/networking/ilb-next-hop/gateways.tf +++ b/blueprints/networking/ilb-next-hop/gateways.tf @@ -60,7 +60,7 @@ module "gw" { } module "ilb-left" { - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" project_id = module.project.project_id region = var.region name = "${var.prefix}-ilb-left" @@ -84,7 +84,7 @@ module "ilb-left" { } module "ilb-right" { - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" project_id = module.project.project_id region = var.region name = "${var.prefix}-ilb-right" diff --git a/blueprints/networking/psc-glb-and-armor/README.md b/blueprints/networking/psc-glb-and-armor/README.md index c9e101e8b7..785dc0081c 100644 --- a/blueprints/networking/psc-glb-and-armor/README.md +++ b/blueprints/networking/psc-glb-and-armor/README.md @@ -27,7 +27,7 @@ This architecture is ideal, if the external Load Balancer and the application ar In a real world implementation, the IaC code might be split into two separate repositories, and the application team raises changes to the load balancer using a pull request. Also the service attachment in the producer project is configured to allow all connections via `connection_preference = "ACCEPT_AUTOMATIC"` in a real world setup you would want to use a manual white listing instead. -The Terraform IaC also deploys a VM to the producer VPC network, this VM is only needed for the internal Layer 7 Load Balancer to properly work with Cloud Run, but has no logical function in the setup, no traffic is routed via this machine. +The Terraform IaC also deploys a VM to the producer VPC network, this VM is only needed for the internal Layer 7 Load Balancer to properly work with Cloud Run, but has no logical function in the setup, no traffic is routed via this machine. ## Setup @@ -101,7 +101,7 @@ The above command will delete the associated resources so there will be no billa |---|---|:---:|:---:|:---:| | [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_project_id](variables.tf#L31) | The producer project, in which the ILB, PSC Service Attachment and Cloud Run service should be created. | string | ✓ | | +| [producer_project_id](variables.tf#L31) | The producer project, in which the LB, PSC Service Attachment and Cloud Run service should be created. | string | ✓ | | | [project_create](variables.tf#L36) | Create project instead of using an existing one. | bool | | false | | [region](variables.tf#L42) | The GCP region in which the resources should be deployed. | string | | "europe-west1" | | [zone](variables.tf#L48) | The GCP zone for the VM. | string | | "europe-west1-b" | diff --git a/blueprints/networking/psc-glb-and-armor/variables.tf b/blueprints/networking/psc-glb-and-armor/variables.tf index b8715ea697..3ded93cb0c 100644 --- a/blueprints/networking/psc-glb-and-armor/variables.tf +++ b/blueprints/networking/psc-glb-and-armor/variables.tf @@ -29,7 +29,7 @@ variable "prefix" { } variable "producer_project_id" { - description = "The producer project, in which the ILB, PSC Service Attachment and Cloud Run service should be created." + description = "The producer project, in which the LB, PSC Service Attachment and Cloud Run service should be created." type = string } @@ -49,4 +49,4 @@ variable "zone" { description = "The GCP zone for the VM." type = string default = "europe-west1-b" -} \ No newline at end of file +} diff --git a/blueprints/serverless/api-gateway/main.tf b/blueprints/serverless/api-gateway/main.tf index d828d5ea44..7bd40037d8 100644 --- a/blueprints/serverless/api-gateway/main.tf +++ b/blueprints/serverless/api-gateway/main.tf @@ -102,7 +102,7 @@ module "gateways" { } module "glb" { - source = "../../../modules/net-glb" + source = "../../../modules/net-lb-app-ext" project_id = module.project.project_id name = "glb" backend_service_configs = { diff --git a/blueprints/serverless/cloud-run-corporate/README.md b/blueprints/serverless/cloud-run-corporate/README.md index fd40913a51..93f98c5491 100644 --- a/blueprints/serverless/cloud-run-corporate/README.md +++ b/blueprints/serverless/cloud-run-corporate/README.md @@ -7,6 +7,7 @@ This blueprint contains all the necessary Terraform modules to build and __priva The content of this blueprint corresponds to the chapter '_Developing an enterprise application - The corporate environment_' of the [__Serverless Networking Guide__](https://services.google.com/fh/files/misc/serverless_networking_guide.pdf). This guide is an easy to follow introduction to Cloud Run, where a couple of friendly characters will guide you from the basics to more advanced topics with a very practical approach and in record time! The code here complements this learning and allows you to test the scenarios presented and your knowledge. If you are interested in following this guide, take a look to the chapters' blueprints: + * [My serverless "Hello, World! - Exploring Cloud Run](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/tree/master/blueprints/serverless/cloud-run-explore) * [Developing an enterprise application - The corporate environment](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/tree/master/blueprints/serverless/cloud-run-corporate) @@ -33,21 +34,27 @@ Below it is explained how to set this information. ### General steps 1. Clone the repo to your local machine or Cloud Shell: + ```bash git clone https://github.com/GoogleCloudPlatform/cloud-foundation-fabric ``` 2. Change to the directory of the blueprint: + ```bash cd cloud-foundation-fabric/blueprints/serverless/cloud-run-corporate ``` + You should see this README and some terraform files. 3. To deploy a specific use case, you will need to create a file in this directory called `terraform.tfvars` and follow the corresponding instructions to set variables. Sometimes values that are meant to be substituted will be shown inside brackets but you need to omit these brackets. E.g.: + ```tfvars project_id = "[your-project_id]" ``` + may become + ```tfvars project_id = "spiritual-hour-331417" ``` @@ -55,6 +62,7 @@ project_id = "spiritual-hour-331417" Use cases are self-contained so you can deploy any of them at will. 4. The usual terraform commands will do the work: + ```bash terraform init terraform plan @@ -72,10 +80,13 @@ This use case deploys a Cloud Run service and a VM in the same project. To priva

In this case the only variable that you need to set in `terraform.tfvars` is the main project ID: + ```tfvars prj_main_id = "[your-main-project-id]" ``` + Alternatively you can pass this value on the command line: + ```bash terraform apply -var prj_main_id="[your-main-project-id]" ``` @@ -93,6 +104,7 @@ This use case deploys a Cloud Run service in a GCP project and simulates an on-p

You will need to set both the main and the on-prem project IDs in `terraform.tfvars`: + ```tfvars prj_main_id = "[your-main-project-id]" prj_onprem_id = "[your-onprem-project-id]" @@ -165,11 +177,11 @@ prj_svc1_id = "[your-service-project1-id]" ### Use case 4: Access to Cloud Run with custom domain -You need to use a L7 ILB with Serverless NEGs (in Preview) to set a custom domain for Cloud Run. As a practical example, this blueprint deploys this configuration in a Shared VPC environment with two Cloud Run services running in a service project and the ILB exposing them via a custom domain, pointing to them through a URL map: `/cart` and `/checkout`. +You need to use an Internal Application LB (L7) with Serverless NEGs (in Preview) to set a custom domain for Cloud Run. As a practical example, this blueprint deploys this configuration in a Shared VPC environment with two Cloud Run services running in a service project and the LB exposing them via a custom domain, pointing to them through a URL map: `/cart` and `/checkout`.

-The blueprint uses an HTTP connection to the ILB to avoid management of SSL certificates. To test access, VMs are created in the host and service projects. Set the following in `terraform.tfvars`: +The blueprint uses an HTTP connection to the LB to avoid management of SSL certificates. To test access, VMs are created in the host and service projects. Set the following in `terraform.tfvars`: ```tfvars prj_main_id = "[your-main-project-id]" # Used as host project @@ -184,9 +196,11 @@ SSH into a test VM and run `curl` specifying as URL the host, your custom domain ## Cleaning up your environment The easiest way to remove all the deployed resources is to run the following command: + ```bash terraform destroy ``` + The above command will delete the associated resources so there will be no billable charges made afterwards. Projects are removed from Terraform state but not deleted from Google Cloud. diff --git a/blueprints/serverless/cloud-run-corporate/main.tf b/blueprints/serverless/cloud-run-corporate/main.tf index 4266a65066..aca41c2847 100644 --- a/blueprints/serverless/cloud-run-corporate/main.tf +++ b/blueprints/serverless/cloud-run-corporate/main.tf @@ -349,7 +349,7 @@ resource "google_compute_global_forwarding_rule" "psc_endpoint_prj1" { ############################################################################### module "ilb-l7" { - source = "../../../modules/net-ilb-l7" + source = "../../../modules/net-lb-app-int" count = var.custom_domain == null ? 0 : 1 project_id = module.project_main.project_id name = "ilb-l7-cr" diff --git a/blueprints/serverless/cloud-run-explore/main.tf b/blueprints/serverless/cloud-run-explore/main.tf index e5ba9b034a..579f75b4cd 100644 --- a/blueprints/serverless/cloud-run-explore/main.tf +++ b/blueprints/serverless/cloud-run-explore/main.tf @@ -67,7 +67,7 @@ resource "google_compute_global_address" "default" { # Global L7 HTTPS Load Balancer in front of Cloud Run module "glb" { - source = "../../../modules/net-glb" + source = "../../../modules/net-lb-app-ext" count = local.gclb_create ? 1 : 0 project_id = module.project.project_id name = "glb" diff --git a/fast/stages/2-networking-a-peering/README.md b/fast/stages/2-networking-a-peering/README.md index 0edfe06f90..f7853f4a0e 100644 --- a/fast/stages/2-networking-a-peering/README.md +++ b/fast/stages/2-networking-a-peering/README.md @@ -88,7 +88,7 @@ Minimizing the number of routes (and subnets) in use on the cloud environment is This stage uses a dedicated /16 block (which should of course be sized to your needs) for each region in each VPC, and subnets created in each VPC derive their ranges from the relevant block. -Spoke VPCs also define and reserve two "special" CIDR ranges dedicated to [PSA (Private Service Access)](https://cloud.google.com/vpc/docs/private-services-access) and [Internal HTTPs Load Balancers (L7ILB)](https://cloud.google.com/load-balancing/docs/l7-internal). +Spoke VPCs also define and reserve two "special" CIDR ranges dedicated to [PSA (Private Service Access)](https://cloud.google.com/vpc/docs/private-services-access) and [Internal Application Load Balancers (L7 LBs)](https://cloud.google.com/load-balancing/docs/l7-internal). Routes in GCP are either automatically created for VPC subnets, manually created via static routes, or dynamically programmed by [Cloud Routers](https://cloud.google.com/network-connectivity/docs/router#docs) via BGP sessions, which can be configured to advertise VPC ranges, and/or custom ranges via custom advertisements. diff --git a/fast/stages/2-networking-b-vpn/README.md b/fast/stages/2-networking-b-vpn/README.md index c74cfb7943..75d8d91adc 100644 --- a/fast/stages/2-networking-b-vpn/README.md +++ b/fast/stages/2-networking-b-vpn/README.md @@ -86,7 +86,7 @@ Minimizing the number of routes (and subnets) in use on the cloud environment is This stage uses a dedicated /16 block (which should of course be sized to your needs) for each region in each VPC, and subnets created in each VPC derive their ranges from the relevant block. -Spoke VPCs also define and reserve two "special" CIDR ranges dedicated to [PSA (Private Service Access)](https://cloud.google.com/vpc/docs/private-services-access) and [Internal HTTPs Load Balancers (L7ILB)](https://cloud.google.com/load-balancing/docs/l7-internal). +Spoke VPCs also define and reserve two "special" CIDR ranges dedicated to [PSA (Private Service Access)](https://cloud.google.com/vpc/docs/private-services-access) and [Internal Application Load Balancers (L7 LBs)](https://cloud.google.com/load-balancing/docs/l7-internal). Routes in GCP are either automatically created for VPC subnets, manually created via static routes, or dynamically programmed by [Cloud Routers](https://cloud.google.com/network-connectivity/docs/router#docs) via BGP sessions, which can be configured to advertise VPC ranges, and/or custom ranges via custom advertisements. diff --git a/fast/stages/2-networking-c-nva/README.md b/fast/stages/2-networking-c-nva/README.md index 34443a18a1..a0f918a0b5 100644 --- a/fast/stages/2-networking-c-nva/README.md +++ b/fast/stages/2-networking-c-nva/README.md @@ -63,7 +63,7 @@ The final number of subnets, and their IP addressing will depend on the user-spe ### Multi-regional deployment -The stage deploys the the infrastructure in two regions. By default, europe-west1 and europe-west4. Regional resources include NVAs (templates, MIGs, ILBs) and test VMs. +The stage deploys the the infrastructure in two regions. By default, europe-west1 and europe-west4. Regional resources include NVAs (templates, MIGs, LBs) and test VMs. This provides enough redundancy to be resilient to regional failures. ### VPC design @@ -135,7 +135,7 @@ Spoke VPCs also define and reserve three "special" CIDR ranges, derived from the - The third-last /24 range is used for PSA (CloudSQL, MySQL) -- [Internal HTTPs Load Balancers (L7ILB)](https://cloud.google.com/load-balancing/docs/l7-internal): +- [Internal Application Load Balancers (L7 LBs)](https://cloud.google.com/load-balancing/docs/l7-internal): - The last /24 range diff --git a/fast/stages/2-networking-c-nva/nva.tf b/fast/stages/2-networking-c-nva/nva.tf index 62c45dbd22..9d09928251 100644 --- a/fast/stages/2-networking-c-nva/nva.tf +++ b/fast/stages/2-networking-c-nva/nva.tf @@ -124,7 +124,7 @@ module "ilb-nva-untrusted" { subnet = "${v}/landing-untrusted-default-${local.region_shortnames[v]}" } } - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" project_id = module.landing-project.project_id region = each.value.region name = "nva-untrusted-${each.key}" @@ -155,7 +155,7 @@ module "ilb-nva-trusted" { subnet = "${v}/landing-trusted-default-${local.region_shortnames[v]}" } } - source = "../../../modules/net-ilb" + source = "../../../modules/net-lb-int" project_id = module.landing-project.project_id region = each.value.region name = "nva-trusted-${each.key}" diff --git a/fast/stages/2-networking-d-separate-envs/README.md b/fast/stages/2-networking-d-separate-envs/README.md index 4b122ee2c1..1276799bd8 100644 --- a/fast/stages/2-networking-d-separate-envs/README.md +++ b/fast/stages/2-networking-d-separate-envs/README.md @@ -60,7 +60,7 @@ Minimizing the number of routes (and subnets) in use on the cloud environment is This stage uses a dedicated /16 block (which should of course be sized to your needs) shared by all regions and environments, and subnets created in each VPC derive their ranges from their relevant block. -Each VPC also defines and reserves two "special" CIDR ranges dedicated to [PSA (Private Service Access)](https://cloud.google.com/vpc/docs/private-services-access) and [Internal HTTPs Load Balancers (L7ILB)](https://cloud.google.com/load-balancing/docs/l7-internal). +Each VPC also defines and reserves two "special" CIDR ranges dedicated to [PSA (Private Service Access)](https://cloud.google.com/vpc/docs/private-services-access) and [Internal Application Load Balancers (L7 LBs)](https://cloud.google.com/load-balancing/docs/l7-internal). Routes in GCP are either automatically created for VPC subnets, manually created via static routes, or dynamically programmed by [Cloud Routers](https://cloud.google.com/network-connectivity/docs/router#docs) via BGP sessions, which can be configured to advertise VPC ranges, and/or custom ranges via custom advertisements. diff --git a/fast/stages/2-networking-e-nva-bgp/README.md b/fast/stages/2-networking-e-nva-bgp/README.md index 474644a54a..c5117b5db8 100644 --- a/fast/stages/2-networking-e-nva-bgp/README.md +++ b/fast/stages/2-networking-e-nva-bgp/README.md @@ -157,7 +157,7 @@ Spoke VPCs also define and reserve three "special" CIDR ranges, derived from the - The third-last /24 range is used for PSA (CloudSQL, MySQL) -- [Internal HTTPs Load Balancers (L7ILB)](https://cloud.google.com/load-balancing/docs/l7-internal): +- [Internal Application Load Balancers (L7 LBs)](https://cloud.google.com/load-balancing/docs/l7-internal): - The last /24 range diff --git a/modules/README.md b/modules/README.md index c1893e376d..0931c352a5 100644 --- a/modules/README.md +++ b/modules/README.md @@ -45,11 +45,11 @@ These modules are used in the examples included in this repository. If you are u - [Cloud Endpoints](./endpoints) - [DNS](./dns) - [DNS Response Policy](./dns-response-policy/) -- [Global Load Balancer](./net-glb/) -- [L4 ILB](./net-ilb) -- [L7 ILB](./net-ilb-l7) +- [External Application Load Balancer](./net-lb-app-ext/) +- [External Network Passthrough Load Balancer](./net-lb-ext) +- [Internal Application LB](./net-lb-app-int) +- [Internal Network Passthrough Load Balancer](./net-lb-int) - [NAT](./net-cloudnat) -- [Network Load Balancer](./net-nlb) - [Service Directory](./service-directory) - [VPC](./net-vpc) - [VPC firewall](./net-vpc-firewall) diff --git a/modules/compute-mig/README.md b/modules/compute-mig/README.md index 9eb9433d57..ef87d085ec 100644 --- a/modules/compute-mig/README.md +++ b/modules/compute-mig/README.md @@ -2,7 +2,7 @@ This module allows creating a managed instance group supporting one or more application versions via instance templates. Optionally, a health check and an autoscaler can be created, and the managed instance group can be configured to be stateful. -This module can be coupled with the [`compute-vm`](../compute-vm) module which can manage instance templates, and the [`net-ilb`](../net-ilb) module to assign the MIG to a backend wired to an Internal Load Balancer. The first use case is shown in the examples below. +This module can be coupled with the [`compute-vm`](../compute-vm) module which can manage instance templates, and the [`net-lb-int`](../net-lb-int) module to assign the MIG to a backend wired to an Internal Load Balancer. The first use case is shown in the examples below. Stateful disks can be created directly, as shown in the last example below. diff --git a/modules/net-glb/.gitignore b/modules/net-lb-app-ext/.gitignore similarity index 100% rename from modules/net-glb/.gitignore rename to modules/net-lb-app-ext/.gitignore diff --git a/modules/net-glb/README.md b/modules/net-lb-app-ext/README.md similarity index 98% rename from modules/net-glb/README.md rename to modules/net-lb-app-ext/README.md index deeb1c7b78..3648fabb96 100644 --- a/modules/net-glb/README.md +++ b/modules/net-lb-app-ext/README.md @@ -1,4 +1,4 @@ -# Global HTTP/S Classic Load Balancer Module +# External Application Load Balancer Module This module allows managing Global HTTP/HTTPS Classic Load Balancers (GLBs). It's designed to expose the full configuration of the underlying resources, and to facilitate common usage patterns by providing sensible defaults, and optionally managing prerequisite resources like health checks, instance groups, etc. @@ -27,7 +27,7 @@ An HTTP load balancer with a backend service pointing to a GCE instance group: ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -50,7 +50,7 @@ An HTTPS load balancer needs a certificate and backends can be HTTP or HTTPS. TH ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -80,7 +80,7 @@ For HTTPS backends the backend service protocol needs to be set to `HTTPS`. The ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -117,7 +117,7 @@ The module uses a classic Global Load Balancer by default. To use the non-classi ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" use_classic_version = false @@ -143,7 +143,7 @@ Health checks created by this module are controlled via the `health_check_config ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = var.project_id name = "glb-test-0" backend_service_configs = { @@ -168,7 +168,7 @@ To leverage existing health checks without having the module create them, simply ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = var.project_id name = "glb-test-0" backend_service_configs = { @@ -192,7 +192,7 @@ The module can optionally create unmanaged instance groups, which can then be re ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -263,7 +263,7 @@ module "win-mig" { } module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -283,7 +283,7 @@ GCS bucket backends can also be managed and used in this module in a similar way ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_buckets_config = { @@ -303,7 +303,7 @@ Supported Network Endpoint Groups (NEGs) can also be used as backends. Similarly ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -327,7 +327,7 @@ This example shows how to create and manage zonal NEGs using GCE VMs as endpoint ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -367,7 +367,7 @@ This example shows how to create and manage hybrid NEGs: ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -405,7 +405,7 @@ This example shows how to create and manage internet NEGs: ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -441,7 +441,7 @@ The module supports managing PSC NEGs if the non-classic version of the load bal ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" use_classic_version = false @@ -473,7 +473,7 @@ The module supports managing Serverless NEGs for Cloud Run and Cloud Function. T ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -504,7 +504,7 @@ Serverless NEGs don't use the port name but it should be set to `http`. An HTTPS ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -548,7 +548,7 @@ The default URL map configuration sets the `default` backend service as the defa ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -611,7 +611,7 @@ resource "tls_self_signed_cert" "default" { } module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_service_configs = { @@ -643,7 +643,7 @@ This example mixes group and NEG backends, and shows how to set HTTPS for specif ```hcl module "glb-0" { - source = "./fabric/modules/net-glb" + source = "./fabric/modules/net-lb-app-ext" project_id = "myprj" name = "glb-test-0" backend_buckets_config = { diff --git a/modules/net-glb/backend-service.tf b/modules/net-lb-app-ext/backend-service.tf similarity index 100% rename from modules/net-glb/backend-service.tf rename to modules/net-lb-app-ext/backend-service.tf diff --git a/modules/net-glb/backends.tf b/modules/net-lb-app-ext/backends.tf similarity index 100% rename from modules/net-glb/backends.tf rename to modules/net-lb-app-ext/backends.tf diff --git a/modules/net-glb/health-check.tf b/modules/net-lb-app-ext/health-check.tf similarity index 100% rename from modules/net-glb/health-check.tf rename to modules/net-lb-app-ext/health-check.tf diff --git a/modules/net-glb/main.tf b/modules/net-lb-app-ext/main.tf similarity index 100% rename from modules/net-glb/main.tf rename to modules/net-lb-app-ext/main.tf diff --git a/modules/net-glb/negs.tf b/modules/net-lb-app-ext/negs.tf similarity index 100% rename from modules/net-glb/negs.tf rename to modules/net-lb-app-ext/negs.tf diff --git a/modules/net-glb/outputs.tf b/modules/net-lb-app-ext/outputs.tf similarity index 100% rename from modules/net-glb/outputs.tf rename to modules/net-lb-app-ext/outputs.tf diff --git a/modules/net-glb/urlmap.tf b/modules/net-lb-app-ext/urlmap.tf similarity index 100% rename from modules/net-glb/urlmap.tf rename to modules/net-lb-app-ext/urlmap.tf diff --git a/modules/net-glb/variables-backend-service.tf b/modules/net-lb-app-ext/variables-backend-service.tf similarity index 100% rename from modules/net-glb/variables-backend-service.tf rename to modules/net-lb-app-ext/variables-backend-service.tf diff --git a/modules/net-glb/variables-health-check.tf b/modules/net-lb-app-ext/variables-health-check.tf similarity index 100% rename from modules/net-glb/variables-health-check.tf rename to modules/net-lb-app-ext/variables-health-check.tf diff --git a/modules/net-glb/variables-urlmap.tf b/modules/net-lb-app-ext/variables-urlmap.tf similarity index 100% rename from modules/net-glb/variables-urlmap.tf rename to modules/net-lb-app-ext/variables-urlmap.tf diff --git a/modules/net-glb/variables.tf b/modules/net-lb-app-ext/variables.tf similarity index 100% rename from modules/net-glb/variables.tf rename to modules/net-lb-app-ext/variables.tf diff --git a/modules/net-glb/versions.tf b/modules/net-lb-app-ext/versions.tf similarity index 100% rename from modules/net-glb/versions.tf rename to modules/net-lb-app-ext/versions.tf diff --git a/modules/net-ilb-l7/README.md b/modules/net-lb-app-int/README.md similarity index 98% rename from modules/net-ilb-l7/README.md rename to modules/net-lb-app-int/README.md index 597d580c96..e4057c1fec 100644 --- a/modules/net-ilb-l7/README.md +++ b/modules/net-lb-app-int/README.md @@ -1,4 +1,4 @@ -# Internal (HTTP/S) Load Balancer Module +# Internal Application Load Balancer Module This module allows managing Internal HTTP/HTTPS Load Balancers (L7 ILBs). It's designed to expose the full configuration of the underlying resources, and to facilitate common usage patterns by providing sensible defaults, and optionally managing prerequisite resources like health checks, instance groups, etc. @@ -21,7 +21,7 @@ An HTTP ILB with a backend service pointing to a GCE instance group: ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -44,7 +44,7 @@ An HTTPS ILB needs a few additional fields: ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -75,7 +75,7 @@ When using Shared VPC, this module also allows configuring [cross-project backen ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = "prj-host" region = "europe-west1" @@ -113,7 +113,7 @@ Defining different health checks from the default is very easy. You can for exam ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -142,7 +142,7 @@ To leverage existing health checks without having the module create them, simply ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -169,7 +169,7 @@ The module can optionally create unmanaged instance groups, which can then be re ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -204,7 +204,7 @@ Network Endpoint Groups (NEGs) can be used as backends, by passing their id as t ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -239,7 +239,7 @@ resource "google_compute_address" "test" { } module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -279,7 +279,7 @@ module "ilb-l7" { ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -313,7 +313,7 @@ module "ilb-l7" { ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -350,7 +350,7 @@ module "ilb-l7" { ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -387,7 +387,7 @@ The default URL map configuration sets the `default` backend service as the defa ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -454,7 +454,7 @@ resource "tls_self_signed_cert" "default" { } module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-test" project_id = var.project_id region = "europe-west1" @@ -494,7 +494,7 @@ This example mixes group and NEG backends, and shows how to set HTTPS for specif ```hcl module "ilb-l7" { - source = "./fabric/modules/net-ilb-l7" + source = "./fabric/modules/net-lb-app-int" name = "ilb-l7-test-0" project_id = "prj-gce" region = "europe-west8" diff --git a/modules/net-ilb-l7/backend-service.tf b/modules/net-lb-app-int/backend-service.tf similarity index 100% rename from modules/net-ilb-l7/backend-service.tf rename to modules/net-lb-app-int/backend-service.tf diff --git a/modules/net-ilb-l7/health-check.tf b/modules/net-lb-app-int/health-check.tf similarity index 100% rename from modules/net-ilb-l7/health-check.tf rename to modules/net-lb-app-int/health-check.tf diff --git a/modules/net-ilb-l7/main.tf b/modules/net-lb-app-int/main.tf similarity index 100% rename from modules/net-ilb-l7/main.tf rename to modules/net-lb-app-int/main.tf diff --git a/modules/net-ilb-l7/outputs.tf b/modules/net-lb-app-int/outputs.tf similarity index 100% rename from modules/net-ilb-l7/outputs.tf rename to modules/net-lb-app-int/outputs.tf diff --git a/modules/net-ilb-l7/urlmap.tf b/modules/net-lb-app-int/urlmap.tf similarity index 100% rename from modules/net-ilb-l7/urlmap.tf rename to modules/net-lb-app-int/urlmap.tf diff --git a/modules/net-ilb-l7/variables-backend-service.tf b/modules/net-lb-app-int/variables-backend-service.tf similarity index 100% rename from modules/net-ilb-l7/variables-backend-service.tf rename to modules/net-lb-app-int/variables-backend-service.tf diff --git a/modules/net-ilb-l7/variables-health-check.tf b/modules/net-lb-app-int/variables-health-check.tf similarity index 100% rename from modules/net-ilb-l7/variables-health-check.tf rename to modules/net-lb-app-int/variables-health-check.tf diff --git a/modules/net-ilb-l7/variables-urlmap.tf b/modules/net-lb-app-int/variables-urlmap.tf similarity index 100% rename from modules/net-ilb-l7/variables-urlmap.tf rename to modules/net-lb-app-int/variables-urlmap.tf diff --git a/modules/net-ilb-l7/variables.tf b/modules/net-lb-app-int/variables.tf similarity index 100% rename from modules/net-ilb-l7/variables.tf rename to modules/net-lb-app-int/variables.tf diff --git a/modules/net-ilb-l7/versions.tf b/modules/net-lb-app-int/versions.tf similarity index 100% rename from modules/net-ilb-l7/versions.tf rename to modules/net-lb-app-int/versions.tf diff --git a/modules/net-nlb/README.md b/modules/net-lb-ext/README.md similarity index 98% rename from modules/net-nlb/README.md rename to modules/net-lb-ext/README.md index a890e2e1b1..3c38a7d273 100644 --- a/modules/net-nlb/README.md +++ b/modules/net-lb-ext/README.md @@ -1,4 +1,4 @@ -# Network Load Balancer Module +# External Passthrough Network Load Balancer Module This module allows managing a GCE Network Load Balancer and integrates the forwarding rule, regional backend, and optional health check resources. It's designed to be a simple match for the [`compute-vm`](../compute-vm) module, which can be used to manage instance templates and instance groups. @@ -43,7 +43,7 @@ module "mig" { } module "nlb" { - source = "./fabric/modules/net-nlb" + source = "./fabric/modules/net-lb-ext" project_id = var.project_id region = "europe-west1" name = "nlb-test" @@ -65,7 +65,7 @@ This examples shows how to create an NLB by combining externally managed instanc ```hcl module "nlb" { - source = "./fabric/modules/net-nlb" + source = "./fabric/modules/net-lb-ext" project_id = var.project_id region = "europe-west1" name = "nlb-test" @@ -132,7 +132,7 @@ module "instance-group" { } module "nlb" { - source = "./fabric/modules/net-nlb" + source = "./fabric/modules/net-lb-ext" project_id = var.project_id region = "europe-west1" name = "nlb-test" diff --git a/modules/net-nlb/groups.tf b/modules/net-lb-ext/groups.tf similarity index 100% rename from modules/net-nlb/groups.tf rename to modules/net-lb-ext/groups.tf diff --git a/modules/net-nlb/health-check.tf b/modules/net-lb-ext/health-check.tf similarity index 100% rename from modules/net-nlb/health-check.tf rename to modules/net-lb-ext/health-check.tf diff --git a/modules/net-nlb/main.tf b/modules/net-lb-ext/main.tf similarity index 100% rename from modules/net-nlb/main.tf rename to modules/net-lb-ext/main.tf diff --git a/modules/net-nlb/outputs.tf b/modules/net-lb-ext/outputs.tf similarity index 100% rename from modules/net-nlb/outputs.tf rename to modules/net-lb-ext/outputs.tf diff --git a/modules/net-nlb/variables.tf b/modules/net-lb-ext/variables.tf similarity index 100% rename from modules/net-nlb/variables.tf rename to modules/net-lb-ext/variables.tf diff --git a/modules/net-ilb/versions.tf b/modules/net-lb-ext/versions.tf similarity index 100% rename from modules/net-ilb/versions.tf rename to modules/net-lb-ext/versions.tf diff --git a/modules/net-ilb/README.md b/modules/net-lb-int/README.md similarity index 98% rename from modules/net-ilb/README.md rename to modules/net-lb-int/README.md index 5f68d8ac55..b7f1a91c5f 100644 --- a/modules/net-ilb/README.md +++ b/modules/net-lb-int/README.md @@ -1,4 +1,4 @@ -# Internal Load Balancer Module +# Internal Passthrough Network Load Balancer Module This module allows managing a GCE Internal Load Balancer and integrates the forwarding rule, regional backend, and optional health check resources. It's designed to be a simple match for the [`compute-vm`](../compute-vm) module, which can be used to manage instance templates and instance groups. @@ -51,7 +51,7 @@ module "mig" { } module "ilb" { - source = "./fabric/modules/net-ilb" + source = "./fabric/modules/net-lb-int" project_id = var.project_id region = "europe-west1" name = "ilb-test" @@ -78,7 +78,7 @@ This examples shows how to create an ILB by combining externally managed instanc ```hcl module "ilb" { - source = "./fabric/modules/net-ilb" + source = "./fabric/modules/net-lb-int" project_id = var.project_id region = "europe-west1" name = "ilb-test" @@ -150,7 +150,7 @@ module "instance-group" { } module "ilb" { - source = "./fabric/modules/net-ilb" + source = "./fabric/modules/net-lb-int" project_id = var.project_id region = "europe-west1" name = "ilb-test" diff --git a/modules/net-ilb/groups.tf b/modules/net-lb-int/groups.tf similarity index 100% rename from modules/net-ilb/groups.tf rename to modules/net-lb-int/groups.tf diff --git a/modules/net-ilb/health-check.tf b/modules/net-lb-int/health-check.tf similarity index 100% rename from modules/net-ilb/health-check.tf rename to modules/net-lb-int/health-check.tf diff --git a/modules/net-ilb/main.tf b/modules/net-lb-int/main.tf similarity index 100% rename from modules/net-ilb/main.tf rename to modules/net-lb-int/main.tf diff --git a/modules/net-ilb/outputs.tf b/modules/net-lb-int/outputs.tf similarity index 100% rename from modules/net-ilb/outputs.tf rename to modules/net-lb-int/outputs.tf diff --git a/modules/net-ilb/variables.tf b/modules/net-lb-int/variables.tf similarity index 100% rename from modules/net-ilb/variables.tf rename to modules/net-lb-int/variables.tf diff --git a/modules/net-nlb/versions.tf b/modules/net-lb-int/versions.tf similarity index 100% rename from modules/net-nlb/versions.tf rename to modules/net-lb-int/versions.tf diff --git a/tests/modules/net_glb/examples/https-sneg.yaml b/tests/modules/net_lb_app_ext/examples/https-sneg.yaml similarity index 100% rename from tests/modules/net_glb/examples/https-sneg.yaml rename to tests/modules/net_lb_app_ext/examples/https-sneg.yaml diff --git a/tests/modules/net_glb/test-plan.tfvars b/tests/modules/net_lb_app_ext/test-plan.tfvars similarity index 100% rename from tests/modules/net_glb/test-plan.tfvars rename to tests/modules/net_lb_app_ext/test-plan.tfvars diff --git a/tests/modules/net_glb/test-plan.yaml b/tests/modules/net_lb_app_ext/test-plan.yaml similarity index 100% rename from tests/modules/net_glb/test-plan.yaml rename to tests/modules/net_lb_app_ext/test-plan.yaml diff --git a/tests/modules/net_glb/tftest.yaml b/tests/modules/net_lb_app_ext/tftest.yaml similarity index 95% rename from tests/modules/net_glb/tftest.yaml rename to tests/modules/net_lb_app_ext/tftest.yaml index 4130f2a504..6e242ecd40 100644 --- a/tests/modules/net_glb/tftest.yaml +++ b/tests/modules/net_lb_app_ext/tftest.yaml @@ -12,6 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -module: modules/net-glb +module: modules/net-lb-app-ext tests: test-plan: diff --git a/tests/modules/net_ilb_l7/__init__.py b/tests/modules/net_lb_app_int/__init__.py similarity index 100% rename from tests/modules/net_ilb_l7/__init__.py rename to tests/modules/net_lb_app_int/__init__.py diff --git a/tests/modules/net_ilb_l7/common.tfvars b/tests/modules/net_lb_app_int/common.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/common.tfvars rename to tests/modules/net_lb_app_int/common.tfvars diff --git a/tests/modules/net_ilb_l7/defaults.tfvars b/tests/modules/net_lb_app_int/defaults.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/defaults.tfvars rename to tests/modules/net_lb_app_int/defaults.tfvars diff --git a/tests/modules/net_ilb_l7/defaults.yaml b/tests/modules/net_lb_app_int/defaults.yaml similarity index 100% rename from tests/modules/net_ilb_l7/defaults.yaml rename to tests/modules/net_lb_app_int/defaults.yaml diff --git a/tests/modules/net_ilb_l7/groups.tfvars b/tests/modules/net_lb_app_int/groups.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/groups.tfvars rename to tests/modules/net_lb_app_int/groups.tfvars diff --git a/tests/modules/net_ilb_l7/groups.yaml b/tests/modules/net_lb_app_int/groups.yaml similarity index 100% rename from tests/modules/net_ilb_l7/groups.yaml rename to tests/modules/net_lb_app_int/groups.yaml diff --git a/tests/modules/net_ilb_l7/health-checks-custom.tfvars b/tests/modules/net_lb_app_int/health-checks-custom.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/health-checks-custom.tfvars rename to tests/modules/net_lb_app_int/health-checks-custom.tfvars diff --git a/tests/modules/net_ilb_l7/health-checks-custom.yaml b/tests/modules/net_lb_app_int/health-checks-custom.yaml similarity index 100% rename from tests/modules/net_ilb_l7/health-checks-custom.yaml rename to tests/modules/net_lb_app_int/health-checks-custom.yaml diff --git a/tests/modules/net_ilb_l7/health-checks-external.tfvars b/tests/modules/net_lb_app_int/health-checks-external.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/health-checks-external.tfvars rename to tests/modules/net_lb_app_int/health-checks-external.tfvars diff --git a/tests/modules/net_ilb_l7/health-checks-external.yaml b/tests/modules/net_lb_app_int/health-checks-external.yaml similarity index 100% rename from tests/modules/net_ilb_l7/health-checks-external.yaml rename to tests/modules/net_lb_app_int/health-checks-external.yaml diff --git a/tests/modules/net_ilb_l7/https.tfvars b/tests/modules/net_lb_app_int/https.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/https.tfvars rename to tests/modules/net_lb_app_int/https.tfvars diff --git a/tests/modules/net_ilb_l7/https.yaml b/tests/modules/net_lb_app_int/https.yaml similarity index 100% rename from tests/modules/net_ilb_l7/https.yaml rename to tests/modules/net_lb_app_int/https.yaml diff --git a/tests/modules/net_ilb_l7/negs.tfvars b/tests/modules/net_lb_app_int/negs.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/negs.tfvars rename to tests/modules/net_lb_app_int/negs.tfvars diff --git a/tests/modules/net_ilb_l7/negs.yaml b/tests/modules/net_lb_app_int/negs.yaml similarity index 100% rename from tests/modules/net_ilb_l7/negs.yaml rename to tests/modules/net_lb_app_int/negs.yaml diff --git a/tests/modules/net_ilb_l7/ssl.tfvars b/tests/modules/net_lb_app_int/ssl.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/ssl.tfvars rename to tests/modules/net_lb_app_int/ssl.tfvars diff --git a/tests/modules/net_ilb_l7/ssl.yaml b/tests/modules/net_lb_app_int/ssl.yaml similarity index 100% rename from tests/modules/net_ilb_l7/ssl.yaml rename to tests/modules/net_lb_app_int/ssl.yaml diff --git a/tests/modules/net_ilb_l7/tftest.yaml b/tests/modules/net_lb_app_int/tftest.yaml similarity index 95% rename from tests/modules/net_ilb_l7/tftest.yaml rename to tests/modules/net_lb_app_int/tftest.yaml index 099fc71b58..4fd90dc358 100644 --- a/tests/modules/net_ilb_l7/tftest.yaml +++ b/tests/modules/net_lb_app_int/tftest.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -module: modules/net-ilb-l7 +module: modules/net-lb-app-int common_tfvars: - common.tfvars tests: diff --git a/tests/modules/net_ilb_l7/urlmaps.tfvars b/tests/modules/net_lb_app_int/urlmaps.tfvars similarity index 100% rename from tests/modules/net_ilb_l7/urlmaps.tfvars rename to tests/modules/net_lb_app_int/urlmaps.tfvars diff --git a/tests/modules/net_ilb_l7/urlmaps.yaml b/tests/modules/net_lb_app_int/urlmaps.yaml similarity index 100% rename from tests/modules/net_ilb_l7/urlmaps.yaml rename to tests/modules/net_lb_app_int/urlmaps.yaml diff --git a/tests/modules/net_ilb/defaults.tfvars b/tests/modules/net_lb_int/defaults.tfvars similarity index 100% rename from tests/modules/net_ilb/defaults.tfvars rename to tests/modules/net_lb_int/defaults.tfvars diff --git a/tests/modules/net_ilb/defaults.yaml b/tests/modules/net_lb_int/defaults.yaml similarity index 100% rename from tests/modules/net_ilb/defaults.yaml rename to tests/modules/net_lb_int/defaults.yaml diff --git a/tests/modules/net_ilb/forwarding-rule.tfvars b/tests/modules/net_lb_int/forwarding-rule.tfvars similarity index 100% rename from tests/modules/net_ilb/forwarding-rule.tfvars rename to tests/modules/net_lb_int/forwarding-rule.tfvars diff --git a/tests/modules/net_ilb/forwarding-rule.yaml b/tests/modules/net_lb_int/forwarding-rule.yaml similarity index 100% rename from tests/modules/net_ilb/forwarding-rule.yaml rename to tests/modules/net_lb_int/forwarding-rule.yaml diff --git a/tests/modules/net_ilb/tftest.yaml b/tests/modules/net_lb_int/tftest.yaml similarity index 95% rename from tests/modules/net_ilb/tftest.yaml rename to tests/modules/net_lb_int/tftest.yaml index aa1b8e4a5d..5cc14ee222 100644 --- a/tests/modules/net_ilb/tftest.yaml +++ b/tests/modules/net_lb_int/tftest.yaml @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -module: modules/net-ilb +module: modules/net-lb-int tests: defaults: From 2c7c41b25f03ebaafe6c27943f391287e0917aff Mon Sep 17 00:00:00 2001 From: Miren Esnaola Date: Mon, 26 Jun 2023 09:51:28 +0200 Subject: [PATCH 10/16] Dependencies update for API Gateway blueprint --- .../api-gateway/function/package-lock.json | 1328 +++++++---------- .../api-gateway/function/package.json | 4 +- 2 files changed, 568 insertions(+), 764 deletions(-) diff --git a/blueprints/serverless/api-gateway/function/package-lock.json b/blueprints/serverless/api-gateway/function/package-lock.json index da027c38b8..20d382dd3f 100644 --- a/blueprints/serverless/api-gateway/function/package-lock.json +++ b/blueprints/serverless/api-gateway/function/package-lock.json @@ -9,8 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@google-cloud/functions-framework": "^3.0.0", - "express": "^4.17.3" + "@google-cloud/functions-framework": "^3.2.1", + "express": "^4.18.2" }, "engines": { "node": ">=16.0.0" @@ -49,14 +49,15 @@ } }, "node_modules/@google-cloud/functions-framework": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/functions-framework/-/functions-framework-3.0.0.tgz", - "integrity": "sha512-+K9+y39/5ig4QrbnaCM8BOzt4+Qx5SRMu2dj5QDTNFc5s8f/Lubty8u3aBQN6JC86M0NuHL9zIj8xs8Awj7C+w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@google-cloud/functions-framework/-/functions-framework-3.2.1.tgz", + "integrity": "sha512-sWpJOAh9tpa1rznTxo90i/iOzG5MYAKGVjqLVh/NgxVYCYQvwrJ2ypuV0wROuS5mIpNvyGUyMfLn4nXeE3TrCQ==", "dependencies": { + "@types/express": "4.17.17", "body-parser": "^1.18.3", - "cloudevents": "^5.1.0", + "cloudevents": "^7.0.0", "express": "^4.16.4", - "minimist": "^1.2.5", + "minimist": "^1.2.7", "on-finished": "^2.3.0", "read-pkg-up": "^7.0.1", "semver": "^7.3.5" @@ -69,11 +70,94 @@ "node": ">=10.0.0" } }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/node": { + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", + "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" + }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -87,13 +171,13 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -101,6 +185,22 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -128,24 +228,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/bignumber.js": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "engines": { + "node": "*" + } + }, "node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/bytes": { @@ -182,13 +293,19 @@ } }, "node_modules/cloudevents": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-5.3.2.tgz", - "integrity": "sha512-ZjEFjx0BJnio8SED1TzD7GHA118zCk04Mz6aDMMii+4/ZvX5LPgn1D4lT5Jj7HodCbdeRS6dX88unH06Qc3mkA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-7.0.1.tgz", + "integrity": "sha512-/i7HRvIUG2RAiB9AD6TqUd07H2ZkJtwCrNpGa4vJftwz5uJdD/bO+u3kYs/r+kQCtZ6uhZs0I9vfIhuhorKUHw==", "dependencies": { - "ajv": "~6.12.3", + "ajv": "^8.11.0", + "ajv-formats": "^2.1.1", + "json-bigint": "^1.0.0", + "process": "^0.11.10", "util": "^0.12.4", - "uuid": "~8.3.0" + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=16 <=20" } }, "node_modules/color-convert": { @@ -224,9 +341,9 @@ } }, "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -244,29 +361,22 @@ "ms": "2.0.0" } }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/ee-first": { "version": "1.1.1", @@ -276,7 +386,7 @@ "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "engines": { "node": ">= 0.8" } @@ -289,59 +399,10 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { "version": "1.0.5", @@ -354,43 +415,44 @@ "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "engines": { "node": ">= 0.6" } }, "node_modules/express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.2", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.2", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.7", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", + "send": "0.18.0", + "serve-static": "1.15.0", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -404,22 +466,17 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "node_modules/finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" }, "engines": { @@ -438,10 +495,13 @@ "node": ">=8" } }, - "node_modules/foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } }, "node_modules/forwarded": { "version": "0.2.0", @@ -454,7 +514,7 @@ "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "engines": { "node": ">= 0.6" } @@ -465,28 +525,25 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "get-intrinsic": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -503,14 +560,6 @@ "node": ">= 0.4.0" } }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -519,10 +568,21 @@ "node": ">=4" } }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "engines": { "node": ">= 0.4" }, @@ -550,18 +610,18 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/iconv-lite": { @@ -580,19 +640,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -621,36 +668,10 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { "node": ">= 0.4" }, @@ -669,20 +690,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -697,91 +704,15 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" }, "engines": { @@ -791,31 +722,28 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/lines-and-columns": { "version": "1.2.4", @@ -896,9 +824,12 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/ms": { "version": "2.0.0", @@ -933,42 +864,17 @@ } }, "node_modules/object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -1052,6 +958,14 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -1065,17 +979,20 @@ } }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, "engines": { "node": ">=0.6" }, @@ -1092,12 +1009,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { "bytes": "3.1.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -1143,6 +1060,14 @@ "node": ">=8" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -1198,23 +1123,23 @@ } }, "node_modules/send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "dependencies": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "engines": { "node": ">= 0.8.0" @@ -1226,14 +1151,14 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.2" + "send": "0.18.0" }, "engines": { "node": ">= 0.8.0" @@ -1286,35 +1211,11 @@ "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" }, "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", "engines": { - "node": ">= 0.6" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, "node_modules/supports-color": { @@ -1367,24 +1268,10 @@ "node": ">= 0.6" } }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "engines": { "node": ">= 0.8" } @@ -1398,15 +1285,14 @@ } }, "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "dependencies": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", "which-typed-array": "^1.1.2" } }, @@ -1443,32 +1329,17 @@ "node": ">= 0.8" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" + "is-typed-array": "^1.1.10" }, "engines": { "node": ">= 0.4" @@ -1508,24 +1379,108 @@ } }, "@google-cloud/functions-framework": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@google-cloud/functions-framework/-/functions-framework-3.0.0.tgz", - "integrity": "sha512-+K9+y39/5ig4QrbnaCM8BOzt4+Qx5SRMu2dj5QDTNFc5s8f/Lubty8u3aBQN6JC86M0NuHL9zIj8xs8Awj7C+w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@google-cloud/functions-framework/-/functions-framework-3.2.1.tgz", + "integrity": "sha512-sWpJOAh9tpa1rznTxo90i/iOzG5MYAKGVjqLVh/NgxVYCYQvwrJ2ypuV0wROuS5mIpNvyGUyMfLn4nXeE3TrCQ==", "requires": { + "@types/express": "4.17.17", "body-parser": "^1.18.3", - "cloudevents": "^5.1.0", + "cloudevents": "^7.0.0", "express": "^4.16.4", - "minimist": "^1.2.5", + "minimist": "^1.2.7", "on-finished": "^2.3.0", "read-pkg-up": "^7.0.1", "semver": "^7.3.5" } }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "@types/node": { + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", + "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" + }, "@types/normalize-package-data": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==" }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -1536,16 +1491,24 @@ } }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "requires": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" } }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + } + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -1564,21 +1527,28 @@ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, + "bignumber.js": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==" + }, "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", "requires": { "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" } }, "bytes": { @@ -1606,13 +1576,16 @@ } }, "cloudevents": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-5.3.2.tgz", - "integrity": "sha512-ZjEFjx0BJnio8SED1TzD7GHA118zCk04Mz6aDMMii+4/ZvX5LPgn1D4lT5Jj7HodCbdeRS6dX88unH06Qc3mkA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-7.0.1.tgz", + "integrity": "sha512-/i7HRvIUG2RAiB9AD6TqUd07H2ZkJtwCrNpGa4vJftwz5uJdD/bO+u3kYs/r+kQCtZ6uhZs0I9vfIhuhorKUHw==", "requires": { - "ajv": "~6.12.3", + "ajv": "^8.11.0", + "ajv-formats": "^2.1.1", + "json-bigint": "^1.0.0", + "process": "^0.11.10", "util": "^0.12.4", - "uuid": "~8.3.0" + "uuid": "^8.3.2" } }, "color-convert": { @@ -1642,9 +1615,9 @@ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, "cookie-signature": { "version": "1.0.6", @@ -1659,23 +1632,15 @@ "ms": "2.0.0" } }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "requires": { - "object-keys": "^1.0.12" - } - }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, "ee-first": { "version": "1.1.1", @@ -1685,7 +1650,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" }, "error-ex": { "version": "1.3.2", @@ -1695,47 +1660,10 @@ "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.1", - "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "escape-string-regexp": { "version": "1.0.5", @@ -1745,40 +1673,41 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, "express": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", - "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.19.2", + "body-parser": "1.20.1", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.4.2", + "cookie": "0.5.0", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "~1.1.2", + "depd": "2.0.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.1.2", + "finalhandler": "1.2.0", "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.1", "methods": "~1.1.2", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", "path-to-regexp": "0.1.7", "proxy-addr": "~2.0.7", - "qs": "6.9.7", + "qs": "6.11.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.17.2", - "serve-static": "1.14.2", + "send": "0.18.0", + "serve-static": "1.15.0", "setprototypeof": "1.2.0", - "statuses": "~1.5.0", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -1789,22 +1718,17 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", "requires": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "statuses": "~1.5.0", + "statuses": "2.0.1", "unpipe": "~1.0.0" } }, @@ -1817,10 +1741,13 @@ "path-exists": "^4.0.0" } }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } }, "forwarded": { "version": "0.2.0", @@ -1830,7 +1757,7 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, "function-bind": { "version": "1.1.1", @@ -1838,22 +1765,22 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1" + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" } }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.1.3" } }, "has": { @@ -1864,20 +1791,20 @@ "function-bind": "^1.1.1" } }, - "has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==" - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, "has-tostringtag": { "version": "1.0.0", @@ -1893,14 +1820,14 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" }, "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" } }, @@ -1917,16 +1844,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -1946,27 +1863,10 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, "is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, "is-core-module": { "version": "2.8.1", @@ -1976,14 +1876,6 @@ "has": "^1.0.3" } }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, "is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -1992,83 +1884,40 @@ "has-tostringtag": "^1.0.0" } }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" - }, - "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==" - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "requires": { - "has-symbols": "^1.0.2" - } - }, "is-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.8.tgz", - "integrity": "sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", "requires": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" } }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "requires": { - "call-bind": "^1.0.2" - } - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "lines-and-columns": { "version": "1.2.4", @@ -2125,9 +1974,9 @@ } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "ms": { "version": "2.0.0", @@ -2158,30 +2007,14 @@ } }, "object-inspect": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", - "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" - }, - "object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -2238,6 +2071,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2248,14 +2086,17 @@ } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" }, "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } }, "range-parser": { "version": "1.2.1", @@ -2263,12 +2104,12 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { "bytes": "3.1.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" } @@ -2301,6 +2142,11 @@ "type-fest": "^0.8.1" } }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -2330,23 +2176,23 @@ } }, "send": { - "version": "0.17.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", - "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", "requires": { "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", + "depd": "2.0.0", + "destroy": "1.2.0", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "0.5.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "mime": "1.6.0", "ms": "2.1.3", - "on-finished": "~2.3.0", + "on-finished": "2.4.1", "range-parser": "~1.2.1", - "statuses": "~1.5.0" + "statuses": "2.0.1" }, "dependencies": { "ms": { @@ -2357,14 +2203,14 @@ } }, "serve-static": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", - "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", "requires": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.17.2" + "send": "0.18.0" } }, "setprototypeof": { @@ -2411,27 +2257,9 @@ "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" }, "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, "supports-color": { "version": "5.5.0", @@ -2465,21 +2293,10 @@ "mime-types": "~2.1.24" } }, - "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - } - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "uri-js": { "version": "4.4.1", @@ -2490,15 +2307,14 @@ } }, "util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "requires": { "inherits": "^2.0.3", "is-arguments": "^1.0.4", "is-generator-function": "^1.0.7", "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", "which-typed-array": "^1.1.2" } }, @@ -2526,29 +2342,17 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, "which-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.7.tgz", - "integrity": "sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", "requires": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", + "for-each": "^0.3.3", + "gopd": "^1.0.1", "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" + "is-typed-array": "^1.1.10" } }, "yallist": { diff --git a/blueprints/serverless/api-gateway/function/package.json b/blueprints/serverless/api-gateway/function/package.json index 6e44d26667..1bf3c6fbb4 100644 --- a/blueprints/serverless/api-gateway/function/package.json +++ b/blueprints/serverless/api-gateway/function/package.json @@ -12,7 +12,7 @@ "node": ">=16.0.0" }, "dependencies": { - "@google-cloud/functions-framework": "^3.0.0", - "express": "^4.17.3" + "@google-cloud/functions-framework": "^3.2.1", + "express": "^4.18.2" } } From e64c043aaaac30eede712d4dc2f145a6c80a76af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 15:03:47 +0200 Subject: [PATCH 11/16] Bump semver and @google-cloud/storage in /blueprints/gke/binauthz/image (#1469) Removes [semver](https://github.com/npm/node-semver). It's no longer used after updating ancestor dependency [@google-cloud/storage](https://github.com/googleapis/nodejs-storage). These dependencies need to be updated together. Removes `semver` Updates `@google-cloud/storage` from 5.18.3 to 6.11.0 - [Release notes](https://github.com/googleapis/nodejs-storage/releases) - [Changelog](https://github.com/googleapis/nodejs-storage/blob/main/CHANGELOG.md) - [Commits](https://github.com/googleapis/nodejs-storage/compare/v5.18.3...v6.11.0) --- updated-dependencies: - dependency-name: semver dependency-type: indirect - dependency-name: "@google-cloud/storage" dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../gke/binauthz/image/package-lock.json | 674 +++++------------- blueprints/gke/binauthz/image/package.json | 2 +- 2 files changed, 169 insertions(+), 507 deletions(-) diff --git a/blueprints/gke/binauthz/image/package-lock.json b/blueprints/gke/binauthz/image/package-lock.json index c7eed8518b..08cd4ae18c 100644 --- a/blueprints/gke/binauthz/image/package-lock.json +++ b/blueprints/gke/binauthz/image/package-lock.json @@ -9,29 +9,10 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@google-cloud/storage": "^5.18.3", + "@google-cloud/storage": "^6.11.0", "express": "^4.17.3" } }, - "node_modules/@google-cloud/common": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.10.0.tgz", - "integrity": "sha512-XMbJYMh/ZSaZnbnrrOFfR/oQrb0SxG4qh6hDisWCoEbFcBHV0qHQo4uXfeMCzolx2Mfkh6VDaOGg+hyJsmxrlw==", - "dependencies": { - "@google-cloud/projectify": "^2.0.0", - "@google-cloud/promisify": "^2.0.0", - "arrify": "^2.0.1", - "duplexify": "^4.1.1", - "ent": "^2.2.0", - "extend": "^3.0.2", - "google-auth-library": "^7.14.0", - "retry-request": "^4.2.2", - "teeny-request": "^7.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@google-cloud/paginator": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz", @@ -45,51 +26,46 @@ } }, "node_modules/@google-cloud/projectify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz", - "integrity": "sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz", + "integrity": "sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==", "engines": { - "node": ">=10" + "node": ">=12.0.0" } }, "node_modules/@google-cloud/promisify": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", - "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz", + "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/@google-cloud/storage": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.18.3.tgz", - "integrity": "sha512-573qJ0ECoy3nkY5YaMWcVf4/46n/zdvfNgAyjaLQywl/eL38uxDhs7YVJd3pcgslaMUwKKsd/eD3St+Pq2iPew==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.11.0.tgz", + "integrity": "sha512-p5VX5K2zLTrMXlKdS1CiQNkKpygyn7CBFm5ZvfhVj6+7QUsjWvYx9YDMkYXdarZ6JDt4cxiu451y9QUIH82ZTw==", "dependencies": { - "@google-cloud/common": "^3.8.1", "@google-cloud/paginator": "^3.0.7", - "@google-cloud/promisify": "^2.0.0", + "@google-cloud/projectify": "^3.0.0", + "@google-cloud/promisify": "^3.0.0", "abort-controller": "^3.0.0", - "arrify": "^2.0.0", "async-retry": "^1.3.3", "compressible": "^2.0.12", - "configstore": "^5.0.0", - "date-and-time": "^2.0.0", "duplexify": "^4.0.0", + "ent": "^2.2.0", "extend": "^3.0.2", - "gaxios": "^4.0.0", - "get-stream": "^6.0.0", - "google-auth-library": "^7.0.0", - "hash-stream-validation": "^0.2.2", + "gaxios": "^5.0.0", + "google-auth-library": "^8.0.1", "mime": "^3.0.0", "mime-types": "^2.0.8", "p-limit": "^3.0.1", - "pumpify": "^2.0.0", - "snakeize": "^0.1.0", - "stream-events": "^1.0.4", - "xdg-basedir": "^4.0.0" + "retry-request": "^5.0.0", + "teeny-request": "^8.0.0", + "uuid": "^8.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/@tootallnate/once": { @@ -175,9 +151,9 @@ ] }, "node_modules/bignumber.js": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", - "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", "engines": { "node": "*" } @@ -218,7 +194,7 @@ "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, "node_modules/bytes": { "version": "3.1.2", @@ -239,22 +215,6 @@ "node": ">= 0.6" } }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -287,19 +247,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/date-and-time": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-2.3.0.tgz", - "integrity": "sha512-DY53oj742mykXjZzDxT7NxH5cxwBRb7FsVG5+8pcV96qU9JQd0UhA21pQB18fwwsXOXeSM0RJV4OzgVxu8eatg==" - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -329,17 +276,6 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/duplexify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", @@ -383,7 +319,7 @@ "node_modules/ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==" }, "node_modules/escape-html": { "version": "1.0.3", @@ -465,9 +401,9 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "node_modules/fast-text-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", - "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==" }, "node_modules/finalhandler": { "version": "1.1.2", @@ -516,99 +452,77 @@ } }, "node_modules/gaxios": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.2.tgz", - "integrity": "sha512-T+ap6GM6UZ0c4E6yb1y/hy2UB6hTrqhglp3XfmU9qbLCGRYhLVV5aRPpC4EmoG8N8zOnkYCgoBz+ScvGAARY6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.2.tgz", + "integrity": "sha512-mPyw3qQq6qoHWTe27CrzhSj7XYKVStTGrpP92a91FfogBWOd9BMW8GT5yS5WhEYGw02AgB1fVQVSAO+JKiQP0w==", "dependencies": { - "abort-controller": "^3.0.0", "extend": "^3.0.2", "https-proxy-agent": "^5.0.0", "is-stream": "^2.0.0", - "node-fetch": "^2.6.1" + "node-fetch": "^2.6.9" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.2.0.tgz", + "integrity": "sha512-aFhhvvNycky2QyhG+dcfEdHBF0FRbYcf39s6WNHUDysKSrbJ5vuFbjydxBcmewtXeV248GP8dWT3ByPNxsyHCw==", "dependencies": { - "gaxios": "^4.0.0", + "gaxios": "^5.0.0", "json-bigint": "^1.0.0" }, "engines": { - "node": ">=10" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, "node_modules/google-auth-library": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", - "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.8.0.tgz", + "integrity": "sha512-0iJn7IDqObDG5Tu9Tn2WemmJ31ksEa96IyK0J0OZCpTh6CrC6FrattwKX87h3qKVuprCJpdOGKc1Xi8V0kMh8Q==", "dependencies": { "arrify": "^2.0.0", "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", + "gaxios": "^5.0.0", + "gcp-metadata": "^5.2.0", + "gtoken": "^6.1.0", "jws": "^4.0.0", "lru-cache": "^6.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/google-p12-pem": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.3.tgz", - "integrity": "sha512-MC0jISvzymxePDVembypNefkAQp+DRP7dBE+zNUPaIjEspIlYg0++OrsNr248V9tPbz6iqtZ7rX1hxWA5B8qBQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", + "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", "dependencies": { - "node-forge": "^1.0.0" + "node-forge": "^1.3.1" }, "bin": { "gp12-pem": "build/src/bin/gp12-pem.js" }, "engines": { - "node": ">=10" + "node": ">=12.0.0" } }, - "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" - }, "node_modules/gtoken": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", - "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", + "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", "dependencies": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.1.3", + "gaxios": "^5.0.1", + "google-p12-pem": "^4.0.0", "jws": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=12.0.0" } }, - "node_modules/hash-stream-validation": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz", - "integrity": "sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==" - }, "node_modules/http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -638,9 +552,9 @@ } }, "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "dependencies": { "agent-base": "6", "debug": "4" @@ -660,14 +574,6 @@ "node": ">=0.10.0" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "engines": { - "node": ">=0.8.19" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -681,14 +587,6 @@ "node": ">= 0.10" } }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "engines": { - "node": ">=8" - } - }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -700,11 +598,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, "node_modules/json-bigint": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", @@ -743,20 +636,6 @@ "node": ">=10" } }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -822,9 +701,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -862,7 +741,7 @@ "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dependencies": { "wrappy": "1" } @@ -906,25 +785,6 @@ "node": ">= 0.10" } }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/pumpify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", - "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", - "dependencies": { - "duplexify": "^4.1.1", - "inherits": "^2.0.3", - "pump": "^3.0.0" - } - }, "node_modules/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", @@ -959,9 +819,9 @@ } }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -980,15 +840,15 @@ } }, "node_modules/retry-request": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz", - "integrity": "sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", + "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", "dependencies": { "debug": "^4.1.1", "extend": "^3.0.2" }, "engines": { - "node": ">=8.10.0" + "node": ">=12" } }, "node_modules/safe-buffer": { @@ -1015,14 +875,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/send": { "version": "0.17.2", "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", @@ -1094,16 +946,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/snakeize": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", - "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=" - }, "node_modules/statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -1136,21 +978,29 @@ "node_modules/stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==" }, "node_modules/teeny-request": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.2.0.tgz", - "integrity": "sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", + "integrity": "sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==", "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.1", "stream-events": "^1.0.5", - "uuid": "^8.0.0" + "uuid": "^9.0.0" }, "engines": { - "node": ">=10" + "node": ">=12" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/toidentifier": { @@ -1164,7 +1014,7 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "node_modules/type-is": { "version": "1.6.18", @@ -1178,25 +1028,6 @@ "node": ">= 0.6" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -1208,7 +1039,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/utils-merge": { "version": "1.0.1", @@ -1237,12 +1068,12 @@ "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -1251,26 +1082,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "engines": { - "node": ">=8" - } + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/yallist": { "version": "4.0.0", @@ -1290,22 +1102,6 @@ } }, "dependencies": { - "@google-cloud/common": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-3.10.0.tgz", - "integrity": "sha512-XMbJYMh/ZSaZnbnrrOFfR/oQrb0SxG4qh6hDisWCoEbFcBHV0qHQo4uXfeMCzolx2Mfkh6VDaOGg+hyJsmxrlw==", - "requires": { - "@google-cloud/projectify": "^2.0.0", - "@google-cloud/promisify": "^2.0.0", - "arrify": "^2.0.1", - "duplexify": "^4.1.1", - "ent": "^2.2.0", - "extend": "^3.0.2", - "google-auth-library": "^7.14.0", - "retry-request": "^4.2.2", - "teeny-request": "^7.0.0" - } - }, "@google-cloud/paginator": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-3.0.7.tgz", @@ -1316,42 +1112,37 @@ } }, "@google-cloud/projectify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-2.1.1.tgz", - "integrity": "sha512-+rssMZHnlh0twl122gXY4/aCrk0G1acBqkHFfYddtsqpYXGxA29nj9V5V9SfC+GyOG00l650f6lG9KL+EpFEWQ==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-3.0.0.tgz", + "integrity": "sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==" }, "@google-cloud/promisify": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-2.0.4.tgz", - "integrity": "sha512-j8yRSSqswWi1QqUGKVEKOG03Q7qOoZP6/h2zN2YO+F5h2+DHU0bSrHCK9Y7lo2DI9fBd8qGAw795sf+3Jva4yA==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-3.0.1.tgz", + "integrity": "sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==" }, "@google-cloud/storage": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-5.18.3.tgz", - "integrity": "sha512-573qJ0ECoy3nkY5YaMWcVf4/46n/zdvfNgAyjaLQywl/eL38uxDhs7YVJd3pcgslaMUwKKsd/eD3St+Pq2iPew==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-6.11.0.tgz", + "integrity": "sha512-p5VX5K2zLTrMXlKdS1CiQNkKpygyn7CBFm5ZvfhVj6+7QUsjWvYx9YDMkYXdarZ6JDt4cxiu451y9QUIH82ZTw==", "requires": { - "@google-cloud/common": "^3.8.1", "@google-cloud/paginator": "^3.0.7", - "@google-cloud/promisify": "^2.0.0", + "@google-cloud/projectify": "^3.0.0", + "@google-cloud/promisify": "^3.0.0", "abort-controller": "^3.0.0", - "arrify": "^2.0.0", "async-retry": "^1.3.3", "compressible": "^2.0.12", - "configstore": "^5.0.0", - "date-and-time": "^2.0.0", "duplexify": "^4.0.0", + "ent": "^2.2.0", "extend": "^3.0.2", - "gaxios": "^4.0.0", - "get-stream": "^6.0.0", - "google-auth-library": "^7.0.0", - "hash-stream-validation": "^0.2.2", + "gaxios": "^5.0.0", + "google-auth-library": "^8.0.1", "mime": "^3.0.0", "mime-types": "^2.0.8", "p-limit": "^3.0.1", - "pumpify": "^2.0.0", - "snakeize": "^0.1.0", - "stream-events": "^1.0.4", - "xdg-basedir": "^4.0.0" + "retry-request": "^5.0.0", + "teeny-request": "^8.0.0", + "uuid": "^8.0.0" } }, "@tootallnate/once": { @@ -1408,9 +1199,9 @@ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "bignumber.js": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", - "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==" + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", + "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==" }, "body-parser": { "version": "1.19.2", @@ -1447,7 +1238,7 @@ "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" }, "bytes": { "version": "3.1.2", @@ -1462,19 +1253,6 @@ "mime-db": ">= 1.43.0 < 2" } }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1498,16 +1276,6 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" - }, - "date-and-time": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/date-and-time/-/date-and-time-2.3.0.tgz", - "integrity": "sha512-DY53oj742mykXjZzDxT7NxH5cxwBRb7FsVG5+8pcV96qU9JQd0UhA21pQB18fwwsXOXeSM0RJV4OzgVxu8eatg==" - }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1526,14 +1294,6 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "requires": { - "is-obj": "^2.0.0" - } - }, "duplexify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", @@ -1574,7 +1334,7 @@ "ent": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=" + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==" }, "escape-html": { "version": "1.0.3", @@ -1649,9 +1409,9 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, "fast-text-encoding": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", - "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz", + "integrity": "sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w==" }, "finalhandler": { "version": "1.1.2", @@ -1693,75 +1453,59 @@ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "gaxios": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.3.2.tgz", - "integrity": "sha512-T+ap6GM6UZ0c4E6yb1y/hy2UB6hTrqhglp3XfmU9qbLCGRYhLVV5aRPpC4EmoG8N8zOnkYCgoBz+ScvGAARY6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.1.2.tgz", + "integrity": "sha512-mPyw3qQq6qoHWTe27CrzhSj7XYKVStTGrpP92a91FfogBWOd9BMW8GT5yS5WhEYGw02AgB1fVQVSAO+JKiQP0w==", "requires": { - "abort-controller": "^3.0.0", "extend": "^3.0.2", "https-proxy-agent": "^5.0.0", "is-stream": "^2.0.0", - "node-fetch": "^2.6.1" + "node-fetch": "^2.6.9" } }, "gcp-metadata": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.3.1.tgz", - "integrity": "sha512-x850LS5N7V1F3UcV7PoupzGsyD6iVwTVvsh3tbXfkctZnBnjW5yu5z1/3k3SehF7TyoTIe78rJs02GMMy+LF+A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-5.2.0.tgz", + "integrity": "sha512-aFhhvvNycky2QyhG+dcfEdHBF0FRbYcf39s6WNHUDysKSrbJ5vuFbjydxBcmewtXeV248GP8dWT3ByPNxsyHCw==", "requires": { - "gaxios": "^4.0.0", + "gaxios": "^5.0.0", "json-bigint": "^1.0.0" } }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" - }, "google-auth-library": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-7.14.1.tgz", - "integrity": "sha512-5Rk7iLNDFhFeBYc3s8l1CqzbEBcdhwR193RlD4vSNFajIcINKI8W8P0JLmBpwymHqqWbX34pJDQu39cSy/6RsA==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.8.0.tgz", + "integrity": "sha512-0iJn7IDqObDG5Tu9Tn2WemmJ31ksEa96IyK0J0OZCpTh6CrC6FrattwKX87h3qKVuprCJpdOGKc1Xi8V0kMh8Q==", "requires": { "arrify": "^2.0.0", "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "fast-text-encoding": "^1.0.0", - "gaxios": "^4.0.0", - "gcp-metadata": "^4.2.0", - "gtoken": "^5.0.4", + "gaxios": "^5.0.0", + "gcp-metadata": "^5.2.0", + "gtoken": "^6.1.0", "jws": "^4.0.0", "lru-cache": "^6.0.0" } }, "google-p12-pem": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.1.3.tgz", - "integrity": "sha512-MC0jISvzymxePDVembypNefkAQp+DRP7dBE+zNUPaIjEspIlYg0++OrsNr248V9tPbz6iqtZ7rX1hxWA5B8qBQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-4.0.1.tgz", + "integrity": "sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ==", "requires": { - "node-forge": "^1.0.0" + "node-forge": "^1.3.1" } }, - "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" - }, "gtoken": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.3.2.tgz", - "integrity": "sha512-gkvEKREW7dXWF8NV8pVrKfW7WqReAmjjkMBh6lNCCGOM4ucS0r0YyXXl0r/9Yj8wcW/32ISkfc8h5mPTDbtifQ==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-6.1.2.tgz", + "integrity": "sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ==", "requires": { - "gaxios": "^4.0.0", - "google-p12-pem": "^3.1.3", + "gaxios": "^5.0.1", + "google-p12-pem": "^4.0.0", "jws": "^4.0.0" } }, - "hash-stream-validation": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/hash-stream-validation/-/hash-stream-validation-0.2.4.tgz", - "integrity": "sha512-Gjzu0Xn7IagXVkSu9cSFuK1fqzwtLwFhNhVL8IFJijRNMgUttFbBSIAzKuSIrsFMO1+g1RlsoN49zPIbwPDMGQ==" - }, "http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -1785,9 +1529,9 @@ } }, "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "requires": { "agent-base": "6", "debug": "4" @@ -1801,11 +1545,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -1816,21 +1555,11 @@ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" - }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, "json-bigint": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", @@ -1866,14 +1595,6 @@ "yallist": "^4.0.0" } }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - } - }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1918,9 +1639,9 @@ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "requires": { "whatwg-url": "^5.0.0" } @@ -1941,7 +1662,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "requires": { "wrappy": "1" } @@ -1973,25 +1694,6 @@ "ipaddr.js": "1.9.1" } }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz", - "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==", - "requires": { - "duplexify": "^4.1.1", - "inherits": "^2.0.3", - "pump": "^3.0.0" - } - }, "qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", @@ -2014,9 +1716,9 @@ } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -2029,9 +1731,9 @@ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" }, "retry-request": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-4.2.2.tgz", - "integrity": "sha512-xA93uxUD/rogV7BV59agW/JHPGXeREMWiZc9jhcwY4YdZ7QOtC7qbomYg0n4wyk2lJhggjvKvhNX8wln/Aldhg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-5.0.2.tgz", + "integrity": "sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ==", "requires": { "debug": "^4.1.1", "extend": "^3.0.2" @@ -2047,11 +1749,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, "send": { "version": "0.17.2", "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", @@ -2115,16 +1812,6 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "snakeize": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/snakeize/-/snakeize-0.1.0.tgz", - "integrity": "sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=" - }, "statuses": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", @@ -2154,18 +1841,25 @@ "stubs": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=" + "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==" }, "teeny-request": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.2.0.tgz", - "integrity": "sha512-SyY0pek1zWsi0LRVAALem+avzMLc33MKW/JLLakdP4s9+D7+jHcy5x6P+h94g2QNZsAqQNfX5lsbd3WSeJXrrw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-8.0.3.tgz", + "integrity": "sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==", "requires": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.1", "stream-events": "^1.0.5", - "uuid": "^8.0.0" + "uuid": "^9.0.0" + }, + "dependencies": { + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + } } }, "toidentifier": { @@ -2176,7 +1870,7 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, "type-is": { "version": "1.6.18", @@ -2187,22 +1881,6 @@ "mime-types": "~2.1.24" } }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "requires": { - "crypto-random-string": "^2.0.0" - } - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2211,7 +1889,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "utils-merge": { "version": "1.0.1", @@ -2231,12 +1909,12 @@ "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "requires": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -2245,23 +1923,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "yallist": { "version": "4.0.0", diff --git a/blueprints/gke/binauthz/image/package.json b/blueprints/gke/binauthz/image/package.json index 26cd3ebbc2..0c56fe6479 100644 --- a/blueprints/gke/binauthz/image/package.json +++ b/blueprints/gke/binauthz/image/package.json @@ -9,7 +9,7 @@ "author": "", "license": "ISC", "dependencies": { - "@google-cloud/storage": "^5.18.3", + "@google-cloud/storage": "^6.11.0", "express": "^4.17.3" } } From 431fcb78476f003d48af5ae4d19e7ea8ac29a074 Mon Sep 17 00:00:00 2001 From: Ludo Date: Tue, 27 Jun 2023 08:12:54 +0200 Subject: [PATCH 12/16] update changelog --- CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24d420bd6d..00ef01835d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,21 +8,64 @@ All notable changes to this project will be documented in this file. ### BLUEPRINTS +- [[#1469](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1469)] Bump semver and @google-cloud/storage in /blueprints/gke/binauthz/image ([dependabot[bot]](https://github.com/dependabot[bot])) +- [[#1466](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1466)] **incompatible change:** Rename network load balancer modules ([ludoo](https://github.com/ludoo)) +- [[#1459](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1459)] Add preliminary support for partner interconnect ([wiktorn](https://github.com/wiktorn)) +- [[#1464](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1464)] Fix Shielded folder README ([lcaggio](https://github.com/lcaggio)) +- [[#1458](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1458)] Fixing typos ([bluPhy](https://github.com/bluPhy)) +- [[#1455](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1455)] Match readme groups with variables file in shielded folder blueprint ([CanburakTumer](https://github.com/CanburakTumer)) +- [[#1451](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1451)] Improve Minimal Data Platform blueprint ([lcaggio](https://github.com/lcaggio)) +- [[#1454](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1454)] data-platform-minimal - 02-processing.tf typo ([kthhrv](https://github.com/kthhrv)) +- [[#1453](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1453)] data-platform-minimal - correct typo ([kthhrv](https://github.com/kthhrv)) +- [[#1450](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1450)] Split Cloud Function module in separate v1 and v2 modules ([ludoo](https://github.com/ludoo)) +- [[#1447](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1447)] **incompatible change:** Refactored apigee module and adjusted the blueprints accordingly ([apichick](https://github.com/apichick)) +- [[#1409](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1409)] Added module for Secure Web Proxy ([rosmo](https://github.com/rosmo)) +- [[#1420](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1420)] Move net-dedicated-vlan-attachment module to net-vlan-attachment and … ([apichick](https://github.com/apichick)) +- [[#1427](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1427)] Updating hub-and-spoke peering blueprint to use HA VPN. ([mark1000](https://github.com/mark1000)) +- [[#1432](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1432)] Make internal/external addresses optional in compute-vm ([juliocc](https://github.com/juliocc)) - [[#1423](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1423)] Add support for Log Analytics on logging-bucket module and bump provider version ([lcaggio](https://github.com/lcaggio)) - [[#1416](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1416)] Fix and improve GCS2BQ blueprint ([lcaggio](https://github.com/lcaggio)) ### DOCUMENTATION +- [[#1466](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1466)] **incompatible change:** Rename network load balancer modules ([ludoo](https://github.com/ludoo)) +- [[#1450](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1450)] Split Cloud Function module in separate v1 and v2 modules ([ludoo](https://github.com/ludoo)) +- [[#1444](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1444)] Fixing typos ([bluPhy](https://github.com/bluPhy)) +- [[#1409](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1409)] Added module for Secure Web Proxy ([rosmo](https://github.com/rosmo)) +- [[#1420](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1420)] Move net-dedicated-vlan-attachment module to net-vlan-attachment and … ([apichick](https://github.com/apichick)) - [[#1418](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1418)] Network Load Balancer module ([ludoo](https://github.com/ludoo)) ### FAST +- [[#1466](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1466)] **incompatible change:** Rename network load balancer modules ([ludoo](https://github.com/ludoo)) +- [[#1446](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1446)] fixup(project-factory): Use the correct KMS Service Agents attribute … ([alloveras](https://github.com/alloveras)) +- [[#1445](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1445)] Bump TF version in all workflow templates to coincide with module requirements ([kthhrv](https://github.com/kthhrv)) +- [[#1443](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1443)] Fix repo names check in extra FAST stage ([ludoo](https://github.com/ludoo)) +- [[#1432](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1432)] Make internal/external addresses optional in compute-vm ([juliocc](https://github.com/juliocc)) +- [[#1429](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1429)] Use RFC6598 addresses for pods and subnets ([wiktorn](https://github.com/wiktorn)) - [[#1426](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1426)] Add custom tag support to FAST ([ludoo](https://github.com/ludoo)) - [[#1425](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1425)] Small fixes ([ludoo](https://github.com/ludoo)) - [[#1412](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1412)] Add VPN monitoring alerts to 2-networking and VPN usage chart ([afda16](https://github.com/afda16)) ### MODULES +- [[#1466](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1466)] **incompatible change:** Rename network load balancer modules ([ludoo](https://github.com/ludoo)) +- [[#1467](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1467)] Add support for resource policies to compute vm module ([ludoo](https://github.com/ludoo)) +- [[#1439](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1439)] modules/vpc-sc: google_access_context_manager_service_perimeter add support for method_selectors/permission ([LudovicEmo](https://github.com/LudovicEmo)) +- [[#1460](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1460)] Added validation for edge_availability_domain value ([apichick](https://github.com/apichick)) +- [[#1458](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1458)] Fixing typos ([bluPhy](https://github.com/bluPhy)) +- [[#1449](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1449)] Added iam for DNS managed zone to dns module ([apichick](https://github.com/apichick)) +- [[#1452](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1452)] feat(artifact-registry): Add support for CMEK ([alloveras](https://github.com/alloveras)) +- [[#1450](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1450)] Split Cloud Function module in separate v1 and v2 modules ([ludoo](https://github.com/ludoo)) +- [[#1447](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1447)] **incompatible change:** Refactored apigee module and adjusted the blueprints accordingly ([apichick](https://github.com/apichick)) +- [[#1440](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1440)] enable_logging variable was not being used ([apichick](https://github.com/apichick)) +- [[#1436](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1436)] Ignore Cloud Run system annotations/labels ([wiktorn](https://github.com/wiktorn)) +- [[#1409](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1409)] Added module for Secure Web Proxy ([rosmo](https://github.com/rosmo)) +- [[#1420](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1420)] Move net-dedicated-vlan-attachment module to net-vlan-attachment and … ([apichick](https://github.com/apichick)) +- [[#1434](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1434)] Add subnets id output, expand net-address outputs ([juliocc](https://github.com/juliocc)) +- [[#1432](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1432)] Make internal/external addresses optional in compute-vm ([juliocc](https://github.com/juliocc)) +- [[#1428](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1428)] Added support for PSC negs in net-ilb-l7 module ([apichick](https://github.com/apichick)) +- [[#1430](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1430)] Fix serverless neg example in ILB L7 module ([ludoo](https://github.com/ludoo)) - [[#1426](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1426)] Add custom tag support to FAST ([ludoo](https://github.com/ludoo)) - [[#1423](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1423)] Add support for Log Analytics on logging-bucket module and bump provider version ([lcaggio](https://github.com/lcaggio)) - [[#1425](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1425)] Small fixes ([ludoo](https://github.com/ludoo)) From 501051f32d830284b8b2b686573483702529398b Mon Sep 17 00:00:00 2001 From: Ludo Date: Tue, 27 Jun 2023 09:03:40 +0200 Subject: [PATCH 13/16] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00ef01835d..9a213cf6de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. ### BLUEPRINTS +- [[#1468](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1468)] Dependencies update for API Gateway blueprint ([apichick](https://github.com/apichick)) - [[#1469](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1469)] Bump semver and @google-cloud/storage in /blueprints/gke/binauthz/image ([dependabot[bot]](https://github.com/dependabot[bot])) - [[#1466](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1466)] **incompatible change:** Rename network load balancer modules ([ludoo](https://github.com/ludoo)) - [[#1459](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/1459)] Add preliminary support for partner interconnect ([wiktorn](https://github.com/wiktorn)) From d6aea3ff5f3d3022386cef5741c0fc629ac0d1b4 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Tue, 27 Jun 2023 09:54:46 +0200 Subject: [PATCH 14/16] Remove unneeded file from resman stage --- fast/stages/1-resman/services.yaml | 88 ------------------------------ 1 file changed, 88 deletions(-) delete mode 100644 fast/stages/1-resman/services.yaml diff --git a/fast/stages/1-resman/services.yaml b/fast/stages/1-resman/services.yaml deleted file mode 100644 index 89844cd20a..0000000000 --- a/fast/stages/1-resman/services.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# skip boilerplate check -- accessapproval.googleapis.com -- adsdatahub.googleapis.com -- aiplatform.googleapis.com -- alpha-documentai.googleapis.com -- apigee.googleapis.com -- apigeeconnect.googleapis.com -- artifactregistry.googleapis.com -- assuredworkloads.googleapis.com -- automl.googleapis.com -- bigquery.googleapis.com -- bigquerydatatransfer.googleapis.com -- bigtable.googleapis.com -- binaryauthorization.googleapis.com -- cloudasset.googleapis.com -- cloudbuild.googleapis.com -- cloudfunctions.googleapis.com -- cloudkms.googleapis.com -- cloudprofiler.googleapis.com -- cloudresourcemanager.googleapis.com -- cloudsearch.googleapis.com -- cloudtrace.googleapis.com -- composer.googleapis.com -- compute.googleapis.com -- connectgateway.googleapis.com -- contactcenterinsights.googleapis.com -- container.googleapis.com -- containeranalysis.googleapis.com -- containerregistry.googleapis.com -- containerthreatdetection.googleapis.com -- datacatalog.googleapis.com -- dataflow.googleapis.com -- datafusion.googleapis.com -- dataproc.googleapis.com -- datastream.googleapis.com -- dialogflow.googleapis.com -- dlp.googleapis.com -- dns.googleapis.com -- documentai.googleapis.com -- eventarc.googleapis.com -- file.googleapis.com -- gameservices.googleapis.com -- gkeconnect.googleapis.com -- gkehub.googleapis.com -- healthcare.googleapis.com -- iam.googleapis.com -- iaptunnel.googleapis.com -- language.googleapis.com -- lifesciences.googleapis.com -- logging.googleapis.com -- managedidentities.googleapis.com -- memcache.googleapis.com -- meshca.googleapis.com -- metastore.googleapis.com -- ml.googleapis.com -- monitoring.googleapis.com -- networkconnectivity.googleapis.com -- networkmanagement.googleapis.com -- networksecurity.googleapis.com -- networkservices.googleapis.com -- notebooks.googleapis.com -- opsconfigmonitoring.googleapis.com -- osconfig.googleapis.com -- oslogin.googleapis.com -- privateca.googleapis.com -- pubsub.googleapis.com -- pubsublite.googleapis.com -- recaptchaenterprise.googleapis.com -- recommender.googleapis.com -- redis.googleapis.com -- run.googleapis.com -- secretmanager.googleapis.com -- servicecontrol.googleapis.com -- servicedirectory.googleapis.com -- spanner.googleapis.com -- speakerid.googleapis.com -- speech.googleapis.com -- sqladmin.googleapis.com -- storage.googleapis.com -- storagetransfer.googleapis.com -- texttospeech.googleapis.com -- tpu.googleapis.com -- trafficdirector.googleapis.com -- transcoder.googleapis.com -- translate.googleapis.com -- videointelligence.googleapis.com -- vision.googleapis.com -- vpcaccess.googleapis.com From 6fcb010ff268747f03289a4ac0c74e5514cbe880 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 27 Jun 2023 11:36:28 +0200 Subject: [PATCH 15/16] Add ToCs to resource manager modules (#1471) * organization module * folder * project module --- modules/folder/README.md | 158 +++++++++++++++++++-------------- modules/organization/README.md | 30 +++++-- modules/project/README.md | 41 ++++++--- 3 files changed, 140 insertions(+), 89 deletions(-) diff --git a/modules/folder/README.md b/modules/folder/README.md index f9229f951f..a4b8d804a7 100644 --- a/modules/folder/README.md +++ b/modules/folder/README.md @@ -2,6 +2,17 @@ This module allows the creation and management of folders, including support for IAM bindings, organization policies, and hierarchical firewall rules. +## Features + +- [IAM](#iam) +- [Organization Policies](#organization-policies) + - [Factory](#organization-policy-factory) +- [Hierarchical Firewall Policies](#hierarchical-firewall-policies) + - [Directly Defined](#directly-defined-firewall-policies) + - [Factory](#firewall-policy-factory) +- [Log Sinks](#log-sinks) +- [Tags](#tags) + ## Basic example with IAM bindings ```hcl @@ -31,6 +42,15 @@ module "folder" { # tftest modules=1 resources=9 inventory=iam.yaml ``` +## IAM + +There are two mutually exclusive ways at the role level of managing IAM in this module + +- non-authoritative via the `iam_additive` and `iam_additive_members` variables, where bindings created outside this module will coexist with those managed here +- authoritative via the `group_iam` and `iam` variables, where bindings created outside this module (eg in the console) will be removed at each `terraform apply` cycle if the same role is also managed here + +Some care must be taken with the `groups_iam` variable (and in some situations with the additive variables) to ensure that variable keys are static values, so that Terraform is able to compute the dependency graph. + ## Organization policies To manage organization policies, the `orgpolicy.googleapis.com` service should be enabled in the quota project. @@ -88,76 +108,11 @@ module "folder" { # tftest modules=1 resources=8 inventory=org-policies.yaml ``` -### Organization policy factory +### Organization Policy Factory See the [organization policy factory in the project module](../project#organization-policy-factory). -## Logging Sinks - -```hcl -module "gcs" { - source = "./fabric/modules/gcs" - project_id = "my-project" - name = "gcs_sink" - force_destroy = true -} - -module "dataset" { - source = "./fabric/modules/bigquery-dataset" - project_id = "my-project" - id = "bq_sink" -} - -module "pubsub" { - source = "./fabric/modules/pubsub" - project_id = "my-project" - name = "pubsub_sink" -} - -module "bucket" { - source = "./fabric/modules/logging-bucket" - parent_type = "project" - parent = "my-project" - id = "bucket" -} - -module "folder-sink" { - source = "./fabric/modules/folder" - parent = "folders/657104291943" - name = "my-folder" - logging_sinks = { - warnings = { - destination = module.gcs.id - filter = "severity=WARNING" - type = "storage" - } - info = { - destination = module.dataset.id - filter = "severity=INFO" - type = "bigquery" - } - notice = { - destination = module.pubsub.id - filter = "severity=NOTICE" - type = "pubsub" - } - debug = { - destination = module.bucket.id - filter = "severity=DEBUG" - exclusions = { - no-compute = "logName:compute" - } - type = "logging" - } - } - logging_exclusions = { - no-gce-instances = "resource.type=gce_instance" - } -} -# tftest modules=5 resources=14 inventory=logging.yaml -``` - -## Hierarchical firewall policies +## Hierarchical Firewall Policies Hierarchical firewall policies can be managed in two ways: @@ -166,7 +121,7 @@ Hierarchical firewall policies can be managed in two ways: Once you have policies (either created via the module or externally), you can associate them using the `firewall_policy_association` variable. -### Directly defined firewall policies +### Directly Defined Firewall Policies ```hcl module "folder1" { @@ -216,7 +171,7 @@ module "folder2" { # tftest modules=2 resources=7 inventory=hfw.yaml ``` -### Firewall policy factory +### Firewall Policy Factory The in-built factory allows you to define a single policy, using one file for rules, and an optional file for CIDR range substitution variables. Remember that non-absolute paths are relative to the root module (the folder where you run `terraform`). @@ -281,6 +236,71 @@ allow-iap-ssh: logging: false ``` +## Log Sinks + +```hcl +module "gcs" { + source = "./fabric/modules/gcs" + project_id = "my-project" + name = "gcs_sink" + force_destroy = true +} + +module "dataset" { + source = "./fabric/modules/bigquery-dataset" + project_id = "my-project" + id = "bq_sink" +} + +module "pubsub" { + source = "./fabric/modules/pubsub" + project_id = "my-project" + name = "pubsub_sink" +} + +module "bucket" { + source = "./fabric/modules/logging-bucket" + parent_type = "project" + parent = "my-project" + id = "bucket" +} + +module "folder-sink" { + source = "./fabric/modules/folder" + parent = "folders/657104291943" + name = "my-folder" + logging_sinks = { + warnings = { + destination = module.gcs.id + filter = "severity=WARNING" + type = "storage" + } + info = { + destination = module.dataset.id + filter = "severity=INFO" + type = "bigquery" + } + notice = { + destination = module.pubsub.id + filter = "severity=NOTICE" + type = "pubsub" + } + debug = { + destination = module.bucket.id + filter = "severity=DEBUG" + exclusions = { + no-compute = "logName:compute" + } + type = "logging" + } + } + logging_exclusions = { + no-gce-instances = "resource.type=gce_instance" + } +} +# tftest modules=5 resources=14 inventory=logging.yaml +``` + ## Tags Refer to the [Creating and managing tags](https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing) documentation for details on usage. diff --git a/modules/organization/README.md b/modules/organization/README.md index 6286f3f3f8..9ae8b299bb 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -10,6 +10,20 @@ This module allows managing several organization properties: To manage organization policies, the `orgpolicy.googleapis.com` service should be enabled in the quota project. +## Features + +- [IAM](#iam) +- [Organization Policies](#organization-policies) + - [Factory](#organization-policy-factory) + - [Custom Constraints](#organization-policy-custom-constraints) + - [Custom Constraints Factory](#organization-policy-custom-constraints-factory) +- [Hierarchical Firewall Policies](#hierarchical-firewall-policies) + - [Directly Defined](#directly-defined-firewall-policies) + - [Factory](#firewall-policy-factory) +- [Log Sinks](#log-sinks) +- [Custom Roles](#custom-roles) +- [Tags](#tags) + ## Example ```hcl @@ -110,11 +124,13 @@ If you set audit policies via the `iam_audit_config_authoritative` variable, be Some care must also be taken with the `groups_iam` variable (and in some situations with the additive variables) to ensure that variable keys are static values, so that Terraform is able to compute the dependency graph. -### Organization policy factory +## Organization Policies + +### Organization Policy Factory See the [organization policy factory in the project module](../project#organization-policy-factory). -### Org policy custom constraints +### Organization Policy Custom Constraints Refer to the [Creating and managing custom constraints](https://cloud.google.com/resource-manager/docs/organization-policy/creating-managing-custom-constraints) documentation for details on usage. To manage organization policy custom constraints, the `orgpolicy.googleapis.com` service should be enabled in the quota project. @@ -145,7 +161,7 @@ module "org" { # tftest modules=1 resources=2 inventory=custom-constraints.yaml ``` -### Org policy custom constraints factory +### Organization Policy Custom Constraints Factory Org policy custom constraints can be loaded from a directory containing YAML files where each file defines one or more custom constraints. The structure of the YAML files is exactly the same as the `org_policy_custom_constraints` variable. @@ -201,7 +217,7 @@ custom.dataprocNoMoreThan10Workers: description: Cluster cannot have more than 10 workers, including primary and secondary workers. ``` -## Hierarchical firewall policies +## Hierarchical Firewall Policies Hierarchical firewall policies can be managed in two ways: @@ -210,7 +226,7 @@ Hierarchical firewall policies can be managed in two ways: Once you have policies (either created via the module or externally), you can associate them using the `firewall_policy_association` variable. -### Directly defined firewall policies +### Directly Defined Firewall Policies ```hcl module "org" { @@ -251,7 +267,7 @@ module "org" { # tftest modules=1 resources=4 inventory=hfw.yaml ``` -### Firewall policy factory +### Firewall Policy Factory The in-built factory allows you to define a single policy, using one file for rules, and an optional file for CIDR range substitution variables. Remember that non-absolute paths are relative to the root module (the folder where you run `terraform`). @@ -306,7 +322,7 @@ allow-iap-ssh: logging: false ``` -## Logging Sinks +## Log Sinks ```hcl module "gcs" { diff --git a/modules/project/README.md b/modules/project/README.md index 56b7d5a5b3..6fb3d42f4e 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -2,7 +2,24 @@ This module implements the creation and management of one GCP project including IAM, organization policies, Shared VPC host or service attachment, service API activation, and tag attachment. It also offers a convenient way to refer to managed service identities (aka robot service accounts) for APIs. -# Basic Project Creation +## Features + +- [Basic Project Creation](#basic-project-creation) +- [IAM](#iam) + - [Authoritative](#authoritative-iam) + - [Additive](#additive-iam) + - [Additive By Member](#additive-iam-by-member) + - [Service Identities and Authoritative IAM](#service-identities-and-authoritative-iam) + - [Using Shortcodes for Service Identities](#using-shortcodes-for-service-identities-in-additive-iam) + - [Service Identities and Manual IAM Grants](#service-identities-requiring-manual-iam-grants) +- [Shared VPC](#shared-vpc) +- [Organization Policies](#organization-policies) + - [Factory](#organization-policy-factory) +- [Log Sinks](#log-sinks) +- [Cloud KMS Encryption Keys](#cloud-kms-encryption-keys) +- [Tags](#tags) + +## Basic Project Creation ```hcl module "project" { @@ -19,7 +36,7 @@ module "project" { # tftest modules=1 resources=3 inventory=basic.yaml ``` -## IAM Examples +## IAM IAM is managed via several variables that implement different levels of control: @@ -101,7 +118,7 @@ module "project" { # tftest modules=1 resources=5 inventory=iam-additive.yaml ``` -### Additive IAM by members +### Additive IAM by Member ```hcl module "project" { @@ -116,7 +133,7 @@ module "project" { # tftest modules=1 resources=4 inventory=iam-additive-members.yaml ``` -### Service Identities and authoritative IAM +### Service Identities and Authoritative IAM As mentioned above, there are cases where authoritative management of specific IAM roles results in removal of default bindings from service identities. One example is outlined below, with a simple workaround leveraging the `service_accounts` output to identify the service identity. A full list of service identities and their roles can be found [here](https://cloud.google.com/iam/docs/service-agents). @@ -138,7 +155,8 @@ module "project" { # tftest modules=1 resources=2 ``` -### Using shortcodes for Service Identities in additive IAM +### Using Shortcodes for Service Identities in Additive Iam + Most Service Identities contains project number in their e-mail address and this prevents additive IAM to work, as these values are not known at moment of execution of `terraform plan` (its not an issue for authoritative IAM). To refer current project Service Identities you may use shortcodes for Service Identities similarly as for `service_identity_iam` when configuring Shared VPC. ```hcl @@ -160,8 +178,7 @@ module "project" { # tftest modules=1 resources=6 ``` - -### Service identities requiring manual IAM grants +### Service Identities Requiring Manual Iam Grants The module will create service identities at project creation instead of creating of them at the time of first use. This allows granting these service identities roles in other projects, something which is usually necessary in a Shared VPC context. @@ -194,7 +211,6 @@ This table lists all affected services and roles that you need to grant to servi | pubsub.googleapis.com | pubsub | roles/pubsub.serviceAgent | | sqladmin.googleapis.com | sqladmin | roles/cloudsql.serviceAgent | - ## Shared VPC The module allows managing Shared VPC status for both hosts and service projects, and includes a simple way of assigning Shared VPC roles to service identities. @@ -231,7 +247,7 @@ module "service-project" { # tftest modules=2 resources=8 inventory=shared-vpc.yaml ``` -## Organization policies +## Organization Policies To manage organization policies, the `orgpolicy.googleapis.com` service should be enabled in the quota project. @@ -290,7 +306,7 @@ module "project" { # tftest modules=1 resources=8 inventory=org-policies.yaml ``` -### Organization policy factory +### Organization Policy Factory Organization policies can be loaded from a directory containing YAML files where each file defines one or more constraints. The structure of the YAML files is exactly the same as the `org_policies` variable. @@ -351,8 +367,7 @@ iam.allowedPolicyMemberDomains: - C0yyyyyyy ``` - -## Logging Sinks +## Log Sinks ```hcl module "gcs" { @@ -418,7 +433,7 @@ module "project-host" { # tftest modules=5 resources=14 inventory=logging.yaml ``` -## Cloud KMS encryption keys +## Cloud Kms Encryption Keys The module offers a simple, centralized way to assign `roles/cloudkms.cryptoKeyEncrypterDecrypter` to service identities. From 099ad03910542c546e50d16676b45fc9ce25ef91 Mon Sep 17 00:00:00 2001 From: lcaggio Date: Wed, 28 Jun 2023 09:05:48 +0200 Subject: [PATCH 16/16] Improve Minimal Data Platform Blueprint (#1473) * Add SA to access to Curated resources * Add BQ dataset in the landing project * Provide example to move data from landing to curated using BQ engine * Improve diagram --- .../data-platform-minimal/01-landing.tf | 19 +++- .../data-platform-minimal/02-processing.tf | 4 +- .../data-platform-minimal/03-curated.tf | 31 +++++- .../data-platform-minimal/IAM.md | 13 ++- .../data-platform-minimal/README.md | 36 +++--- .../data-platform-minimal/demo/README.md | 2 +- .../demo/dag_bq_gcs2bq.py | 104 ++++++++++++++++++ .../data-platform-minimal/images/diagram.png | Bin 104566 -> 178372 bytes .../data-platform-minimal/outputs.tf | 56 +++++----- .../data-platform-minimal/variables.tf | 5 +- 10 files changed, 196 insertions(+), 74 deletions(-) create mode 100644 blueprints/data-solutions/data-platform-minimal/demo/dag_bq_gcs2bq.py diff --git a/blueprints/data-solutions/data-platform-minimal/01-landing.tf b/blueprints/data-solutions/data-platform-minimal/01-landing.tf index 48eb9969c0..10eb597423 100644 --- a/blueprints/data-solutions/data-platform-minimal/01-landing.tf +++ b/blueprints/data-solutions/data-platform-minimal/01-landing.tf @@ -16,7 +16,7 @@ locals { iam_lnd = { - "roles/storage.objectCreator" = [module.land-sa-cs-0.iam_email] + "roles/storage.objectCreator" = [module.land-sa-0.iam_email] "roles/storage.objectViewer" = [module.processing-sa-cmp-0.iam_email] "roles/storage.objectAdmin" = [module.processing-sa-0.iam_email] } @@ -36,6 +36,9 @@ module "land-project" { iam = var.project_config.billing_account_id != null ? local.iam_lnd : null iam_additive = var.project_config.billing_account_id == null ? local.iam_lnd : null services = [ + "bigquery.googleapis.com", + "bigqueryreservation.googleapis.com", + "bigquerystorage.googleapis.com", "cloudkms.googleapis.com", "cloudresourcemanager.googleapis.com", "iam.googleapis.com", @@ -52,12 +55,12 @@ module "land-project" { # Cloud Storage -module "land-sa-cs-0" { +module "land-sa-0" { source = "../../../modules/iam-service-account" project_id = module.land-project.project_id prefix = var.prefix - name = "lnd-cs-0" - display_name = "Data platform GCS landing service account." + name = "lnd-sa-0" + display_name = "Data platform landing zone service account." iam = { "roles/iam.serviceAccountTokenCreator" = [ local.groups_iam.data-engineers @@ -75,3 +78,11 @@ module "land-cs-0" { encryption_key = var.service_encryption_keys.storage force_destroy = var.data_force_destroy } + +module "land-bq-0" { + source = "../../../modules/bigquery-dataset" + project_id = module.land-project.project_id + id = "${replace(var.prefix, "-", "_")}_lnd_bq_0" + location = var.location + encryption_key = var.service_encryption_keys.bq +} diff --git a/blueprints/data-solutions/data-platform-minimal/02-processing.tf b/blueprints/data-solutions/data-platform-minimal/02-processing.tf index 17835dced7..53da3fa683 100644 --- a/blueprints/data-solutions/data-platform-minimal/02-processing.tf +++ b/blueprints/data-solutions/data-platform-minimal/02-processing.tf @@ -49,7 +49,7 @@ locals { } processing_subnet = ( local.use_shared_vpc - ? var.network_config.subnet_self_links.processing_transformation + ? var.network_config.subnet_self_link : module.processing-vpc.0.subnet_self_links["${var.region}/${var.prefix}-processing"] ) processing_vpc = ( @@ -57,8 +57,6 @@ locals { ? var.network_config.network_self_link : module.processing-vpc.0.self_link ) - - } module "processing-project" { diff --git a/blueprints/data-solutions/data-platform-minimal/03-curated.tf b/blueprints/data-solutions/data-platform-minimal/03-curated.tf index 730e8d6cb7..4b72f7618a 100644 --- a/blueprints/data-solutions/data-platform-minimal/03-curated.tf +++ b/blueprints/data-solutions/data-platform-minimal/03-curated.tf @@ -18,33 +18,41 @@ locals { cur_iam = { "roles/bigquery.dataOwner" = [module.processing-sa-0.iam_email] "roles/bigquery.dataViewer" = [ + module.cur-sa-0.iam_email, local.groups_iam.data-analysts, local.groups_iam.data-engineers ] "roles/bigquery.jobUser" = [ - module.processing-sa-0.iam_email, + module.processing-sa-0.iam_email, # Remove once bug is fixed. https://github.com/apache/airflow/issues/32106 + module.cur-sa-0.iam_email, local.groups_iam.data-analysts, local.groups_iam.data-engineers ] "roles/datacatalog.tagTemplateViewer" = [ - local.groups_iam.data-analysts, local.groups_iam.data-engineers + module.cur-sa-0.iam_email, + local.groups_iam.data-analysts, + local.groups_iam.data-engineers ] "roles/datacatalog.viewer" = [ - local.groups_iam.data-analysts, local.groups_iam.data-engineers + module.cur-sa-0.iam_email, + local.groups_iam.data-analysts, + local.groups_iam.data-engineers ] "roles/storage.objectViewer" = [ - local.groups_iam.data-analysts, local.groups_iam.data-engineers + module.cur-sa-0.iam_email, + local.groups_iam.data-analysts, + local.groups_iam.data-engineers ] "roles/storage.objectAdmin" = [module.processing-sa-0.iam_email] } cur_services = [ - "iam.googleapis.com", "bigquery.googleapis.com", "bigqueryreservation.googleapis.com", "bigquerystorage.googleapis.com", "cloudkms.googleapis.com", "cloudresourcemanager.googleapis.com", "compute.googleapis.com", + "iam.googleapis.com", "servicenetworking.googleapis.com", "serviceusage.googleapis.com", "stackdriver.googleapis.com", @@ -75,6 +83,19 @@ module "cur-project" { } } +module "cur-sa-0" { + source = "../../../modules/iam-service-account" + project_id = module.cur-project.project_id + prefix = var.prefix + name = "cur-sa-0" + display_name = "Data platform curated zone service account." + iam = { + "roles/iam.serviceAccountTokenCreator" = [ + local.groups_iam.data-engineers + ] + } +} + # Bigquery module "cur-bq-0" { diff --git a/blueprints/data-solutions/data-platform-minimal/IAM.md b/blueprints/data-solutions/data-platform-minimal/IAM.md index 54bde92d50..d5c1ccbb34 100644 --- a/blueprints/data-solutions/data-platform-minimal/IAM.md +++ b/blueprints/data-solutions/data-platform-minimal/IAM.md @@ -9,7 +9,7 @@ Legend: + additive, conditional. |gcp-data-analysts
group|[roles/datacatalog.viewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.viewer) | |gcp-data-engineers
group|[roles/dlp.estimatesAdmin](https://cloud.google.com/iam/docs/understanding-roles#dlp.estimatesAdmin)
[roles/dlp.reader](https://cloud.google.com/iam/docs/understanding-roles#dlp.reader)
[roles/dlp.user](https://cloud.google.com/iam/docs/understanding-roles#dlp.user) | |gcp-data-security
group|[roles/datacatalog.admin](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.admin)
[roles/dlp.admin](https://cloud.google.com/iam/docs/understanding-roles#dlp.admin) | -|prc-dp-0
serviceAccount|[roles/datacatalog.categoryFineGrainedReader](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.categoryFineGrainedReader)
[roles/datacatalog.viewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.viewer)
[roles/dlp.user](https://cloud.google.com/iam/docs/understanding-roles#dlp.user) | +|prc-0
serviceAccount|[roles/datacatalog.categoryFineGrainedReader](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.categoryFineGrainedReader)
[roles/datacatalog.viewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.viewer)
[roles/dlp.user](https://cloud.google.com/iam/docs/understanding-roles#dlp.user) | ## Project cur @@ -18,15 +18,16 @@ Legend: + additive, conditional. |gcp-data-analysts
group|[roles/bigquery.dataViewer](https://cloud.google.com/iam/docs/understanding-roles#bigquery.dataViewer)
[roles/bigquery.jobUser](https://cloud.google.com/iam/docs/understanding-roles#bigquery.jobUser)
[roles/datacatalog.tagTemplateViewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.tagTemplateViewer)
[roles/datacatalog.viewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.viewer)
[roles/storage.objectViewer](https://cloud.google.com/iam/docs/understanding-roles#storage.objectViewer) | |gcp-data-engineers
group|[roles/bigquery.dataViewer](https://cloud.google.com/iam/docs/understanding-roles#bigquery.dataViewer)
[roles/bigquery.jobUser](https://cloud.google.com/iam/docs/understanding-roles#bigquery.jobUser)
[roles/datacatalog.tagTemplateViewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.tagTemplateViewer)
[roles/datacatalog.viewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.viewer)
[roles/storage.objectViewer](https://cloud.google.com/iam/docs/understanding-roles#storage.objectViewer) | |SERVICE_IDENTITY_service-networking
serviceAccount|[roles/servicenetworking.serviceAgent](https://cloud.google.com/iam/docs/understanding-roles#servicenetworking.serviceAgent) +| -|prc-dp-0
serviceAccount|[roles/bigquery.dataOwner](https://cloud.google.com/iam/docs/understanding-roles#bigquery.dataOwner)
[roles/bigquery.jobUser](https://cloud.google.com/iam/docs/understanding-roles#bigquery.jobUser)
[roles/storage.objectAdmin](https://cloud.google.com/iam/docs/understanding-roles#storage.objectAdmin) | +|cur-sa-0
serviceAccount|[roles/bigquery.dataViewer](https://cloud.google.com/iam/docs/understanding-roles#bigquery.dataViewer)
[roles/bigquery.jobUser](https://cloud.google.com/iam/docs/understanding-roles#bigquery.jobUser)
[roles/datacatalog.tagTemplateViewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.tagTemplateViewer)
[roles/datacatalog.viewer](https://cloud.google.com/iam/docs/understanding-roles#datacatalog.viewer)
[roles/storage.objectViewer](https://cloud.google.com/iam/docs/understanding-roles#storage.objectViewer) | +|prc-0
serviceAccount|[roles/bigquery.dataOwner](https://cloud.google.com/iam/docs/understanding-roles#bigquery.dataOwner)
[roles/bigquery.jobUser](https://cloud.google.com/iam/docs/understanding-roles#bigquery.jobUser)
[roles/storage.objectAdmin](https://cloud.google.com/iam/docs/understanding-roles#storage.objectAdmin) | ## Project lnd | members | roles | |---|---| -|lnd-cs-0
serviceAccount|[roles/storage.objectCreator](https://cloud.google.com/iam/docs/understanding-roles#storage.objectCreator) | +|lnd-sa-0
serviceAccount|[roles/storage.objectCreator](https://cloud.google.com/iam/docs/understanding-roles#storage.objectCreator) | +|prc-0
serviceAccount|[roles/storage.objectAdmin](https://cloud.google.com/iam/docs/understanding-roles#storage.objectAdmin) | |prc-cmp-0
serviceAccount|[roles/storage.objectViewer](https://cloud.google.com/iam/docs/understanding-roles#storage.objectViewer) | -|prc-dp-0
serviceAccount|[roles/storage.objectAdmin](https://cloud.google.com/iam/docs/understanding-roles#storage.objectAdmin) | ## Project prc @@ -35,5 +36,5 @@ Legend: + additive, conditional. |gcp-data-engineers
group|[roles/composer.admin](https://cloud.google.com/iam/docs/understanding-roles#composer.admin)
[roles/composer.environmentAndStorageObjectAdmin](https://cloud.google.com/iam/docs/understanding-roles#composer.environmentAndStorageObjectAdmin)
[roles/iam.serviceAccountUser](https://cloud.google.com/iam/docs/understanding-roles#iam.serviceAccountUser)
[roles/iap.httpsResourceAccessor](https://cloud.google.com/iam/docs/understanding-roles#iap.httpsResourceAccessor)
[roles/serviceusage.serviceUsageConsumer](https://cloud.google.com/iam/docs/understanding-roles#serviceusage.serviceUsageConsumer)
[roles/storage.admin](https://cloud.google.com/iam/docs/understanding-roles#storage.admin) | |SERVICE_IDENTITY_cloudcomposer-accounts
serviceAccount|[roles/composer.ServiceAgentV2Ext](https://cloud.google.com/iam/docs/understanding-roles#composer.ServiceAgentV2Ext)
[roles/storage.admin](https://cloud.google.com/iam/docs/understanding-roles#storage.admin) | |SERVICE_IDENTITY_service-networking
serviceAccount|[roles/servicenetworking.serviceAgent](https://cloud.google.com/iam/docs/understanding-roles#servicenetworking.serviceAgent) +| -|prc-cmp-0
serviceAccount|[roles/composer.worker](https://cloud.google.com/iam/docs/understanding-roles#composer.worker)
[roles/dataproc.editor](https://cloud.google.com/iam/docs/understanding-roles#dataproc.editor)
[roles/iam.serviceAccountUser](https://cloud.google.com/iam/docs/understanding-roles#iam.serviceAccountUser)
[roles/storage.admin](https://cloud.google.com/iam/docs/understanding-roles#storage.admin) | -|prc-dp-0
serviceAccount|[roles/dataproc.worker](https://cloud.google.com/iam/docs/understanding-roles#dataproc.worker) | +|prc-0
serviceAccount|[roles/bigquery.jobUser](https://cloud.google.com/iam/docs/understanding-roles#bigquery.jobUser)
[roles/dataflow.worker](https://cloud.google.com/iam/docs/understanding-roles#dataflow.worker)
[roles/dataproc.worker](https://cloud.google.com/iam/docs/understanding-roles#dataproc.worker) | +|prc-cmp-0
serviceAccount|[roles/bigquery.jobUser](https://cloud.google.com/iam/docs/understanding-roles#bigquery.jobUser)
[roles/composer.worker](https://cloud.google.com/iam/docs/understanding-roles#composer.worker)
[roles/dataflow.admin](https://cloud.google.com/iam/docs/understanding-roles#dataflow.admin)
[roles/dataproc.editor](https://cloud.google.com/iam/docs/understanding-roles#dataproc.editor)
[roles/iam.serviceAccountUser](https://cloud.google.com/iam/docs/understanding-roles#iam.serviceAccountUser)
[roles/storage.admin](https://cloud.google.com/iam/docs/understanding-roles#storage.admin) | diff --git a/blueprints/data-solutions/data-platform-minimal/README.md b/blueprints/data-solutions/data-platform-minimal/README.md index cae07a5450..e459c37fc0 100644 --- a/blueprints/data-solutions/data-platform-minimal/README.md +++ b/blueprints/data-solutions/data-platform-minimal/README.md @@ -203,7 +203,7 @@ module "data-platform" { prefix = "myprefix" } -# tftest modules=21 resources=116 +# tftest modules=23 resources=123 ``` ## Customizations @@ -229,10 +229,7 @@ To configure the use of a shared VPC, configure the `network_config`, example: network_config = { host_project = "PROJECT_ID" network_self_link = "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/global/networks/NAME" - subnet_self_links = { - processing_transformation = "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/subnetworks/NAME" - processing_composer = "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/subnetworks/NAME" - } + subnet_self_link = "https://www.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/subnetworks/NAME" composer_ip_ranges = { cloudsql = "192.168.XXX.XXX/24" gke_master = "192.168.XXX.XXX/28" @@ -280,32 +277,31 @@ The application layer is out of scope of this script. As a demo purpuse only, on | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [organization_domain](variables.tf#L122) | Organization domain. | string | ✓ | | -| [prefix](variables.tf#L127) | Prefix used for resource names. | string | ✓ | | -| [project_config](variables.tf#L136) | Provide 'billing_account_id' value if project creation is needed, uses existing 'project_ids' if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | ✓ | | +| [organization_domain](variables.tf#L119) | Organization domain. | string | ✓ | | +| [prefix](variables.tf#L124) | Prefix used for resource names. | string | ✓ | | +| [project_config](variables.tf#L133) | Provide 'billing_account_id' value if project creation is needed, uses existing 'project_ids' if null. Parent is in 'folders/nnn' or 'organizations/nnn' format. | object({…}) | ✓ | | | [composer_config](variables.tf#L17) | Cloud Composer config. | object({…}) | | {} | | [data_catalog_tags](variables.tf#L54) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(map(list(string))) | | {…} | | [data_force_destroy](variables.tf#L65) | Flag to set 'force_destroy' on data services like BiguQery or Cloud Storage. | bool | | false | | [enable_services](variables.tf#L71) | Flag to enable or disable services in the Data Platform. | object({…}) | | {} | | [groups](variables.tf#L80) | User groups. | map(string) | | {…} | | [location](variables.tf#L90) | Location used for multi-regional resources. | string | | "eu" | -| [network_config](variables.tf#L96) | Shared VPC network configurations to use. If null networks will be created in projects. | object({…}) | | {} | -| [project_suffix](variables.tf#L160) | Suffix used only for project ids. | string | | null | -| [region](variables.tf#L166) | Region used for regional resources. | string | | "europe-west1" | -| [service_encryption_keys](variables.tf#L172) | Cloud KMS to use to encrypt different services. Key location should match service region. | object({…}) | | {} | +| [network_config](variables.tf#L96) | Shared VPC network configurations to use. If null networks will be created in projects. | object({…}) | | {} | +| [project_suffix](variables.tf#L157) | Suffix used only for project ids. | string | | null | +| [region](variables.tf#L163) | Region used for regional resources. | string | | "europe-west1" | +| [service_encryption_keys](variables.tf#L169) | Cloud KMS to use to encrypt different services. Key location should match service region. | object({…}) | | {} | ## Outputs | name | description | sensitive | |---|---|:---:| | [bigquery-datasets](outputs.tf#L17) | BigQuery datasets. | | -| [composer](outputs.tf#L24) | Composer variables. | | -| [dataproc-history-server](outputs.tf#L31) | List of bucket names which have been assigned to the cluster. | | -| [gcs_buckets](outputs.tf#L36) | GCS buckets. | | -| [kms_keys](outputs.tf#L46) | Cloud MKS keys. | | -| [projects](outputs.tf#L51) | GCP Projects informations. | | -| [service_accounts](outputs.tf#L69) | Service account created. | | -| [vpc_network](outputs.tf#L78) | VPC network. | | -| [vpc_subnet](outputs.tf#L86) | VPC subnetworks. | | +| [composer](outputs.tf#L25) | Composer variables. | | +| [dataproc-history-server](outputs.tf#L33) | List of bucket names which have been assigned to the cluster. | | +| [gcs_buckets](outputs.tf#L38) | GCS buckets. | | +| [kms_keys](outputs.tf#L47) | Cloud MKS keys. | | +| [network](outputs.tf#L52) | VPC network. | | +| [projects](outputs.tf#L60) | GCP Projects informations. | | +| [service_accounts](outputs.tf#L78) | Service account created. | | diff --git a/blueprints/data-solutions/data-platform-minimal/demo/README.md b/blueprints/data-solutions/data-platform-minimal/demo/README.md index 910fccf5b9..b9a24b8277 100644 --- a/blueprints/data-solutions/data-platform-minimal/demo/README.md +++ b/blueprints/data-solutions/data-platform-minimal/demo/README.md @@ -47,7 +47,7 @@ Below you can find computed commands to perform steps. ```bash terraform output -json | jq -r '@sh "export LND_SA=\(.service_accounts.value.landing)\nexport PRC_SA=\(.service_accounts.value.processing)\nexport CMP_SA=\(.service_accounts.value.composer)"' > env.sh -terraform output -json | jq -r '@sh "export LND_GCS=\(.gcs_buckets.value.landing_cs_0)\nexport PRC_GCS=\(.gcs_buckets.value.processing_cs_0)\nexport CMP_GCS=\(.gcs_buckets.value.composer)"' >> env.sh +terraform output -json | jq -r '@sh "export LND_GCS=\(.gcs_buckets.value.landing)\nexport PRC_GCS=\(.gcs_buckets.value.processing)\nexport CUR_GCS=\(.gcs_buckets.value.curated)\nexport CMP_GCS=\(.composer.value.dag_bucket)"' >> env.sh source ./env.sh diff --git a/blueprints/data-solutions/data-platform-minimal/demo/dag_bq_gcs2bq.py b/blueprints/data-solutions/data-platform-minimal/demo/dag_bq_gcs2bq.py new file mode 100644 index 0000000000..7abf369108 --- /dev/null +++ b/blueprints/data-solutions/data-platform-minimal/demo/dag_bq_gcs2bq.py @@ -0,0 +1,104 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# -------------------------------------------------------------------------------- +# Load The Dependencies +# -------------------------------------------------------------------------------- + +import csv +import datetime +import io +import json +import logging +import os + +from airflow import models +from airflow.operators import dummy +from airflow.providers.google.cloud.transfers.gcs_to_bigquery import GCSToBigQueryOperator + +# -------------------------------------------------------------------------------- +# Set variables - Needed for the DEMO +# -------------------------------------------------------------------------------- +BQ_LOCATION = os.environ.get("BQ_LOCATION") +CURATED_PRJ = os.environ.get("CURATED_PRJ") +CURATED_BQ_DATASET = os.environ.get("CURATED_BQ_DATASET") +CURATED_GCS = os.environ.get("CURATED_GCS") +LAND_PRJ = os.environ.get("LAND_PRJ") +LAND_GCS = os.environ.get("LAND_GCS") +PROCESSING_GCS = os.environ.get("PROCESSING_GCS") +PROCESSING_SA = os.environ.get("PROCESSING_SA") +PROCESSING_PRJ = os.environ.get("PROCESSING_PRJ") +PROCESSING_SUBNET = os.environ.get("PROCESSING_SUBNET") +PROCESSING_VPC = os.environ.get("PROCESSING_VPC") +DP_KMS_KEY = os.environ.get("DP_KMS_KEY", "") +DP_REGION = os.environ.get("DP_REGION") +DP_ZONE = os.environ.get("DP_REGION") + "-b" + +# -------------------------------------------------------------------------------- +# Set default arguments +# -------------------------------------------------------------------------------- + +# If you are running Airflow in more than one time zone +# see https://airflow.apache.org/docs/apache-airflow/stable/timezone.html +# for best practices +yesterday = datetime.datetime.now() - datetime.timedelta(days=1) + +default_args = { + 'owner': 'airflow', + 'start_date': yesterday, + 'depends_on_past': False, + 'email': [''], + 'email_on_failure': False, + 'email_on_retry': False, + 'retries': 1, + 'retry_delay': datetime.timedelta(minutes=5), +} + +# -------------------------------------------------------------------------------- +# Main DAG +# -------------------------------------------------------------------------------- + +with models.DAG( + 'bq_gcs2bq', + default_args=default_args, + schedule_interval=None) as dag: + start = dummy.DummyOperator( + task_id='start', + trigger_rule='all_success' + ) + + end = dummy.DummyOperator( + task_id='end', + trigger_rule='all_success' + ) + + # Bigquery Tables automatically created for demo porpuse. + # Consider a dedicated pipeline or tool for a real life scenario. + + customers_import = GCSToBigQueryOperator( + task_id='csv_to_bigquery', + bucket=LAND_GCS[5:], + source_objects=['customers.csv'], + destination_project_dataset_table='{}:{}.{}'.format(CURATED_PRJ, CURATED_BQ_DATASET, 'customers'), + create_disposition='CREATE_IF_NEEDED', + write_disposition='WRITE_APPEND', + schema_update_options=['ALLOW_FIELD_RELAXATION', 'ALLOW_FIELD_ADDITION'], + schema_object="customers.json", + schema_object_bucket=PROCESSING_GCS[5:], + project_id=PROCESSING_PRJ, # The process will continue to run on the dataset project until the Apache Airflow bug is fixed. https://github.com/apache/airflow/issues/32106 + impersonation_chain=[PROCESSING_SA] + ) + + start >> customers_import >> end + \ No newline at end of file diff --git a/blueprints/data-solutions/data-platform-minimal/images/diagram.png b/blueprints/data-solutions/data-platform-minimal/images/diagram.png index 7f992cbcb514f1e28edd0fadaebfd5b6f2e867bd..72eed2df62f47cb6d2c067288ea69e6010719b55 100644 GIT binary patch literal 178372 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 literal 104566 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

in~0C1{tHc9M2Kyaz%lCt@(X-Bux^pUw13p6s%5 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 D3gXe- diff --git a/blueprints/data-solutions/data-platform-minimal/outputs.tf b/blueprints/data-solutions/data-platform-minimal/outputs.tf index 73bcf0b1c8..5b975443f8 100644 --- a/blueprints/data-solutions/data-platform-minimal/outputs.tf +++ b/blueprints/data-solutions/data-platform-minimal/outputs.tf @@ -17,7 +17,8 @@ output "bigquery-datasets" { description = "BigQuery datasets." value = { - curated = module.cur-bq-0.dataset_id, + curated = module.cur-bq-0.dataset_id + landing = module.land-bq-0.dataset_id } } @@ -25,6 +26,7 @@ output "composer" { description = "Composer variables." value = { air_flow_uri = try(google_composer_environment.processing-cmp-0[0].config.0.airflow_uri, null) + dag_bucket = try(google_composer_environment.processing-cmp-0[0].config[0].dag_gcs_prefix, null) } } @@ -36,10 +38,9 @@ output "dataproc-history-server" { output "gcs_buckets" { description = "GCS buckets." value = { - landing_cs_0 = module.land-cs-0.name, - processing_cs_0 = module.processing-cs-0.name, - cur_cs_0 = module.cur-cs-0.name, - composer = try(google_composer_environment.processing-cmp-0[0].config[0].dag_gcs_prefix, null) + curated = module.cur-cs-0.name + landing = module.land-cs-0.name + processing = module.processing-cs-0.name } } @@ -48,20 +49,28 @@ output "kms_keys" { value = var.service_encryption_keys } +output "network" { + description = "VPC network." + value = { + processing_subnet = local.processing_subnet + processing_vpc = local.processing_vpc + } +} + output "projects" { description = "GCP Projects informations." value = { project_number = { - landing = module.land-project.number, - common = module.common-project.number, - curated = module.cur-project.number, - processing = module.processing-project.number, + common = module.common-project.number + curated = module.cur-project.number + landing = module.land-project.number + processing = module.processing-project.number } project_id = { - landing = module.land-project.project_id, - common = module.common-project.project_id, - curated = module.cur-project.project_id, - processing = module.processing-project.project_id, + common = module.common-project.project_id + curated = module.cur-project.project_id + landing = module.land-project.project_id + processing = module.processing-project.project_id } } } @@ -69,24 +78,9 @@ output "projects" { output "service_accounts" { description = "Service account created." value = { - landing = module.land-sa-cs-0.email - processing = module.processing-sa-0.email composer = module.processing-sa-cmp-0.email - } -} - -output "vpc_network" { - description = "VPC network." - value = { - processing_transformation = local.processing_vpc - processing_composer = local.processing_vpc - } -} - -output "vpc_subnet" { - description = "VPC subnetworks." - value = { - processing_transformation = local.processing_subnet - processing_composer = local.processing_subnet + curated = module.cur-sa-0.email, + landing = module.land-sa-0.email, + processing = module.processing-sa-0.email, } } diff --git a/blueprints/data-solutions/data-platform-minimal/variables.tf b/blueprints/data-solutions/data-platform-minimal/variables.tf index e6b62df6f3..09cdfdb8f3 100644 --- a/blueprints/data-solutions/data-platform-minimal/variables.tf +++ b/blueprints/data-solutions/data-platform-minimal/variables.tf @@ -98,10 +98,7 @@ variable "network_config" { type = object({ host_project = optional(string) network_self_link = optional(string) - subnet_self_links = optional(object({ - processing_transformation = string - processing_composer = string - }), null) + subnet_self_link = optional(string) composer_ip_ranges = optional(object({ connection_subnetwork = optional(string) cloud_sql = optional(string, "10.20.10.0/24")