diff --git a/modules/dns/README.md b/modules/dns/README.md
index ebd200ab..c9232371 100644
--- a/modules/dns/README.md
+++ b/modules/dns/README.md
@@ -53,25 +53,59 @@ module "private-dns" {
}
# tftest modules=1 resources=1
```
+
+### Routing Policies
+
+```hcl
+module "private-dns" {
+ source = "./fabric/modules/dns"
+ project_id = "myproject"
+ type = "private"
+ name = "test-example"
+ domain = "test.example."
+ client_networks = [var.vpc.self_link]
+ recordsets = {
+ "A regular" = { records = ["10.20.0.1"] }
+ "A geo" = {
+ geo_routing = [
+ { location = "europe-west1", records = ["10.0.0.1"] },
+ { location = "europe-west2", records = ["10.0.0.2"] },
+ { location = "europe-west3", records = ["10.0.0.3"] }
+ ]
+ }
+
+ "A wrr" = {
+ ttl = 600
+ wrr_routing = [
+ { weight = 0.6, records = ["10.10.0.1"] },
+ { weight = 0.2, records = ["10.10.0.2"] },
+ { weight = 0.2, records = ["10.10.0.3"] }
+ ]
+ }
+ }
+}
+# tftest modules=1 resources=4
+```
+
## Variables
| name | description | type | required | default |
|---|---|:---:|:---:|:---:|
-| [domain](variables.tf#L51) | Zone domain, must end with a period. | string
| ✓ | |
-| [name](variables.tf#L69) | Zone name, must be unique within the project. | string
| ✓ | |
-| [project_id](variables.tf#L80) | Project id for the zone. | string
| ✓ | |
+| [domain](variables.tf#L53) | Zone domain, must end with a period. | string
| ✓ | |
+| [name](variables.tf#L71) | Zone name, must be unique within the project. | string
| ✓ | |
+| [project_id](variables.tf#L82) | Project id for the zone. | string
| ✓ | |
| [client_networks](variables.tf#L21) | List of VPC self links that can see this zone. | list(string)
| | []
|
| [description](variables.tf#L28) | Domain description. | string
| | "Terraform managed."
|
-| [dnssec_config](variables.tf#L34) | DNSSEC configuration for this zone. | object({…})
| | null
|
-| [enable_logging](variables.tf#L62) | Enable query logging for this zone. Only valid for public zones. | bool
| | false
|
-| [forwarders](variables.tf#L56) | Map of {IPV4_ADDRESS => FORWARDING_PATH} for 'forwarding' zone types. Path can be 'default', 'private', or null for provider default. | map(string)
| | {}
|
-| [peer_network](variables.tf#L74) | Peering network self link, only valid for 'peering' zone types. | string
| | null
|
-| [recordsets](variables.tf#L85) | Map of DNS recordsets in \"type name\" => {ttl, [records]} format. | map(object({…}))
| | {}
|
-| [service_directory_namespace](variables.tf#L102) | Service directory namespace id (URL), only valid for 'service-directory' zone types. | string
| | null
|
-| [type](variables.tf#L108) | Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering', 'service-directory'. | string
| | "private"
|
-| [zone_create](variables.tf#L118) | Create zone. When set to false, uses a data source to reference existing zone. | bool
| | true
|
+| [dnssec_config](variables.tf#L34) | DNSSEC configuration for this zone. | object({…})
| | {…}
|
+| [enable_logging](variables.tf#L64) | Enable query logging for this zone. Only valid for public zones. | bool
| | false
|
+| [forwarders](variables.tf#L58) | Map of {IPV4_ADDRESS => FORWARDING_PATH} for 'forwarding' zone types. Path can be 'default', 'private', or null for provider default. | map(string)
| | {}
|
+| [peer_network](variables.tf#L76) | Peering network self link, only valid for 'peering' zone types. | string
| | null
|
+| [recordsets](variables.tf#L87) | Map of DNS recordsets in \"type name\" => {ttl, [records]} format. | map(object({…}))
| | {}
|
+| [service_directory_namespace](variables.tf#L122) | Service directory namespace id (URL), only valid for 'service-directory' zone types. | string
| | null
|
+| [type](variables.tf#L128) | Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering', 'service-directory'. | string
| | "private"
|
+| [zone_create](variables.tf#L138) | Create zone. When set to false, uses a data source to reference existing zone. | bool
| | true
|
## Outputs
diff --git a/modules/dns/main.tf b/modules/dns/main.tf
index ed687d97..55b9301b 100644
--- a/modules/dns/main.tf
+++ b/modules/dns/main.tf
@@ -15,10 +15,25 @@
*/
locals {
- recordsets = {
+ _recordsets = {
for key, attrs in var.recordsets :
key => merge(attrs, zipmap(["type", "name"], split(" ", key)))
}
+ geo_recordsets = {
+ for k, v in local._recordsets :
+ k => v
+ if v.geo_routing != null
+ }
+ recordsets = {
+ for k, v in local._recordsets :
+ k => v
+ if v.records != null
+ }
+ wrr_recordsets = {
+ for k, v in local._recordsets :
+ k => v
+ if v.wrr_routing != null
+ }
zone = (
var.zone_create
? try(
@@ -166,6 +181,87 @@ resource "google_dns_record_set" "cloud-static-records" {
type = each.value.type
ttl = each.value.ttl
rrdatas = each.value.records
+
+ depends_on = [
+ google_dns_managed_zone.non-public, google_dns_managed_zone.public
+ ]
+}
+
+resource "google_dns_record_set" "cloud-geo-records" {
+ for_each = (
+ var.type == "public" || var.type == "private"
+ ? local.geo_recordsets
+ : {}
+ )
+ project = var.project_id
+ managed_zone = var.name
+ name = (
+ each.value.name == ""
+ ? var.domain
+ : (
+ substr(each.value.name, -1, 1) == "."
+ ? each.value.name
+ : "${each.value.name}.${var.domain}"
+ )
+ )
+ type = each.value.type
+ ttl = each.value.ttl
+
+ dynamic "routing_policy" {
+ for_each = each.value.geo_routing != null ? [1] : [0]
+ iterator = unused
+ content {
+ dynamic "geo" {
+ for_each = each.value.geo_routing
+ iterator = policy
+ content {
+ location = policy.value.location
+ rrdatas = policy.value.records
+ }
+ }
+ }
+ }
+
+ depends_on = [
+ google_dns_managed_zone.non-public, google_dns_managed_zone.public
+ ]
+}
+
+resource "google_dns_record_set" "cloud-wrr-records" {
+ for_each = (
+ var.type == "public" || var.type == "private"
+ ? local.wrr_recordsets
+ : {}
+ )
+ project = var.project_id
+ managed_zone = var.name
+ name = (
+ each.value.name == ""
+ ? var.domain
+ : (
+ substr(each.value.name, -1, 1) == "."
+ ? each.value.name
+ : "${each.value.name}.${var.domain}"
+ )
+ )
+ type = each.value.type
+ ttl = each.value.ttl
+
+ dynamic "routing_policy" {
+ for_each = each.value.wrr_routing != null ? [1] : [0]
+ iterator = unused
+ content {
+ dynamic "wrr" {
+ for_each = each.value.wrr_routing
+ iterator = policy
+ content {
+ weight = policy.value.weight
+ rrdatas = policy.value.records
+ }
+ }
+ }
+ }
+
depends_on = [
google_dns_managed_zone.non-public, google_dns_managed_zone.public
]
diff --git a/modules/dns/variables.tf b/modules/dns/variables.tf
index 749bbdd5..644b8395 100644
--- a/modules/dns/variables.tf
+++ b/modules/dns/variables.tf
@@ -45,7 +45,9 @@ variable "dnssec_config" {
{ algorithm = "rsasha256", key_length = 1024 }
)
})
- default = null
+ default = {
+ state = "off"
+ }
}
variable "domain" {
@@ -86,17 +88,35 @@ variable "recordsets" {
description = "Map of DNS recordsets in \"type name\" => {ttl, [records]} format."
type = map(object({
ttl = optional(number, 300)
- records = list(string)
+ records = optional(list(string))
+ geo_routing = optional(list(object({
+ location = string
+ records = list(string)
+ })))
+ wrr_routing = optional(list(object({
+ weight = number
+ records = list(string)
+ })))
}))
default = {}
nullable = false
validation {
condition = alltrue([
- for k, v in var.recordsets == null ? {} : var.recordsets :
+ for k, v in coalesce(var.recordsets, {}) :
length(split(" ", k)) == 2
])
error_message = "Recordsets must have keys in the format \"type name\"."
}
+ validation {
+ condition = alltrue([
+ for k, v in coalesce(var.recordsets, {}) : (
+ (v.records != null && v.wrr_routing == null && v.geo_routing == null) ||
+ (v.records == null && v.wrr_routing != null && v.geo_routing == null) ||
+ (v.records == null && v.wrr_routing == null && v.geo_routing != null)
+ )
+ ])
+ error_message = "Only one of records, wrr_routing or geo_routing can be defined for each recordset."
+ }
}
variable "service_directory_namespace" {