I am trying to make a module for a ruleset in cloudflare with multiple rules. When I pass in a variable with the rules, it tries to create two rulesets, not a single ruleset with multiple rules in it.
This the terraform file that calls the module:
module "cloudflare-single-redirects-cf-domain-com" {
source = "./single-redirects"
single_redirect = var.single-redirects-cf-domain-com
zone_id = "8451218541616132151"
providers = {
cloudflare = cloudflare.provider
}
}
variable "single-redirects-cf-domain-com" {
type = map(object({
target_url = string
preserve_query_string = bool
expression = string
description = string
enabled = bool
}))
default = {
alerts-redirect-otherdomain = {
target_url = "https://www.otherdomain.com"
preserve_query_string = false
expression = "(starts_with(http.request.uri.path, \"/test\"))"
description = "Redirect users to otherdomain"
enabled = true
}
jaymz-redirect-otherdomain = {
target_url = "https://www.otherdomain.com"
preserve_query_string = false
expression = "(starts_with(http.request.uri.path, \"/testing\"))"
description = "Redirect users to otherdomain"
enabled = true
}
}
}
This is the module file
resource "cloudflare_ruleset" "single_redirect" {
zone_id = var.zone_id
name = "http_request_dynamic_redirect"
description = "http_request_dynamic_redirect"
kind = "zone"
phase = "http_request_dynamic_redirect"
for_each = var.single_redirect
rules {
action = "redirect"
action_parameters {
from_value {
status_code = 301
target_url {
value = each.value["target_url"]
}
preserve_query_string = each.value["preserve_query_string"]
}
}
expression = each.value["expression"]
description = each.value["description"]
enabled = each.value["enabled"]
}
}
If I remove the second rule in the variable, it creates a ruleset fine.
When I tried to move the for_each into the rules section but get "Error: each.value cannot be used in this context"
Don't use a foreach meta, that is telling Terraform you want to create the resource for each item. Instead you want to create a rule for each item. I have not used CloudFlare or the Terraform provider for it, but normally in this situation you want to use Terraform dynamic block https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks.
A dynamic block acts much like a for expression, but produces nested blocks instead of a complex typed value. It iterates over a given complex value, and generates a nested block for each element of that complex value.
Try the below, I can't say it will work for sure since I don't know the CF provider but it's the format I would expect to work:
resource "cloudflare_ruleset" "single_redirect" {
zone_id = var.zone_id
name = "http_request_dynamic_redirect"
description = "http_request_dynamic_redirect"
kind = "zone"
phase = "http_request_dynamic_redirect"
dynamic "rules" {
for_each = var.single-redirects-cf-domain-com
content {
action = "redirect"
action_parameters {
from_value {
status_code = 301
target_url {
value = rules.value["target_url"]
}
preserve_query_string = rules.value["preserve_query_string"]
}
}
expression = rules.value["expression"]
description = rules.value["description"]
enabled = rules.value["enabled"]
}
}
}