From 96255659beddd2dc2dda6376ecfc27fed743684c Mon Sep 17 00:00:00 2001 From: Anmol Nagpal Date: Thu, 21 Sep 2023 00:05:07 +0530 Subject: [PATCH] feat: feature weighted and other record policies --- _example/complete/.terraform.lock.hcl | 25 +++++++ _example/complete/example.tf | 56 ++++++++++++++++ _example/complete/outputs.tf | 9 +++ _example/complete/versions.tf | 10 +++ _example/vpc-association/example.tf | 2 +- main.tf | 97 +++++++++++++++++++-------- variables.tf | 56 ++-------------- 7 files changed, 173 insertions(+), 82 deletions(-) create mode 100644 _example/complete/.terraform.lock.hcl create mode 100644 _example/complete/example.tf create mode 100644 _example/complete/outputs.tf create mode 100644 _example/complete/versions.tf diff --git a/_example/complete/.terraform.lock.hcl b/_example/complete/.terraform.lock.hcl new file mode 100644 index 0000000..4bcc96c --- /dev/null +++ b/_example/complete/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.17.0" + constraints = ">= 4.48.0" + hashes = [ + "h1:U+EDfeUqefebA1h7KyBMD1xH0h311LMi7wijPDPkC/0=", + "zh:0087b9dd2c9c638fd63e527e5b9b70988008e263d480a199f180efe5a4f070f0", + "zh:0fd532a4fd03ddef11f0502ff9fe4343443e1ae805cb088825a71d6d48906ec7", + "zh:16411e731100cd15f7e165f53c23be784b2c86c2fcfd34781e0642d17090d342", + "zh:251d520927e77f091e2ec6302e921d839a2430ac541c6a461aed7c08fb5eae12", + "zh:4919e69682dc2a8c32d44f6ebc038a52c9f40af9c61cb574b64e322800d6a794", + "zh:5334c60759d5f76bdc51355d1a3ebcc451d4d20f632f5c73b6e55c52b5dc9e52", + "zh:7341a2b7247572eba0d0486094a870b872967702ec0ac7af728c2df2c30af4e5", + "zh:81d1b1cb2cac6b3922a05adab69543b678f344a01debd54500263700dad7a288", + "zh:882bc8e15ef6d4020a07321ec4c056977c5c1d96934118032922561d29504d43", + "zh:8cd4871ef2b03fd916de1a6dc7eb8a81a354c421177d4334a2e3308e50215e41", + "zh:97e12fe6529b21298adf1046c5e20ac35d0569c836a6f385ff041e257e00cfd2", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9f5baf5d59b9f3cf5504d1fa975f10f27da3791896a9e18ece47c258bac17634", + "zh:dffafba6731ac1db1c540bdbd6a8c878486b71de9d0ca1d23c5c00a6c3c14d80", + "zh:fa7440c3c15a42fc5731444d324ced75407d417bfe3184661ae47d40a9718dce", + ] +} diff --git a/_example/complete/example.tf b/_example/complete/example.tf new file mode 100644 index 0000000..59073f3 --- /dev/null +++ b/_example/complete/example.tf @@ -0,0 +1,56 @@ +provider "aws" { + region = "eu-west-1" +} + +module "route53" { + source = "../../" + + name = "route53" + environment = "test" + label_order = ["environment", "name"] + public_enabled = true + record_enabled = true + + domain_name = "clouddrove.com" + + records = [ + { + name = "" + type = "A" + ttl = 3600 + records = [ + "10.10.10.10", + ] + }, + { + name = "geo" + type = "CNAME" + ttl = 5 + records = ["europe.test.clouddrove.com."] + set_identifier = "europe" + geolocation_routing_policy = { + continent = "EU" + } + }, + { + name = "test" + type = "CNAME" + ttl = 5 + records = ["test.clouddrove.com."] + set_identifier = "test-primary" + weighted_routing_policy = { + weight = 90 + } + }, + { + name = "test" + type = "CNAME" + ttl = 5 + records = ["test.clouddrove.com."] + set_identifier = "test-secondary" + weighted_routing_policy = { + weight = 10 + } + } + ] +} diff --git a/_example/complete/outputs.tf b/_example/complete/outputs.tf new file mode 100644 index 0000000..52fd0aa --- /dev/null +++ b/_example/complete/outputs.tf @@ -0,0 +1,9 @@ +output "id" { + value = module.route53.*.zone_id + description = "The ID of the Hostzone." +} + +output "tags" { + value = module.route53.tags + description = "A mapping of tags to assign to the resource." +} \ No newline at end of file diff --git a/_example/complete/versions.tf b/_example/complete/versions.tf new file mode 100644 index 0000000..54186fd --- /dev/null +++ b/_example/complete/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.5.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.48.0" + } + } +} \ No newline at end of file diff --git a/_example/vpc-association/example.tf b/_example/vpc-association/example.tf index f0d4892..ffa40d9 100644 --- a/_example/vpc-association/example.tf +++ b/_example/vpc-association/example.tf @@ -5,11 +5,11 @@ provider "aws" { module "route53" { source = "../../" + enabled = true name = "route53" environment = "test" label_order = ["environment", "name"] private_enabled = true - enabled = true domain_name = "clouddrove.com" vpc_id = "vpc-xxxxxxxxxxxxxx" diff --git a/main.tf b/main.tf index ac0e1cf..d2b6c01 100644 --- a/main.tf +++ b/main.tf @@ -1,6 +1,16 @@ ## Managed By : CloudDrove ## Copyright @ CloudDrove. All Right Reserved. +locals { + # Terragrunt users have to provide `records_jsonencoded` as jsonencode()'d string. + # See details: https://github.com/gruntwork-io/terragrunt/issues/1211 + records = concat(var.records, try(jsondecode(var.records_jsonencoded), [])) + + # Convert `records` from list to map with unique keys + recordsets = { for rs in local.records : try(rs.key, join(" ", compact(["${rs.name} ${rs.type}", try(rs.set_identifier, "")]))) => rs } + zone_id = var.zone_id != "" ? var.zone_id : (var.private_enabled ? aws_route53_zone.private.*.zone_id[0] : aws_route53_zone.public.*.zone_id[0]) +} + #Module : label #Description : This terraform module is designed to generate consistent label names and tags # for resources. You can use terraform-labels to implement a strict naming @@ -47,34 +57,63 @@ resource "aws_route53_zone" "public" { # Module : Route53 Record Set # Description : Terraform module to create Route53 record sets resource on AWS. -resource "aws_route53_record" "default" { - count = var.record_enabled && length(var.ttls) > 0 ? length(var.ttls) : 0 - zone_id = var.zone_id != "" ? var.zone_id : (var.private_enabled ? aws_route53_zone.private.*.zone_id[0] : aws_route53_zone.public.*.zone_id[0]) - name = element(var.names, count.index) - type = element(var.types, count.index) - ttl = element(var.ttls, count.index) - records = split(",", element(var.values, count.index)) - set_identifier = length(var.set_identifiers) > 0 ? element(var.set_identifiers, count.index) : "" - health_check_id = length(var.health_check_ids) > 0 ? element(var.health_check_ids, count.index) : "" - multivalue_answer_routing_policy = length(var.multivalue_answer_routing_policies) > 0 ? element(var.multivalue_answer_routing_policies, count.index) : null - allow_overwrite = length(var.allow_overwrites) > 0 ? element(var.allow_overwrites, count.index) : false -} -# Module : Route53 Record Set -# Description : Terraform module to create Route53 record sets resource on AWS. -resource "aws_route53_record" "alias" { - count = var.record_enabled && length(var.alias) > 0 && length(var.alias["names"]) > 0 ? length(var.alias["names"]) : 0 - zone_id = var.zone_id - name = element(var.names, count.index) - type = element(var.types, count.index) - set_identifier = length(var.set_identifiers) > 0 ? element(var.set_identifiers, count.index) : "" - health_check_id = length(var.health_check_ids) > 0 ? element(var.health_check_ids, count.index) : "" - multivalue_answer_routing_policy = length(var.multivalue_answer_routing_policies) > 0 ? element(var.multivalue_answer_routing_policies, count.index) : null - allow_overwrite = length(var.allow_overwrites) > 0 ? element(var.allow_overwrites, count.index) : false - alias { - name = length(var.alias) > 0 ? element(var.alias["names"], count.index) : "" - zone_id = length(var.alias) > 0 ? element(var.alias["zone_ids"], count.index) : "" - evaluate_target_health = length(var.alias) > 0 ? element(var.alias["evaluate_target_healths"], count.index) : false +resource "aws_route53_record" "this" { + for_each = { for k, v in local.recordsets : k => v if var.record_enabled && (local.zone_id != null || var.domain_name != null) } + + zone_id = local.zone_id + + name = each.value.name != "" ? (lookup(each.value, "full_name_override", false) ? each.value.name : "${each.value.name}.${var.domain_name}") : var.domain_name + type = each.value.type + ttl = lookup(each.value, "ttl", null) + records = try(each.value.records, null) + set_identifier = lookup(each.value, "set_identifier", null) + health_check_id = lookup(each.value, "health_check_id", null) + multivalue_answer_routing_policy = lookup(each.value, "multivalue_answer_routing_policy", null) + allow_overwrite = lookup(each.value, "allow_overwrite", false) + + dynamic "alias" { + for_each = length(keys(lookup(each.value, "alias", {}))) == 0 ? [] : [true] + + content { + name = each.value.alias.name + zone_id = try(each.value.alias.zone_id, local.zone_id) + evaluate_target_health = lookup(each.value.alias, "evaluate_target_health", false) + } + } + + dynamic "failover_routing_policy" { + for_each = length(keys(lookup(each.value, "failover_routing_policy", {}))) == 0 ? [] : [true] + + content { + type = each.value.failover_routing_policy.type + } + } + + dynamic "latency_routing_policy" { + for_each = length(keys(lookup(each.value, "latency_routing_policy", {}))) == 0 ? [] : [true] + + content { + region = each.value.latency_routing_policy.region + } + } + + dynamic "weighted_routing_policy" { + for_each = length(keys(lookup(each.value, "weighted_routing_policy", {}))) == 0 ? [] : [true] + + content { + weight = each.value.weighted_routing_policy.weight + } + } + + dynamic "geolocation_routing_policy" { + for_each = length(keys(lookup(each.value, "geolocation_routing_policy", {}))) == 0 ? [] : [true] + + content { + continent = lookup(each.value.geolocation_routing_policy, "continent", null) + country = lookup(each.value.geolocation_routing_policy, "country", null) + subdivision = lookup(each.value.geolocation_routing_policy, "subdivision", null) + } } } @@ -82,7 +121,7 @@ resource "aws_route53_record" "alias" { # Description : Terraform module to create Route53 record sets resource on AWS for Weighted # Routing Policy. resource "aws_route53_zone_association" "default" { - count = var.enabled ? 1 : 0 - zone_id = var.private_enabled ? aws_route53_zone.private.*.zone_id[0] : aws_route53_zone.public.*.zone_id[0] + count = var.enabled && var.private_enabled ? 1 : 0 + zone_id = aws_route53_zone.private.*.zone_id[0] vpc_id = var.secondary_vpc_id } diff --git a/variables.tf b/variables.tf index f631231..bece144 100644 --- a/variables.tf +++ b/variables.tf @@ -30,7 +30,6 @@ variable "repository" { } } - variable "label_order" { type = list(any) default = [] @@ -63,11 +62,6 @@ variable "tags" { # Module : Route53 # Description : Terraform Route53 module variables. -variable "private_enabled" { - type = bool - default = false - description = "Whether to create private Route53 zone." -} variable "record_enabled" { type = bool @@ -87,28 +81,10 @@ variable "record_set_enabled" { description = "Whether to create seperate Route53 record set." } -variable "failover_enabled" { - type = bool - default = false - description = "Whether to create Route53 record set." -} - -variable "latency_enabled" { - type = bool - default = false - description = "Whether to create Route53 record set." -} - -variable "geolocation_enabled" { - type = bool - default = false - description = "Whether to create Route53 record set." -} - -variable "weighted_enabled" { - type = bool - default = false - description = "Whether to create Route53 record set." +variable "records" { + description = "List of objects of DNS records" + type = any + default = [] } variable "domain_name" { @@ -146,42 +122,18 @@ variable "types" { description = "The record type. Valid values are A, AAAA, CAA, CNAME, MX, NAPTR, NS, PTR, SOA, SPF, SRV and TXT. " } -variable "ttls" { - type = list(any) - default = [] - description = "(Required for non-alias records) The TTL of the record." -} - -variable "names" { - type = list(any) - default = [] - description = "The name of the record." -} - variable "values" { type = list(any) default = [] description = "(Required for non-alias records) A string list of records. To specify a single record value longer than 255 characters such as a TXT record for DKIM, add \"\" inside the Terraform configuration string (e.g. \"first255characters\"\"morecharacters\")." } -variable "set_identifiers" { - type = list(any) - default = [] - description = "Unique identifier to differentiate records with routing policies from one another. Required if using failover, geolocation, latency, or weighted routing policies documented below." -} - variable "health_check_ids" { type = list(any) default = [] description = "The health check the record should be associated with." } -variable "alias" { - type = map(any) - default = { "names" = [], "zone_ids" = [], "evaluate_target_healths" = [] } - description = "An alias block. Conflicts with ttl & records. Alias record documented below." -} - variable "failover_routing_policies" { default = null description = "A block indicating the routing behavior when associated health check fails. Conflicts with any other routing policy. Documented below."