Reputation: 23
I am just getting my feet wet with Terraform but I don't see an obvious way to keep me from repeating myself.
I have a bunch of zones in Cloudlfare that I want to manage. These zones will all have very similar settings and I want my .tf
files to be both short and readable.
Lets say I have example1.com example2.com example3.com... I add them with the following code:
resource "cloudflare_zone" "example1"{
zone = "example1.com"
}
resource "cloudflare_zone" "example2"{
zone = "example2.com"
}
resource "cloudflare_zone" "example3"{
zone = "example3.com"
}
So far so good.
Now I want to apply some identical settings to all my zones using the cloudflare_zone_settings_override
provider.
Looking at the documentation this is straight forward for one zone. But I would rather not have to do this for each zone:
resource "cloudflare_zone_settings_override" "example1" {
name = "$example1.com"
settings {
brotli = "on"
security_level = "high"
opportunistic_encryption = "on"
automatic_https_rewrites = "on"
mirage = "on"
waf = "on"
minify {
css = "on"
js = "off"
html = "off"
}
}
}
What is the best way to apply these to all (or some) of the zones in Cloudflare?
Thanks
Upvotes: 2
Views: 943
Reputation: 509
Alternative solution using this module. Here is a ready-to-use example:
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = ">= 3.12.1"
}
}
}
variable "cloudflare_api_token" {
type = string
sensitive = true
}
provider "cloudflare" {
api_token = var.cloudflare_api_token
}
locals {
# All your zones go here
zones = ["acme.com", "example.com"]
}
module "zones" {
source = "registry.terraform.io/alex-feel/zone/cloudflare"
version = "1.7.0"
for_each = toset(local.zones)
zone = each.value
brotli = "on"
security_level = "high"
opportunistic_encryption = "on"
automatic_https_rewrites = "on"
mirage = "on"
waf = "on"
minify = {
css = "on"
}
}
Upvotes: 0
Reputation: 56887
Terraform has a couple of ways of minimising repeating yourself.
You could loop through a list, using the count
meta-parameter creating resources as necessary:
variable "zones" {
type = "list"
}
resource "cloudflare_zone" "zones" {
count = "${length(var.zones)}"
zone = "${var.zones[count.index]}"
}
resource "cloudflare_zone_settings_override" "settings" {
count = "${length(var.zones)}"
name = "${cloudflare_zone.zones.*.zone[count.index]}"
settings {
brotli = "on"
security_level = "high"
opportunistic_encryption = "on"
automatic_https_rewrites = "on"
mirage = "on"
waf = "on"
minify {
css = "on"
js = "off"
html = "off"
}
}
}
Note the use of "${cloudflare_zone.zones.*.zone[count.index]}"
in the zone settings for the zone name. This will make sure that Terraform knows that it needs to create the Cloudflare zone before creating the zone settings override rather than not seeing a dependency between the two and trying to create them both at the same time which may potentially fail as the zone is not yet created when Terraform attempts to create the zone settings override.
Or you could move the zone configuration out to a module, allowing you to abstract things, providing a more constrained amount of control of a resource to the module caller:
variable "zone" {}
variable "waf" {
default = "on"
}
resource "cloudflare_zone" "zone" {
zone = "${var.zone}"
}
resource "cloudflare_zone_settings_override" "settings" {
name = "${cloudflare_zone.zone.zone}"
settings {
brotli = "on"
security_level = "high"
opportunistic_encryption = "on"
automatic_https_rewrites = "on"
mirage = "on"
waf = "${var.waf}"
minify {
css = "on"
js = "off"
html = "off"
}
}
}
This module then has a required variable of zone
and an optional, defaulted variable of waf
that controls whether to enable the WAF for the zone. All the other options are set for the caller so the module can simply be called multiple times like this:
module "cloudflare_zone_example1" {
source = "path/to/module"
zone = "example1.com"
}
module "cloudflare_zone_example2" {
source = "path/to/module"
zone = "example2.com"
waf = "off"
}
Upvotes: 2
Reputation: 1478
In order to avoid repetition of Terraform code, you could:
Example for the second solution:
local {
domain_names = [
example1.com,
example2.com,
example3.com
]
}
resource "cloudflare_zone" "these_zones" {
count = "${length(local.domain_names)}"
zone = "${element(local.domain_names, count.index)}"
}
resource "cloudflare_zone_settings_override" "these_zones_settings" {
count = "${length(local.domain_names)}"
name = "${element(local.domain_names, count.index)}"
settings {
brotli = "on"
security_level = "high"
opportunistic_encryption = "on"
automatic_https_rewrites = "on"
mirage = "on"
waf = "on"
minify {
css = "on"
js = "off"
html = "off"
}
}
}
PS: This code is written for terraform < 0.12
Upvotes: 0