Add context to net-address module (#3876)
This commit is contained in:
@@ -11,6 +11,7 @@ This module allows reserving Compute Engine external, global, and internal addre
|
||||
- [PSC addresses](#psc-addresses)
|
||||
- [IPSec Interconnect addresses](#ipsec-interconnect-addresses)
|
||||
- [PSC Network Attachments](#psc-network-attachments)
|
||||
- [Use contexts](#use-contexts)
|
||||
- [Variables](#variables)
|
||||
- [Outputs](#outputs)
|
||||
- [Fixtures](#fixtures)
|
||||
@@ -216,6 +217,7 @@ module "addresses" {
|
||||
project_id = var.project_id
|
||||
network_attachments = {
|
||||
gce-0 = {
|
||||
region = "europe-west8"
|
||||
subnet_self_link = (
|
||||
"projects/net-host/regions/europe-west8/subnetworks/gce"
|
||||
)
|
||||
@@ -225,19 +227,66 @@ module "addresses" {
|
||||
}
|
||||
# tftest modules=1 resources=1 inventory=network-attachments.yaml
|
||||
```
|
||||
|
||||
### Use contexts
|
||||
|
||||
The module supports the contexts interpolation. For example:
|
||||
|
||||
```hcl
|
||||
module "addresses" {
|
||||
source = "./fabric/modules/net-address"
|
||||
project_id = "$project_ids:my-prj"
|
||||
context = {
|
||||
locations = {
|
||||
primary-region = "us-central1"
|
||||
secondary-region = "europe-west1"
|
||||
}
|
||||
networks = {
|
||||
shared-vpc = "projects/prj-host/global/networks/shared-vpc"
|
||||
}
|
||||
project_ids = {
|
||||
my-prj = "my-project-1"
|
||||
}
|
||||
subnets = {
|
||||
subnet-primary = "projects/prj-host/regions/us-central1/subnetworks/sub-1"
|
||||
subnet-secondary = "projects/prj-host/regions/europe-west1/subnetworks/sub-2"
|
||||
}
|
||||
}
|
||||
internal_addresses = {
|
||||
ilb-1 = {
|
||||
purpose = "SHARED_LOADBALANCER_VIP"
|
||||
region = "$locations:primary-region"
|
||||
subnetwork = "$subnets:subnet-primary"
|
||||
}
|
||||
ilb-2 = {
|
||||
address = "10.0.16.102"
|
||||
region = "$locations:secondary-region"
|
||||
subnetwork = "$subnets:subnet-secondary"
|
||||
}
|
||||
}
|
||||
psc_addresses = {
|
||||
one = {
|
||||
address = "10.0.0.32"
|
||||
network = "$networks:shared-vpc"
|
||||
}
|
||||
}
|
||||
}
|
||||
# tftest modules=1 resources=3 inventory=context.yaml
|
||||
```
|
||||
<!-- BEGIN TFDOC -->
|
||||
## Variables
|
||||
|
||||
| name | description | type | required | default |
|
||||
|---|---|:---:|:---:|:---:|
|
||||
| [project_id](variables.tf#L97) | Project where the addresses will be created. | <code>string</code> | ✓ | |
|
||||
| [external_addresses](variables.tf#L17) | Map of external addresses, keyed by name. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [global_addresses](variables.tf#L40) | List of global addresses to create. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [internal_addresses](variables.tf#L50) | Map of internal addresses to create, keyed by name. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [ipsec_interconnect_addresses](variables.tf#L65) | Map of internal addresses used for HPA VPN over Cloud Interconnect. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [network_attachments](variables.tf#L84) | PSC network attachments, names as keys. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [psa_addresses](variables.tf#L102) | Map of internal addresses used for Private Service Access. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [psc_addresses](variables.tf#L114) | Map of internal addresses used for Private Service Connect. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [project_id](variables.tf#L106) | Project where the addresses will be created. | <code>string</code> | ✓ | |
|
||||
| [context](variables.tf#L17) | Context-specific interpolations. | <code>object({…})</code> | | <code>{}</code> |
|
||||
| [external_addresses](variables.tf#L29) | Map of external addresses, keyed by name. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [global_addresses](variables.tf#L55) | List of global addresses to create. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [internal_addresses](variables.tf#L65) | Map of internal addresses to create, keyed by name. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [ipsec_interconnect_addresses](variables.tf#L80) | Map of internal addresses used for HPA VPN over Cloud Interconnect. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [network_attachments](variables.tf#L93) | PSC network attachments, names as keys. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [psa_addresses](variables.tf#L111) | Map of internal addresses used for Private Service Access. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
| [psc_addresses](variables.tf#L123) | Map of internal addresses used for Private Service Connect. | <code>map(object({…}))</code> | | <code>{}</code> |
|
||||
|
||||
## Outputs
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2026 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,9 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
locals {
|
||||
ctx = {
|
||||
for k, v in var.context : k => {
|
||||
for kk, vv in v : "${local.ctx_p}${k}:${kk}" => vv
|
||||
}
|
||||
}
|
||||
ctx_p = "$"
|
||||
project_id = lookup(
|
||||
local.ctx.project_ids, var.project_id, var.project_id
|
||||
)
|
||||
}
|
||||
|
||||
resource "google_compute_global_address" "global" {
|
||||
for_each = var.global_addresses
|
||||
project = var.project_id
|
||||
project = local.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
description = each.value.description
|
||||
ip_version = each.value.ipv6 != null ? "IPV6" : "IPV4"
|
||||
@@ -25,7 +37,7 @@ resource "google_compute_global_address" "global" {
|
||||
resource "google_compute_address" "external" {
|
||||
provider = google-beta
|
||||
for_each = var.external_addresses
|
||||
project = var.project_id
|
||||
project = local.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
address_type = "EXTERNAL"
|
||||
description = each.value.description
|
||||
@@ -33,14 +45,20 @@ resource "google_compute_address" "external" {
|
||||
ipv6_endpoint_type = try(each.value.ipv6.endpoint_type, null)
|
||||
labels = each.value.labels
|
||||
network_tier = each.value.tier
|
||||
region = each.value.region
|
||||
subnetwork = each.value.subnetwork
|
||||
region = lookup(
|
||||
local.ctx.locations, each.value.region, each.value.region
|
||||
)
|
||||
subnetwork = try(lookup(
|
||||
local.ctx.subnets,
|
||||
each.value.subnetwork,
|
||||
each.value.subnetwork
|
||||
), null)
|
||||
}
|
||||
|
||||
resource "google_compute_address" "internal" {
|
||||
provider = google-beta
|
||||
for_each = var.internal_addresses
|
||||
project = var.project_id
|
||||
project = local.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
address = each.value.address
|
||||
address_type = "INTERNAL"
|
||||
@@ -48,33 +66,41 @@ resource "google_compute_address" "internal" {
|
||||
ip_version = each.value.ipv6 != null ? "IPV6" : "IPV4"
|
||||
labels = coalesce(each.value.labels, {})
|
||||
purpose = each.value.purpose
|
||||
region = each.value.region
|
||||
subnetwork = each.value.subnetwork
|
||||
region = lookup(
|
||||
local.ctx.locations, each.value.region, each.value.region
|
||||
)
|
||||
subnetwork = lookup(
|
||||
local.ctx.subnets, each.value.subnetwork, each.value.subnetwork
|
||||
)
|
||||
}
|
||||
|
||||
resource "google_compute_global_address" "psa" {
|
||||
for_each = var.psa_addresses
|
||||
project = var.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
description = each.value.description
|
||||
address = each.value.address
|
||||
address_type = "INTERNAL"
|
||||
network = each.value.network
|
||||
for_each = var.psa_addresses
|
||||
project = local.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
description = each.value.description
|
||||
address = each.value.address
|
||||
address_type = "INTERNAL"
|
||||
network = lookup(
|
||||
local.ctx.networks, each.value.network, each.value.network
|
||||
)
|
||||
prefix_length = each.value.prefix_length
|
||||
purpose = "VPC_PEERING"
|
||||
# labels = lookup(var.internal_address_labels, each.key, {})
|
||||
}
|
||||
|
||||
resource "google_compute_address" "ipsec_interconnect" {
|
||||
for_each = var.ipsec_interconnect_addresses
|
||||
project = var.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
description = each.value.description
|
||||
address = each.value.address
|
||||
address_type = "INTERNAL"
|
||||
region = each.value.region
|
||||
network = each.value.network
|
||||
for_each = var.ipsec_interconnect_addresses
|
||||
project = local.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
description = each.value.description
|
||||
address = each.value.address
|
||||
address_type = "INTERNAL"
|
||||
network = lookup(
|
||||
local.ctx.networks, each.value.network, each.value.network
|
||||
)
|
||||
prefix_length = each.value.prefix_length
|
||||
purpose = "IPSEC_INTERCONNECT"
|
||||
region = lookup(
|
||||
local.ctx.locations, each.value.region, each.value.region
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2023 Google LLC
|
||||
* Copyright 2026 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2026 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,9 +17,17 @@
|
||||
locals {
|
||||
network_attachments = {
|
||||
for k, v in var.network_attachments : k => merge(v, {
|
||||
region = regex("regions/([^/]+)", v.subnet_self_link)[0]
|
||||
region = lookup(
|
||||
local.ctx.locations,
|
||||
regex("regions/([^/]+)", v.subnet_self_link)[0],
|
||||
regex("regions/([^/]+)", v.subnet_self_link)[0]
|
||||
)
|
||||
# not using the full self link generates a permadiff
|
||||
subnet_self_link = (
|
||||
subnet_self_link = lookup(
|
||||
local.ctx,
|
||||
startswith(v.subnet_self_link, "https://")
|
||||
? v.subnet_self_link
|
||||
: "https://www.googleapis.com/compute/v1/${v.subnet_self_link}",
|
||||
startswith(v.subnet_self_link, "https://")
|
||||
? v.subnet_self_link
|
||||
: "https://www.googleapis.com/compute/v1/${v.subnet_self_link}"
|
||||
@@ -28,7 +36,6 @@ locals {
|
||||
}
|
||||
regional_psc = {
|
||||
for name, psc in var.psc_addresses : name => psc if psc.region != null
|
||||
|
||||
}
|
||||
global_psc = {
|
||||
for name, psc in var.psc_addresses : name => psc if psc.region == null
|
||||
@@ -36,39 +43,55 @@ locals {
|
||||
}
|
||||
|
||||
resource "google_compute_network_attachment" "default" {
|
||||
provider = google-beta
|
||||
for_each = local.network_attachments
|
||||
project = var.project_id
|
||||
region = each.value.region
|
||||
name = each.key
|
||||
description = each.value.description
|
||||
connection_preference = (
|
||||
each.value.automatic_connection ? "ACCEPT_AUTOMATIC" : "ACCEPT_MANUAL"
|
||||
)
|
||||
subnetworks = [each.value.subnet_self_link]
|
||||
provider = google-beta
|
||||
for_each = local.network_attachments
|
||||
name = each.key
|
||||
project = local.project_id
|
||||
description = each.value.description
|
||||
producer_accept_lists = each.value.producer_accept_lists
|
||||
producer_reject_lists = each.value.producer_reject_lists
|
||||
region = lookup(
|
||||
local.ctx.locations, each.value.region, each.value.region
|
||||
)
|
||||
subnetworks = [lookup(
|
||||
local.ctx.subnets,
|
||||
each.value.subnet_self_link,
|
||||
each.value.subnet_self_link
|
||||
)]
|
||||
connection_preference = (
|
||||
each.value.automatic_connection
|
||||
? "ACCEPT_AUTOMATIC"
|
||||
: "ACCEPT_MANUAL"
|
||||
)
|
||||
}
|
||||
|
||||
# global PSC services
|
||||
resource "google_compute_global_address" "psc" {
|
||||
for_each = local.global_psc
|
||||
project = var.project_id
|
||||
project = local.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
description = each.value.description
|
||||
address = try(each.value.address, null)
|
||||
address_type = "INTERNAL"
|
||||
network = each.value.network
|
||||
purpose = "PRIVATE_SERVICE_CONNECT"
|
||||
# labels = lookup(var.internal_address_labels, each.key, {})
|
||||
network = try(lookup(
|
||||
local.ctx.networks,
|
||||
each.value.network,
|
||||
each.value.network
|
||||
), null)
|
||||
}
|
||||
|
||||
resource "google_compute_global_forwarding_rule" "psc_consumer" {
|
||||
provider = google-beta
|
||||
for_each = { for name, psc in local.global_psc : name => psc if psc.service_attachment != null }
|
||||
name = coalesce(each.value.name, each.key)
|
||||
project = var.project_id
|
||||
network = each.value.network
|
||||
provider = google-beta
|
||||
for_each = {
|
||||
for name, psc in local.global_psc
|
||||
: name => psc if psc.service_attachment != null
|
||||
}
|
||||
name = coalesce(each.value.name, each.key)
|
||||
project = local.project_id
|
||||
network = lookup(
|
||||
local.ctx.networks, each.value.network, each.value.network
|
||||
)
|
||||
ip_address = google_compute_global_address.psc[each.key].self_link
|
||||
load_balancing_scheme = ""
|
||||
target = each.value.service_attachment.psc_service_attachment_link
|
||||
@@ -81,29 +104,47 @@ resource "google_compute_global_forwarding_rule" "psc_consumer" {
|
||||
# regional PSC services
|
||||
resource "google_compute_address" "psc" {
|
||||
for_each = local.regional_psc
|
||||
project = var.project_id
|
||||
project = local.project_id
|
||||
name = coalesce(each.value.name, each.key)
|
||||
address = try(each.value.address, null)
|
||||
address_type = "INTERNAL"
|
||||
description = each.value.description
|
||||
network = each.value.network
|
||||
# purpose not applicable for regional address
|
||||
# purpose = "PRIVATE_SERVICE_CONNECT"
|
||||
region = each.value.region
|
||||
subnetwork = each.value.subnet_self_link
|
||||
# labels = lookup(var.internal_address_labels, each.key, {})
|
||||
region = lookup(
|
||||
local.ctx.locations, each.value.region, each.value.region
|
||||
)
|
||||
network = try(lookup(
|
||||
local.ctx.networks,
|
||||
each.value.network,
|
||||
each.value.network
|
||||
), null)
|
||||
subnetwork = lookup(
|
||||
local.ctx.subnets,
|
||||
each.value.subnet_self_link,
|
||||
each.value.subnet_self_link
|
||||
)
|
||||
}
|
||||
|
||||
resource "google_compute_forwarding_rule" "psc_consumer" {
|
||||
provider = google-beta
|
||||
for_each = { for name, psc in local.regional_psc : name => psc if psc.service_attachment != null }
|
||||
provider = google-beta
|
||||
for_each = {
|
||||
for name, psc in local.regional_psc
|
||||
: name => psc if psc.service_attachment != null
|
||||
}
|
||||
name = coalesce(each.value.name, each.key)
|
||||
project = var.project_id
|
||||
region = each.value.region
|
||||
subnetwork = each.value.subnet_self_link
|
||||
project = local.project_id
|
||||
ip_address = google_compute_address.psc[each.key].self_link
|
||||
load_balancing_scheme = ""
|
||||
recreate_closed_psc = true
|
||||
target = each.value.service_attachment.psc_service_attachment_link
|
||||
allow_psc_global_access = each.value.service_attachment.global_access
|
||||
region = lookup(
|
||||
local.ctx.locations,
|
||||
each.value.region,
|
||||
each.value.region
|
||||
)
|
||||
subnetwork = lookup(
|
||||
local.ctx.subnets,
|
||||
each.value.subnet_self_link,
|
||||
each.value.subnet_self_link
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2024 Google LLC
|
||||
* Copyright 2026 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,6 +14,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
variable "context" {
|
||||
description = "Context-specific interpolations."
|
||||
type = object({
|
||||
locations = optional(map(string), {})
|
||||
networks = optional(map(string), {})
|
||||
project_ids = optional(map(string), {})
|
||||
subnets = optional(map(string), {})
|
||||
})
|
||||
default = {}
|
||||
nullable = false
|
||||
}
|
||||
|
||||
variable "external_addresses" {
|
||||
description = "Map of external addresses, keyed by name."
|
||||
type = map(object({
|
||||
@@ -31,7 +43,10 @@ variable "external_addresses" {
|
||||
validation {
|
||||
condition = (
|
||||
try(var.external_addresses.ipv6, null) == null
|
||||
|| can(regex("^(NETLB|VM)$", try(var.external_addresses.ipv6.endpoint_type, null)))
|
||||
|| can(
|
||||
regex("^(NETLB|VM)$",
|
||||
try(var.external_addresses.ipv6.endpoint_type, null))
|
||||
)
|
||||
)
|
||||
error_message = "IPv6 endpoint type must be NETLB, VM."
|
||||
}
|
||||
@@ -41,7 +56,7 @@ variable "global_addresses" {
|
||||
description = "List of global addresses to create."
|
||||
type = map(object({
|
||||
description = optional(string, "Terraform managed.")
|
||||
ipv6 = optional(map(string)) # To be left empty for ipv6
|
||||
ipv6 = optional(map(string)) # To be left empty for IPv6
|
||||
name = optional(string)
|
||||
}))
|
||||
default = {}
|
||||
@@ -54,7 +69,7 @@ variable "internal_addresses" {
|
||||
subnetwork = string
|
||||
address = optional(string)
|
||||
description = optional(string, "Terraform managed.")
|
||||
ipv6 = optional(map(string)) # To be left empty for ipv6
|
||||
ipv6 = optional(map(string)) # To be left empty for IPv6
|
||||
labels = optional(map(string))
|
||||
name = optional(string)
|
||||
purpose = optional(string)
|
||||
@@ -65,22 +80,16 @@ variable "internal_addresses" {
|
||||
variable "ipsec_interconnect_addresses" {
|
||||
description = "Map of internal addresses used for HPA VPN over Cloud Interconnect."
|
||||
type = map(object({
|
||||
region = string
|
||||
address = string
|
||||
network = string
|
||||
region = string
|
||||
prefix_length = number
|
||||
description = optional(string, "Terraform managed.")
|
||||
name = optional(string)
|
||||
prefix_length = number
|
||||
}))
|
||||
default = {}
|
||||
}
|
||||
|
||||
# variable "internal_address_labels" {
|
||||
# description = "Optional labels for internal addresses, keyed by address name."
|
||||
# type = map(map(string))
|
||||
# default = {}
|
||||
# }
|
||||
|
||||
variable "network_attachments" {
|
||||
description = "PSC network attachments, names as keys."
|
||||
type = map(object({
|
||||
@@ -120,26 +129,57 @@ variable "psc_addresses" {
|
||||
network = optional(string)
|
||||
region = optional(string)
|
||||
subnet_self_link = optional(string)
|
||||
service_attachment = optional(object({ # so we can safely check if service_attachemnt != null in for_each
|
||||
# so we can safely check if service_attachemnt != null in for_each
|
||||
service_attachment = optional(object({
|
||||
psc_service_attachment_link = string
|
||||
global_access = optional(bool)
|
||||
}))
|
||||
}))
|
||||
default = {}
|
||||
validation {
|
||||
condition = alltrue([for key, value in var.psc_addresses : (value.address != null || (value.address == null && value.subnet_self_link != null))])
|
||||
condition = alltrue(
|
||||
[
|
||||
for key, value in var.psc_addresses
|
||||
: (
|
||||
value.address != null
|
||||
|| (value.address == null && value.subnet_self_link != null)
|
||||
)
|
||||
]
|
||||
)
|
||||
error_message = "Provide address if creating a global PSC addresses / endpoints."
|
||||
}
|
||||
validation {
|
||||
condition = alltrue([for key, value in var.psc_addresses : (value.region != null || (value.region == null && value.network != null))])
|
||||
condition = alltrue(
|
||||
[
|
||||
for key, value in var.psc_addresses
|
||||
: (
|
||||
value.region != null
|
||||
|| (value.region == null && value.network != null
|
||||
)
|
||||
)
|
||||
]
|
||||
)
|
||||
error_message = "Provide network if creating global PSC addresses / endpoints."
|
||||
}
|
||||
validation {
|
||||
condition = alltrue([for key, value in var.psc_addresses : (value.region == null || (value.region != null && value.subnet_self_link != null))])
|
||||
condition = alltrue(
|
||||
[
|
||||
for key, value in var.psc_addresses
|
||||
: (
|
||||
value.region == null
|
||||
|| (value.region != null && value.subnet_self_link != null)
|
||||
)
|
||||
]
|
||||
)
|
||||
error_message = "Provide subnet_self_link if creating regional PSC addresses / endpoints."
|
||||
}
|
||||
validation {
|
||||
condition = alltrue([for key, value in var.psc_addresses : !(value.subnet_self_link != null && value.network != null)])
|
||||
condition = alltrue(
|
||||
[
|
||||
for key, value in var.psc_addresses
|
||||
: !(value.subnet_self_link != null && value.network != null)
|
||||
]
|
||||
)
|
||||
error_message = "Do not provide network and subnet_self_link at the same time"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user