diff --git a/fast/stages/2-networking-a-simple/README.md b/fast/stages/2-networking-a-simple/README.md
index 5c059a0ec0..81a8b48fcc 100644
--- a/fast/stages/2-networking-a-simple/README.md
+++ b/fast/stages/2-networking-a-simple/README.md
@@ -10,7 +10,8 @@ This stage sets up the shared network infrastructure for the whole organization.
Connectivity between hub and spokes is configurable, and can be established via one of either
- [VPC Peering](https://cloud.google.com/vpc/docs/vpc-peering) (enabled by default), which offers a complete isolation between environments, and no choke-points in the data plane. Different ways of implementing connectivity, and their respective pros and cons, are discussed below.
-- [HA VPN](https://cloud.google.com/network-connectivity/docs/vpn/concepts/topologies) tunnels, which offer easy interoperability with some key GCP features (GKE, services leveraging Service Networking like Cloud SQL, etc.), allowing clear partitioning of quota and limits between environments, and fine-grained control of routing
+- [HA VPN](https://cloud.google.com/network-connectivity/docs/vpn/concepts/topologies) tunnels, which offer easy interoperability with some key GCP features (GKE, services leveraging Service Networking like Cloud SQL, etc.), allowing clear partitioning of quota and limits between environments, and fine-grained control of routing.
+- [NCC](https://cloud.google.com/network-connectivity/docs/network-connectivity-center), which allows for transitive connections between spokes, PSC endpoints transitivity, and a much higher limit in terms of VPCs that can participate to the peering group.
The following diagrams illustrate the high-level designs for the VPN and for the Peering configuration, and should be used as a reference for the following sections. The final number of subnets, and their IP addressing design will of course depend on customer-specific requirements, and can be easily changed via variables or external data files without having to edit the actual code.
@@ -23,6 +24,11 @@ The following diagrams illustrate the high-level designs for the VPN and for the
Peering diagram
+
+
+
+ NCC diagram
+
## Table of contents
@@ -35,6 +41,7 @@ The following diagrams illustrate the high-level designs for the VPN and for the
- [IP ranges, subnetting, routing](#ip-ranges-subnetting-routing)
- [Peering specific routing setup](#peering-specific-routing-setup)
- [HA VPN specific routing setup](#ha-vpn-specific-routing-setup)
+ - [NCC specific routing setup](#ncc-specific-routing-setup)
- [Internet egress](#internet-egress)
- [VPC and Hierarchical Firewall](#vpc-and-hierarchical-firewall)
- [DNS](#dns)
@@ -90,7 +97,7 @@ Connectivity to additional on-prem sites or other cloud providers should be impl
### Internal connectivity
-As mentioned initially, there are of course other ways to implement internal connectivity other than HA VPN. These can be easily retrofitted with minimal code changes, but introduce additional considerations for service interoperability, quotas and management.
+As mentioned initially, there are multiple ways to implement internal connectivity. These can be easily retrofitted with minimal code changes, but introduce additional considerations for service interoperability, quotas and management.
This is a summary of the main options:
@@ -100,6 +107,9 @@ This is a summary of the main options:
- [HA VPN](https://cloud.google.com/network-connectivity/docs/vpn/concepts/topologies) (implemented here)
- Pros: simple compatibility with GCP services that leverage peering internally, better control on routes, avoids peering groups shared quotas and limits
- Cons: additional cost, marginal increase in latency, requires multiple tunnels for full bandwidth
+- [NCC](https://cloud.google.com/network-connectivity/docs/network-connectivity-center)
+ - Pros: full bandwidth with no configurations, no extra latency, transitivity between spokes, feature (PSC transitivity, Private NAT, rich roadmap)
+ - Cons: traffic between spokes incour charges, PSA transitivity currently not supported, architectures involving NVAs can't currently easily be implemented
- [Multi-NIC appliances](https://cloud.google.com/architecture/best-practices-vpc-design#multi-nic) (implemented by [2-networking-b-nva](../2-networking-b-nva/)
- Pros: additional security features (e.g. IPS), potentially better integration with on-prem systems by using the same vendor
- Cons: complex HA/failover setup, limited by VM bandwidth and scale, additional costs for VMs and licenses, out of band management of a critical cloud component
@@ -140,10 +150,20 @@ The high-level routing plan implemented in this architecture is as follows:
As is evident from the table above, the hub/landing VPC acts as the route concentrator for the whole GCP network, implementing a full line of sight between environments, and between GCP and on-prem. While advertisements can be adjusted to selectively exchange routes (e.g. to isolate the production and the development environment), we recommend using [Firewall](#firewall) policies or rules to achieve the desired isolation.
+#### NCC specific routing setup
+
+When the NCC configuration is enabled:
+
+- routes between multiple subnets within the same VPC are automatically programmed by GCP
+- each spoke exchanges routes with the NCC hub, and gets NCC routes belonging to other spoks from the hub
+- on-premises is connected to the landing VPC and dynamically exchanges BGP routes with GCP using HA VPN. The HA VPN tunnels are configured as Hybrid spokes on the NCC hub, and as such all spokes receive those dynamic routes.
+
### Internet egress
Cloud NAT provides the simplest path for internet egress. This setup uses Cloud NAT, with optional per-VPC NAT gateways. Cloud NAT is disabled by default; enable it by setting the `enable_cloud_nat` variable.
+Cloud NAT is always disabled in the `landing` VPC when using NCC, as it's solely used for hybrid connectivity.
+
Several other scenarios are possible of course, with varying degrees of complexity:
- a forward proxy, with optional URL filters
@@ -204,7 +224,11 @@ Connectivity to on-prem is implemented with HA VPN ([`net-vpn`](../../../modules
Internal connectivity is controlled by `var.spoke_configs`, where you can either configure `peering-configs` or `vpn-configs` based on which spoke connectivity method you want to deploy. By default, an empty configuration will deploy a VPC Peering based hub-and-spoke.
-Peerings are managed by `spoke-peerings.tf`, and VPNs ([`net-vpn`](../../../modules/net-vpn-ha)) are managed by the `spoke-vpns.tf` file. In case of VPNs, per-gateway configurations (e.g. BGP advertisements and session ranges) are controlled by variable `var.spoke_configs.vpn_configs`. VPN gateways and IKE secrets are automatically generated and configured.
+Peerings are managed by `spoke-peerings.tf`, VPNs are managed by the `spoke-vpns.tf` file and NCC connectivity is managed by `spoke-ncc.tf`.
+
+In case of VPNs, per-gateway configurations (e.g. BGP advertisements and session ranges) are controlled by variable `var.spoke_configs.vpn_configs`. VPN gateways and IKE secrets are automatically generated and configured.
+
+In case of NCC, `var.spoke_configs.ncc_configs` allows for the definition of [range export exclusions](https://cloud.google.com/network-connectivity/docs/network-connectivity-center/concepts/vpc-spokes-overview#exclude-export-ranges).
### Routing and BGP
@@ -219,6 +243,8 @@ BGP sessions for landing-spoke are configured through variable `spoke_configs.vp
**VPC firewall rules** ([`net-vpc-firewall`](../../../modules/net-vpc-firewall)) are defined per-vpc on each `vpc-*.tf` file and leverage a resource factory to massively create rules.
To add a new firewall rule, create a new file or edit an existing one in the `data_folder` directory defined in the module `net-vpc-firewall`, following the examples of the "[Rules factory](../../../modules/net-vpc-firewall#rules-factory)" section of the module documentation. Sample firewall rules are shipped in [data/firewall-rules/landing](./data/firewall-rules/landing) and can be easily customised.
+When using NCC, no firewall rule is created for the `landing` VPC, as they don't apply to traffic in transit, and no workload should be deployed in such VPC.
+
**Hierarchical firewall policies** ([`folder`](../../../modules/folder)) are defined in `main.tf` and managed through a policy factory implemented by the `net-firewall-policy` module, which is then applied to the `Networking` folder containing all the core networking infrastructure. Policies are defined in the `rules_file` file, to define a new one simply use the [firewall policy module documentation](../../../modules/net-firewall-policy/README.md#factory)". Sample hierarchical firewall rules are shipped in [data/hierarchical-ingress-rules.yaml](./data/hierarchical-ingress-rules.yaml) and can be easily customised.
### DNS architecture
@@ -443,6 +469,7 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS
| [net-prod.tf](./net-prod.tf) | Production spoke VPC and related resources. | net-cloudnat · net-vpc · net-vpc-firewall · project | |
| [outputs.tf](./outputs.tf) | Module outputs. | | google_storage_bucket_object · local_file |
| [regions.tf](./regions.tf) | Compute short names for regions. | | |
+| [spoke-ncc.tf](./spoke-ncc.tf) | Peerings between landing and spokes. | | google_network_connectivity_hub · google_network_connectivity_spoke |
| [spoke-peerings.tf](./spoke-peerings.tf) | Peerings between landing and spokes. | net-vpc-peering | |
| [spoke-vpns.tf](./spoke-vpns.tf) | VPN between landing and spokes. | net-vpn-ha | |
| [test-resources.tf](./test-resources.tf) | Temporary instances for testing | | |
@@ -470,8 +497,8 @@ DNS configurations are centralised in the `dns-*.tf` files. Spokes delegate DNS
| [psa_ranges](variables.tf#L98) | IP ranges used for Private Service Access (CloudSQL, etc.). | object({…}) | | {} | |
| [regions](variables.tf#L118) | Region definitions. | object({…}) | | {…} | |
| [service_accounts](variables-fast.tf#L80) | Automation service accounts in name => email format. | object({…}) | | null | 1-resman |
-| [spoke_configs](variables.tf#L130) | Spoke connectivity configurations. | object({…}) | | {…} | |
-| [vpn_onprem_primary_config](variables.tf#L180) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | |
+| [spoke_configs](variables.tf#L130) | Spoke connectivity configurations. | object({…}) | | {…} | |
+| [vpn_onprem_primary_config](variables.tf#L198) | VPN gateway configuration for onprem interconnection in the primary region. | object({…}) | | null | |
## Outputs
diff --git a/fast/stages/2-networking-a-simple/diagram-ncc.png b/fast/stages/2-networking-a-simple/diagram-ncc.png
new file mode 100644
index 0000000000..21019668be
Binary files /dev/null and b/fast/stages/2-networking-a-simple/diagram-ncc.png differ
diff --git a/fast/stages/2-networking-a-simple/diagram-ncc.svg b/fast/stages/2-networking-a-simple/diagram-ncc.svg
new file mode 100644
index 0000000000..ca982a58d9
--- /dev/null
+++ b/fast/stages/2-networking-a-simple/diagram-ncc.svg
@@ -0,0 +1,1956 @@
+
+
diff --git a/fast/stages/2-networking-a-simple/diagram-peering.svg b/fast/stages/2-networking-a-simple/diagram-peering.svg
index 0eff395730..4467925778 100644
--- a/fast/stages/2-networking-a-simple/diagram-peering.svg
+++ b/fast/stages/2-networking-a-simple/diagram-peering.svg
@@ -1424,7 +1424,7 @@
height="100%" />
+ id="defs2024">
diff --git a/fast/stages/2-networking-a-simple/main.tf b/fast/stages/2-networking-a-simple/main.tf
index 1587f05826..b1b56e72ce 100644
--- a/fast/stages/2-networking-a-simple/main.tf
+++ b/fast/stages/2-networking-a-simple/main.tf
@@ -21,7 +21,11 @@ locals {
for k, v in coalesce(var.service_accounts, {}) :
k => "serviceAccount:${v}" if v != null
}
- spoke_connection = var.spoke_configs.peering_configs != null ? "peering" : "vpn"
+ spoke_connection = coalesce(
+ var.spoke_configs.peering_configs != null ? "peering" : null,
+ var.spoke_configs.vpn_configs != null ? "vpn" : null,
+ var.spoke_configs.ncc_configs != null ? "ncc" : null,
+ )
stage3_sas_delegated_grants = [
"roles/composer.sharedVpcAgent",
"roles/compute.networkUser",
diff --git a/fast/stages/2-networking-a-simple/monitoring-vpn.tf b/fast/stages/2-networking-a-simple/monitoring-vpn.tf
index eae1641e1e..88d87d2c5b 100644
--- a/fast/stages/2-networking-a-simple/monitoring-vpn.tf
+++ b/fast/stages/2-networking-a-simple/monitoring-vpn.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/fast/stages/2-networking-a-simple/monitoring.tf b/fast/stages/2-networking-a-simple/monitoring.tf
index be3a47faac..0875e3a698 100644
--- a/fast/stages/2-networking-a-simple/monitoring.tf
+++ b/fast/stages/2-networking-a-simple/monitoring.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/fast/stages/2-networking-a-simple/net-landing.tf b/fast/stages/2-networking-a-simple/net-landing.tf
index 9f53fad539..f6ee4a0d59 100644
--- a/fast/stages/2-networking-a-simple/net-landing.tf
+++ b/fast/stages/2-networking-a-simple/net-landing.tf
@@ -22,13 +22,18 @@ module "landing-project" {
name = "prod-net-landing-0"
parent = var.folder_ids.networking-prod
prefix = var.prefix
- services = [
+ services = concat([
"compute.googleapis.com",
"dns.googleapis.com",
"iap.googleapis.com",
"networkmanagement.googleapis.com",
"stackdriver.googleapis.com"
- ]
+ ], (
+ local.spoke_connection == "ncc"
+ ? ["networkconnectivity.googleapis.com"]
+ : []
+ )
+ )
shared_vpc_host_config = {
enabled = true
}
@@ -59,6 +64,7 @@ module "landing-vpc" {
}
module "landing-firewall" {
+ count = local.spoke_connection != "ncc" ? 1 : 0
source = "../../../modules/net-vpc-firewall"
project_id = module.landing-project.project_id
network = module.landing-vpc.name
@@ -73,7 +79,7 @@ module "landing-firewall" {
module "landing-nat-primary" {
source = "../../../modules/net-cloudnat"
- count = var.enable_cloud_nat ? 1 : 0
+ count = var.enable_cloud_nat && local.spoke_connection != "ncc" ? 1 : 0
project_id = module.landing-project.project_id
region = var.regions.primary
name = local.region_shortnames[var.regions.primary]
diff --git a/fast/stages/2-networking-a-simple/outputs.tf b/fast/stages/2-networking-a-simple/outputs.tf
index 28da678b87..007b7948cf 100644
--- a/fast/stages/2-networking-a-simple/outputs.tf
+++ b/fast/stages/2-networking-a-simple/outputs.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/fast/stages/2-networking-a-simple/spoke-ncc.tf b/fast/stages/2-networking-a-simple/spoke-ncc.tf
new file mode 100644
index 0000000000..8811380428
--- /dev/null
+++ b/fast/stages/2-networking-a-simple/spoke-ncc.tf
@@ -0,0 +1,63 @@
+/**
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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 Peerings between landing and spokes.
+
+resource "google_network_connectivity_hub" "default" {
+ count = local.spoke_connection == "ncc" ? 1 : 0
+ name = "hub"
+ description = "Hub"
+ project = module.landing-project.project_id
+}
+
+resource "google_network_connectivity_spoke" "spoke-dev" {
+ count = local.spoke_connection == "ncc" ? 1 : 0
+ name = "dev-spoke-0"
+ project = module.dev-spoke-project.id
+ location = "global"
+ description = "NCC Spoke dev"
+ hub = google_network_connectivity_hub.default[0].id
+ linked_vpc_network {
+ uri = module.dev-spoke-vpc.self_link
+ exclude_export_ranges = var.spoke_configs.ncc_configs.dev.exclude_export_ranges
+ }
+}
+
+resource "google_network_connectivity_spoke" "spoke-prod" {
+ count = local.spoke_connection == "ncc" ? 1 : 0
+ name = "prod-spoke-0"
+ project = module.prod-spoke-project.id
+ location = "global"
+ description = "NCC Spoke prod"
+ hub = google_network_connectivity_hub.default[0].id
+ linked_vpc_network {
+ uri = module.prod-spoke-vpc.self_link
+ exclude_export_ranges = var.spoke_configs.ncc_configs.prod.exclude_export_ranges
+ }
+}
+
+resource "google_network_connectivity_spoke" "onprem-primary-vpn" {
+ count = local.spoke_connection == "ncc" && var.vpn_onprem_primary_config != null ? 1 : 0
+ name = "onprem-primary-vpn"
+ location = var.regions.primary
+ project = module.landing-project.project_id
+ description = "Onprem primary VPN spoke"
+ hub = google_network_connectivity_hub.default[0].id
+ linked_vpn_tunnels {
+ site_to_site_data_transfer = false
+ uris = [for _, v in module.landing-to-onprem-primary-vpn[0].tunnel_self_links : v]
+ }
+}
diff --git a/fast/stages/2-networking-a-simple/spoke-peerings.tf b/fast/stages/2-networking-a-simple/spoke-peerings.tf
index f004de4084..2d8757aec5 100644
--- a/fast/stages/2-networking-a-simple/spoke-peerings.tf
+++ b/fast/stages/2-networking-a-simple/spoke-peerings.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,6 @@
# tfdoc:file:description Peerings between landing and spokes.
-moved {
- from = module.peering-dev
- to = module.peering-dev[0]
-}
-
module "peering-dev" {
count = local.spoke_connection == "peering" ? 1 : 0
source = "../../../modules/net-vpc-peering"
@@ -30,11 +25,6 @@ module "peering-dev" {
routes_config = var.spoke_configs.peering_configs.dev
}
-moved {
- from = module.peering-prod
- to = module.peering-prod[0]
-}
-
module "peering-prod" {
count = local.spoke_connection == "peering" ? 1 : 0
source = "../../../modules/net-vpc-peering"
diff --git a/fast/stages/2-networking-a-simple/spoke-vpns.tf b/fast/stages/2-networking-a-simple/spoke-vpns.tf
index 1285c03bf9..3ab5627927 100644
--- a/fast/stages/2-networking-a-simple/spoke-vpns.tf
+++ b/fast/stages/2-networking-a-simple/spoke-vpns.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,11 +36,6 @@ locals {
}
}
-moved {
- from = module.landing-to-spokes-primary-vpn
- to = module.landing-to-spokes-primary-vpn[0]
-}
-
module "landing-to-spokes-primary-vpn" {
count = local.spoke_connection == "vpn" ? 1 : 0
source = "../../../modules/net-vpn-ha"
@@ -96,11 +91,6 @@ module "landing-to-spokes-primary-vpn" {
}
}
-moved {
- from = module.landing-to-spokes-secondary-vpn
- to = module.landing-to-spokes-secondary-vpn[1]
-}
-
module "landing-to-spokes-secondary-vpn" {
count = local.spoke_connection == "vpn" ? 1 : 0
source = "../../../modules/net-vpn-ha"
@@ -137,11 +127,6 @@ module "landing-to-spokes-secondary-vpn" {
}
}
-moved {
- from = module.dev-to-landing-primary-vpn
- to = module.dev-to-landing-primary-vpn[1]
-}
-
module "dev-to-landing-primary-vpn" {
count = local.spoke_connection == "vpn" ? 1 : 0
source = "../../../modules/net-vpn-ha"
@@ -178,11 +163,6 @@ module "dev-to-landing-primary-vpn" {
}
}
-moved {
- from = module.prod-to-landing-primary-vpn
- to = module.prod-to-landing-primary-vpn[1]
-}
-
module "prod-to-landing-primary-vpn" {
count = local.spoke_connection == "vpn" ? 1 : 0
source = "../../../modules/net-vpn-ha"
@@ -219,10 +199,6 @@ module "prod-to-landing-primary-vpn" {
}
}
-moved {
- from = module.prod-to-landing-secondary-vpn
- to = module.prod-to-landing-secondary-vpn[1]
-}
module "prod-to-landing-secondary-vpn" {
count = local.spoke_connection == "vpn" ? 1 : 0
source = "../../../modules/net-vpn-ha"
diff --git a/fast/stages/2-networking-a-simple/test-resources.tf b/fast/stages/2-networking-a-simple/test-resources.tf
index 39613f66dc..16b16662a8 100644
--- a/fast/stages/2-networking-a-simple/test-resources.tf
+++ b/fast/stages/2-networking-a-simple/test-resources.tf
@@ -17,29 +17,33 @@
# tfdoc:file:description Temporary instances for testing
locals {
- test-vms = var.create_test_instances != true ? {} : {
- dev-spoke-primary = {
- region = var.regions.primary
- project_id = module.dev-spoke-project.project_id
- zone = "b"
- network = module.dev-spoke-vpc.self_link
- subnetwork = module.dev-spoke-vpc.subnet_self_links["${var.regions.primary}/dev-default"]
- }
- landing-primary = {
- region = var.regions.primary
- project_id = module.landing-project.project_id
- zone = "b"
- network = module.landing-vpc.self_link
- subnetwork = module.landing-vpc.subnet_self_links["${var.regions.primary}/landing-default"]
- }
- prod-spoke-primary = {
- region = var.regions.primary
- project_id = module.prod-spoke-project.project_id
- zone = "b"
- network = module.prod-spoke-vpc.self_link
- subnetwork = module.prod-spoke-vpc.subnet_self_links["${var.regions.primary}/prod-default"]
- }
- }
+ test-vms = var.create_test_instances != true ? {} : merge(
+ {
+ dev-spoke-primary = {
+ region = var.regions.primary
+ project_id = module.dev-spoke-project.project_id
+ zone = "b"
+ network = module.dev-spoke-vpc.self_link
+ subnetwork = module.dev-spoke-vpc.subnet_self_links["${var.regions.primary}/dev-default"]
+ }
+ prod-spoke-primary = {
+ region = var.regions.primary
+ project_id = module.prod-spoke-project.project_id
+ zone = "b"
+ network = module.prod-spoke-vpc.self_link
+ subnetwork = module.prod-spoke-vpc.subnet_self_links["${var.regions.primary}/prod-default"]
+ }
+ },
+ local.spoke_connection == "ncc" ? {} :
+ {
+ landing-primary = {
+ region = var.regions.primary
+ project_id = module.landing-project.project_id
+ zone = "b"
+ network = module.landing-vpc.self_link
+ subnetwork = module.landing-vpc.subnet_self_links["${var.regions.primary}/landing-default"]
+ }
+ })
}
module "test-vms" {
diff --git a/fast/stages/2-networking-a-simple/variables.tf b/fast/stages/2-networking-a-simple/variables.tf
index bf92791e42..234c4e5719 100644
--- a/fast/stages/2-networking-a-simple/variables.tf
+++ b/fast/stages/2-networking-a-simple/variables.tf
@@ -130,6 +130,18 @@ variable "regions" {
variable "spoke_configs" {
description = "Spoke connectivity configurations."
type = object({
+ ncc_configs = optional(object({
+ dev = optional(object({
+ exclude_export_ranges = list(string)
+ }), {
+ exclude_export_ranges = []
+ })
+ prod = optional(object({
+ exclude_export_ranges = list(string)
+ }), {
+ exclude_export_ranges = []
+ })
+ }))
peering_configs = optional(object({
dev = optional(object({
export = optional(bool, true)
@@ -172,8 +184,14 @@ variable "spoke_configs" {
peering_configs = {}
}
validation {
- condition = (var.spoke_configs.peering_configs == null) != (var.spoke_configs.vpn_configs == null)
- error_message = "Only one of `var.spoke_configs.peering_configs` or `var.spoke_configs.vpn_configs` must be configured."
+ condition = length(
+ compact([
+ var.spoke_configs.peering_configs != null ? "peering" : null,
+ var.spoke_configs.vpn_configs != null ? "vpn" : null,
+ var.spoke_configs.ncc_configs != null ? "ncc" : null,
+ ])
+ ) == 1
+ error_message = "Only one of `var.spoke_configs.ncc_configs`, `var.spoke_configs.peering_configs` or `var.spoke_configs.vpn_configs` must be configured."
}
}
diff --git a/fast/stages/2-networking-a-simple/vpn-onprem.tf b/fast/stages/2-networking-a-simple/vpn-onprem.tf
index 2f38f1a5de..e70f298a08 100644
--- a/fast/stages/2-networking-a-simple/vpn-onprem.tf
+++ b/fast/stages/2-networking-a-simple/vpn-onprem.tf
@@ -1,5 +1,5 @@
/**
- * Copyright 2022 Google LLC
+ * Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/fast/stages/2-networking-c-separate-envs/data/subnets/dev/dev-dataplatform.yaml b/fast/stages/2-networking-c-separate-envs/data/subnets/dev/dev-dataplatform.yaml
index 9b1cfb4684..f6007d28a5 100644
--- a/fast/stages/2-networking-c-separate-envs/data/subnets/dev/dev-dataplatform.yaml
+++ b/fast/stages/2-networking-c-separate-envs/data/subnets/dev/dev-dataplatform.yaml
@@ -1,9 +1,9 @@
# skip boilerplate check
name: dev-dataplatform
-region: europe-west1
+region: primary
description: Default subnet for dev Data Platform
ip_cidr_range: 10.68.2.0/24
secondary_ip_ranges:
- pods: 100.69.0.0/16
- services: 100.71.2.0/24
+ pods: 100.69.0.0/16
+ services: 100.71.2.0/24
diff --git a/tests/fast/stages/s2_networking_a_simple/ncc.tfvars b/tests/fast/stages/s2_networking_a_simple/ncc.tfvars
new file mode 100644
index 0000000000..0ef78ea332
--- /dev/null
+++ b/tests/fast/stages/s2_networking_a_simple/ncc.tfvars
@@ -0,0 +1,41 @@
+automation = {
+ outputs_bucket = "test"
+}
+billing_account = {
+ id = "000000-111111-222222"
+}
+custom_roles = {
+ service_project_network_admin = "organizations/123456789012/roles/foo"
+}
+dns = {
+ resolvers = ["10.10.10.10"]
+ enable_logging = true
+}
+enable_cloud_nat = true
+essential_contacts = "gcp-network-admins@fast.example.com"
+folder_ids = {
+ networking = null
+ networking-dev = null
+ networking-prod = null
+}
+groups = {
+ gcp-network-admins = "gcp-vpc-network-admins"
+}
+organization = {
+ domain = "fast.example.com"
+ id = 123456789012
+ customer_id = "C00000000"
+}
+prefix = "fast2"
+service_accounts = {
+ data-platform-dev = "string"
+ data-platform-prod = "string"
+ gke-dev = "string"
+ gke-prod = "string"
+ project-factory = "string"
+ project-factory-dev = "string"
+ project-factory-prod = "string"
+}
+spoke_configs = {
+ ncc_configs = {}
+}
diff --git a/tests/fast/stages/s2_networking_a_simple/ncc.yaml b/tests/fast/stages/s2_networking_a_simple/ncc.yaml
new file mode 100644
index 0000000000..997240ce9f
--- /dev/null
+++ b/tests/fast/stages/s2_networking_a_simple/ncc.yaml
@@ -0,0 +1,45 @@
+# Copyright 2024 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# 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_firewall: 4
+ google_compute_firewall_policy: 1
+ google_compute_firewall_policy_association: 1
+ google_compute_firewall_policy_rule: 4
+ google_compute_network: 3
+ google_compute_route: 9
+ google_compute_router: 2
+ google_compute_router_nat: 2
+ google_compute_shared_vpc_host_project: 3
+ google_compute_subnetwork: 7
+ google_dns_managed_zone: 9
+ google_dns_policy: 3
+ google_dns_record_set: 3
+ google_dns_response_policy: 1
+ google_dns_response_policy_rule: 38
+ google_essential_contacts_contact: 1
+ google_folder: 1
+ google_monitoring_alert_policy: 2
+ google_monitoring_dashboard: 3
+ google_monitoring_monitored_project: 2
+ google_network_connectivity_hub: 1
+ google_network_connectivity_spoke: 2
+ google_project: 3
+ google_project_iam_binding: 4
+ google_project_iam_member: 18
+ google_project_service: 22
+ google_project_service_identity: 16
+ google_storage_bucket_object: 2
+ modules: 24
+ resources: 169
diff --git a/tests/fast/stages/s2_networking_a_simple/tftest.yaml b/tests/fast/stages/s2_networking_a_simple/tftest.yaml
index 0c12b846ee..9b14f136b4 100644
--- a/tests/fast/stages/s2_networking_a_simple/tftest.yaml
+++ b/tests/fast/stages/s2_networking_a_simple/tftest.yaml
@@ -16,6 +16,9 @@ module: fast/stages/2-networking-a-simple
tests:
# peering (default) is implemented in simple.tfvars
+ ncc:
+ extra_files:
+ - ../../plugins/2-networking-serverless-connector/*.tf
simple:
extra_files:
- ../../plugins/2-networking-serverless-connector/*.tf