I have a Terraform module that creates a Kubernetes NetworkPolicy from sets of predefined policies that are contained in the module. These are defined as object literals that mirror the Kubernetes API spec for a network policy egress rule. For example, one of the object literals looks like this:
locals {
available_egress_policies = {
"https" : {
ports = [
{
port = 443,
protocol = "TCP",
},
],
to = [],
},
}
}
This is a policy that allows the caller to egress on HTTPS to the internet at large.
The resource consuming it looks like this:
resource "kubernetes_network_policy" "policy" {
spec {
dynamic "egress" {
for_each = local.selected_egress_policies
content {
dynamic "ports" {
for_each = egress.value.ports
content {
port = ports.value.port
protocol = ports.value.protocol
}
}
# etc... big mess of dynamic blocks for all possible options
The user specifies which policy stanzas they want in the arguments to the module by name:
module "networkpolicy" {
egress_policies = [ "https" ]
}
I want to extend this module to allow the user to pass in custom policy blocks, so that they can use more policy than just the predefined stanzas in the module. I added a var that looks like this:
variable "custom_policies" {
default = []
type = set(object({
ports = optional(list(object({
port = optional(any) # Can be either a port number or a named port.
protocol = optional(string)
})))
to = optional(list(object({
ip_block = optional(object({
cidr = string
}))
namespace_selector = optional(object({
match_labels = map(string)
}))
})))
}))
}
The problem is that when I try to combine the policies passed in the var and policies selected from the locals so that I can for_each over all of them, I get errors from Terraform that their types arenβt compatible.
This:
locals {
selected_egress_policies = toset([for p in var.egress_policies : local.available_egress_policies[p]])
all_egress_policies = setunion(
local.selected_egress_policies,
var.custom_policies,
)
}
Yields this error:
β·
β Error: Error in function call
β
β on ../networkpolicy/vars.tf line 65, in locals:
β 65: all_egress_policies = setunion(
β 66: local.selected_egress_policies,
β 67: var.custom_policies,
β 68: )
β βββββββββββββββββ
β β local.selected_egress_policies is set of object with 1 element
β β var.custom_policies is set of object with 1 element
β
β Call to function "setunion" failed: given sets must all have compatible
β element types.
β΅
And this:
locals {
selected_egress_policies = setunion(
[for p in var.egress_policies : local.available_egress_policies[p]],
var.custom_policies,
)
}
Yields this error:
β·
β Error: Error in function call
β
β on ../networkpolicy/vars.tf line 64, in locals:
β 64: selected_egress_policies = setunion(
β 65: toset([for p in var.egress_policies : local.available_egress_policies[p]]),
β 66: var.custom_policies,
β 67: )
β βββββββββββββββββ
β β local.available_egress_policies is object with 3 attributes
β β var.custom_policies is set of object with 1 element
β β var.egress_policies is set of string with 1 element
β
β Call to function "setunion" failed: given sets must all have compatible
β element types.
β΅
Is there a way to mush these two together into one set? I would rather not have to copy-paste the entire dynamic "egress"
block to for_each over them separately.