Hi,
I came across this issue yesterday when supplying a map of objects as a variable to a module and even after I “fixed” it, it wasn’t obvious to me why I was seeing this behaviour. Here’s an example of what my configuration looked like:
Code calling the module:
locals {
dashboards = {
app_service_plans = var.app_service_plans_dashboard
}
}
module "grafana_dashboards" {
source = "../../modules/grafana_dashboard"
for_each = local.dashboards
environment = var.env
dashboard_folder = each.value.folder
dashboard_title = each.value.title
dashboard_json_model = each.value.template_json
dashboard_panels = each.value.panels
}
var.app_service_plans_dashboard definition:
variable "app_service_plans_dashboard" {
type = object({
title = string
folder = string
template_json = string
panels = list(object({
title = string
type = string
metric = string
metric_namespace = string
alerts = optional(map(object({
enabled = optional(bool, false)
pause_evaluation = optional(bool, false)
aggregation = optional(string, "Average")
threshold = optional(number)
interval_ms = optional(number, 60000)
reduction_expression = optional(string, "last")
eval_operator = optional(string)
pending_period = optional(string, "5m")
contact_point = optional(string)
time_range = optional(number, 21600)
})), {})
}))
})
default = null
}
var.app_service_plans_dashboard value in tfvars:
app_service_plans_dashboard = {
title = "OCPP App Service Plans (Dev)"
folder = "OCPP Dev"
template_json = "./templates/generic-grafana-dashboard.tftpl"
panels = [
{
title = "CPU % (Avg)"
type = "timeseries"
metric = "CpuPercentage"
metric_namespace = "Microsoft.Web/serverFarms"
panel_aggregation = "Average"
alerts = {
Teams = {
enabled = true
aggregation = "Average"
threshold = 85
reduction_expression = "last"
eval_operator = "gt"
pending_period = "10m"
contact_point = "default-not-in-use"
}
}
},
{
title = "HTTP Queue Length"
type = "timeseries"
metric = "HttpQueueLength"
metric_namespace = "Microsoft.Web/serverFarms"
},
{
title = "Data In"
type = "timeseries"
metric = "BytesReceived"
metric_namespace = "Microsoft.Web/serverFarms"
}
]
}
definition of panels
inside the grafana_dashboard module:
variable "app_service_plans_dashboard" {
type = object({
title = string
folder = string
template_json = string
panels = list(object({
title = string
type = string
metric = string
metric_namespace = string
alerts = optional(map(object({
enabled = optional(bool, false)
panel_id = optional(number, -1)
pause_evaluation = optional(bool, false)
aggregation = optional(string, "Average")
threshold = optional(number)
interval_ms = optional(number, 60000)
reduction_expression = optional(string, "last")
eval_operator = optional(string)
pending_period = optional(string, "5m")
contact_point = optional(string)
time_range = optional(number, 21600)
})), {})
}))
})
default = null
}
The full error was:
The given value is not suitable for module.grafana_dashboards["app_service_plans"].var.dashboard_panels declared at ../../global_modules/grafana_dashboard/variables.tf:21,1-28: element types must all match for conversion to list
and the fix that I eventually came to was that the variable declared in variables.tf
outside of the module was missing the panel_id
attribute. I was under the impression that since that attribute existed in the module variables.tf
as optional and with a default, that this should have worked anyway?
I’m sure there’s something I’m missing here, I was just curious as performing some testing with similar code, I was struggling to replicate it. The above are just excerpts from the code, so if it helps to include the whole configuration, I can provide that somewhere.
If anyone bothered to read all of that, thanks!