Fairly new to terraform, but loving it!
I need to create mulitple healthcheck with different configuration each.
for instance:
say i have 2 servers that need to have HC:
ip_address = "1.2.3.4"
hc_name = "server1"
hc_port = "80"
ip_address = "4.3.2.1"
hc_name = "server2"
hc_port = "88"
I want to use only one tf, meaning i would like to loop through the servers, something like:
variable "servers" {
type = list
default = [ "server1", "server2" ]
}
variable "server1" {
type = map(string)
default = {
ip_address = "1.2.3.4"
hc_port = "80"
}
variable "server2" {
type = map(string)
default = {
ip_address = "4.3.2.1"
hc_port = "88"
}
and do something like:
resource "aws_route53_health_check" "prod-hc" {
for s in servers:
ip_address = lookup(s,"ip_address")
type = "HTTP"
port = lookup(s,"port")
}
Is this possible at all?
Many thanks!
Hi @davidcsi,
This is the sort of thing we can do with resource for_each
, if you’re able to change slightly the shape of your input variables:
variable "servers" {
type = map(object({
ip_address = string
hc_port = number
}})
}
resource "aws_route53_health_check" "prod" {
for_each = var.servers
ip_address = each.value.ip_address
type = "HTTP"
port = each.value.hc_port
}
An important aspect of resource for_each
is that the keys in the given map become part of the unique address of each instance of that resource. For example, if the caller of the module were to set the value like this:
servers = {
server1 = {
ip_address = "1.2.3.4"
hc_port = 80
}
server2 = {
ip_address = "4.3.2.1"
port = 88
}
}
…then Terraform would see that it should be creating two instances for this resource, with the following addresses:
aws_route53_health_check.prod["server1"]
aws_route53_health_check.prod["server2"]
Because the key is part of the identifying address, if you change one of the IP addresses or port numbers in future without changing the map keys then Terraform will understand that as requesting an update to one of the existing instances, but if you change the map keys or add new elements with different keys then Terraform will understand that as requesting instances to be added and/or removed.
Ok for the moment this is what’s working for me:
variable "servers" {
type = list(map(string))
default = [
{
"ip_address" = "1.2.3.4",
"hc_port" = "80"
},
{
"ip_address" = "4.3.2.1",
"hc_port" = "80"
}
]
}
resource "random_pet" "this" {
count = 1
}
output "subnet" {
value = [
for ip, ip_value in var.servers :
{ ip_address = ip_value }
]
}
Many thanks for your help!
Ok that seems to work with outputs… but i’m trying to use that map in a resource like this:
this is how it works on my test:
output "subnets" {
value = [
for key, value in var.servers :
{
ip_address = value.ip_address
healthcheck_name = value.healthcheck_name
}
]
}
variable "servers" {
type = list(map(string))
default = [
{
ip_address = "1.2.3.4"
healthcheck_name = "prod-fs-1-failure"
resource_path = "/alive.html"
resource_port = "80"
},
{
ip_address = "4.3.2.1"
healthcheck_name = "prod-fs-2-failure"
resource_path = "/alive.html"
resource_port = "80"
},
{
ip_address = "9.8.7.6"
healthcheck_name = "prod-kam-failure"
resource_path = "/alive.html"
resource_port = "8888"
}
]
}
This outputs:
subnet = [
{
"healthcheck_name" = "prod-fs-1-failure"
"ip_address" = "1.2.3.4"
},
{
"healthcheck_name" = "prod-fs-2-failure"
"ip_address" = "4.3.2.1"
},
{
"healthcheck_name" = "prod-kam-failure"
"ip_address" = "9.8.7.6"
},
]
Which is perfect.
But if i want to do the same on a resource like this:
(same variable map)
resource "aws_route53_health_check" "prod-hc" {
for key, value in var.servers :
{
provider = aws.use1
ip_address = value.ip_address
type = "HTTP"
resource_path = value.resource_path
port = value.resource_port
failure_threshold = "2"
request_interval = "30"
regions = var.hc_regions
tags = {
Product = "Servers Monitoring"
Owner = "mp-devops"
TagsComponent = "HeathCheck"
Env = "prod"
Contact = "mp-david"
Name = value.healthcheck_name
}
}
}
I’m getting:
Error: Invalid block definition
on main.tf line 32, in resource "aws_route53_health_check" "prod-hc":
32: for key, value in var.servers :
Either a quoted string block label or an opening brace ("{") is expected here.
Any ideas why?
Thanks
I finally figured it all out, it’s all on https://github.com/davidcsi/terraform
if anyone is interested.
Thanks!