how to use dynamic block in terraform? - azure

main.tf
resource "azurerm_cdn_endpoint" "default" {
for_each = {
for cdn_endpoint in var.cdn_endpoints : cdn_endpoint.endpoint_name => cdn_endpoint
}
name = each.value.endpoint_name
location = coalesce(var.location, data.azurerm_resource_group.current.location)
resource_group_name = data.azurerm_resource_group.current.name
profile_name = azurerm_cdn_profile.default.name
tags = var.resource_tags
origin {
name = random_id.id[each.key].hex
host_name = each.value.origin_host_name
}
dynamic "delivery_rule" {
for_each = {
for deliveryrule in var.delivery_rules : deliveryrule.order => deliveryrule
}
content {
name = delivery_rule.value.name
order = delivery_rule.value.order
request_scheme_condition {
operator = delivery_rule.value.operator
match_values = delivery_rule.value.match_values
}
url_redirect_action {
redirect_type = delivery_rule.value.redirect_type #"Found"
protocol = delivery_rule.value.protocol #"Https"
}
}
}
}
variable.tf
variable "delivery_rules" {
default = {
name = "test"
order = 1
request_scheme_condition = {
match_values = ["HTTP"]
operator = "Equal"
}
}
type = object(
{
name = string
order = number
request_scheme_condition = object({
match_values = list(string)
operator = string
})
})
}
I'm trying to create rule engine for the azure cdn.
getting below error
Error: Unsupported attribute
│
│ on ../../main.tf line 86, in resource "azurerm_cdn_endpoint" "default":
│ 86: protocol = delivery_rule.value.protocol #"Https"
│ ├────────────────
│ │ delivery_rule.value is "test"
│
│ This value does not have any attributes.
╵
╷

Related

Unsupported argument for_each from terraform

I'm trying to create a multiple delivery rules for the azure cdn endpoint through terraform.
But while trying to achieve the same getting below error,
Error: Unsupported argument
│
on main.tf line 71, in resource "azurerm_cdn_endpoint" "default":
71: for_each = {
│
An argument named "for_each" is not expected here.
╵
delivery_rule {
for_each = {
for deliveryrule in var.delivery_rules : deliveryrule.name => deliveryrule
}
name = each.value.name
order = each.value.order
request_scheme_condition {
operator = each.value.operator
match_values = each.value.match_values
}
url_redirect_action {
redirect_type = each.value.redirect_type #"Found"
protocol = each.value.protocol #"Https"
}
}
You have to use dynamic blocks:
dynamic "delivery_rule" {
for_each = {
for deliveryrule in var.delivery_rules : deliveryrule.name => deliveryrule
}
content {
name = delivery_rule.value.name
order = delivery_rule.value.order
request_scheme_condition {
operator = delivery_rule.value.operator
match_values = delivery_rule.value.match_values
}
url_redirect_action {
redirect_type = delivery_rule.value.redirect_type #"Found"
protocol = delivery_rule.value.protocol #"Https"
}
}
}

Terraform throwing error while trying to create Azure service bus subscription filters

I would like to create three Azure service bus subscriptions and then two of the subscriptions need to have filters on them. My code is given below
resource "azurerm_servicebus_topic" "default" {
resource_group_name = azurerm_servicebus_namespace.default.resource_group_name
namespace_name = azurerm_servicebus_namespace.default.name
name = module.names-default.environment.servicebus_topic.name_unique
enable_partitioning = false
}
resource "azurerm_servicebus_subscription" "new-subscr" {
for_each = local.svc_bus_subscr
resource_group_name = azurerm_servicebus_topic.default.resource_group_name
namespace_name = azurerm_servicebus_topic.default.namespace_name
default_message_ttl = "P35D"
topic_name = azurerm_servicebus_topic.default.name
max_delivery_count = 5
name = each.value["name"]
requires_session = each.value["requires_session"]
}
locals {
svc_bus_subscr = {
sub-1 = {
name = format("sbs-%s-%s-%s", var.resource_group_name, (var.resource_group_environment != "main") ? var.resource_group_environment : "dev", "b214")
requires_session = false
}
sub-2 = {
name = format("sbs-%s-%s-%s", var.resource_group_name, (var.resource_group_environment != "main") ? var.resource_group_environment : "dev", "ef14")
requires_session = true
}
sub-3 = {
name = format("sbs-%s-%s-%s", var.resource_group_name, (var.resource_group_environment != "main") ? var.resource_group_environment : "dev", "ck89")
requires_session = true
}
}
}
These are the filters for two of the subscriptions
locals {
svc_bus_subscr_filter = {
filter-b214 = {
name = ""
id = ""
label = ""
}
filter-ef14 = {
name = "MinestarQbEvents"
id = "minestarqb"
label = "red"
}
filter-ck89 = {
name = "WencoHvcEvents"
id = "wencohvc"
label = "red"
}
}
}
resource "azurerm_servicebus_subscription_rule" "filter" {
for_each = { for n in local.svc_bus_subscr : n.name => n }
subscription_name = lookup(local.svc_bus_subscr[each.value.name], "name", null)
name = local.svc_bus_subscr_filter.value.filter_name
resource_group_name = azurerm_servicebus_namespace.default.resource_group_name
topic_name = azurerm_servicebus_topic.default.name
namespace_name = azurerm_servicebus_namespace.default.name
filter_type = "CorrelationFilter"
correlation_filter {
correlation_id = local.svc_bus_subscr_filter.value.id
label = local.svc_bus_subscr_filter.value.label
properties = {
customProperty = "value"
}
}
}
The errors that i get are :
Error: Unsupported attribute
│
│ on resources.sb.tf line 149, in resource "azurerm_servicebus_subscription_rule" "filter":
│ 149: name = local.svc_bus_subscr_filter.value.filter_name
│ ├────────────────
│ │ local.svc_bus_subscr_filter is object with 3 attributes
│
│ This object does not have an attribute named "value".
╵
╷
│ Error: Unsupported attribute
│
│ on resources.sb.tf line 156, in resource "azurerm_servicebus_subscription_rule" "filter":
│ 156: correlation_id = local.svc_bus_subscr_filter.value.id
│ ├────────────────
│ │ local.svc_bus_subscr_filter is object with 3 attributes
│
│ This object does not have an attribute named "value".
╵
╷
│ Error: Unsupported attribute
│
│ on resources.sb.tf line 157, in resource "azurerm_servicebus_subscription_rule" "filter":
│ 157: label = local.svc_bus_subscr_filter.value.label
│ ├────────────────
│ │ local.svc_bus_subscr_filter is object with 3 attributes
│
│ This object does not have an attribute named "value".

How to loop correctly in terraform for_each?

Objective: Loop through azure subnets via terraform.
Code That I use:
Main.tf:
resource "azurerm_network_security_group" "nsg" {
name = "nsg-vnet-hub-${var.env}-indoundDNS"
location = azurerm_resource_group.rg[0].location
resource_group_name = azurerm_resource_group.rg[0].name
tags = {
environment = "${var.env}"
costcentre = "12345"
}
}
resource "azurerm_monitor_diagnostic_setting" "nsg" {
for_each = var.subnets
name = lower("${each.key}-diag")
target_resource_id = azurerm_network_security_group.nsg[each.key].id
storage_account_id = azurerm_storage_account.storeacc.id
log_analytics_workspace_id = azurerm_log_analytics_workspace.logws.id
dynamic "log" {
for_each = var.nsg_diag_logs
content {
category = log.value
enabled = true
retention_policy {
enabled = false
}
}
}
}
My root module variable.tf :
variable "subnets" {
type = map(object({
name = string
}))
default = {
"s1" = { name = "dns_snet"},
"s2" = { name = "common_snet"},
"s3" = { name = "gw_snet"},
"s4" = { name = "data_snet"}
}
}
Problem I am facing:
Error:
network_security_group_id = azurerm_network_security_group.nsg[each.key].id
│ ├────────────────
│ │ azurerm_network_security_group.nsg is object with 7 attributes
│ │ each.key is "s3"
│
│ The given key does not identify an element in this collection value
Just updated this post, now I get error as above. I am referring to below documentation
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/network_security_group
You have only a single instance of azurerm_network_security_group.nsg. Thus there is nothing to iterate over. To fix your error, it should be:
target_resource_id = azurerm_network_security_group.nsg.id

Terraform - Can't access attributes on a primitive-typed value (string)

I am using terraform to deploy MX records in cloudflare. Created locals and flattened them filtering out different values
locals {
MXRecordSets = [
{
Name = "example.com.",
Type = "MX",
TTL = 3600,
MXRecords = [
{
Value = "asdsd.l.google.com",
Priority = 1
},
{
Value = "alt1.asdsd.l.google.com",
Priority = 5
},
{
Value = "alt2.asdsd.l.google.com",
Priority = 5
}
]
}
]
}
locals {
FlatMXRecordSets = merge([
for idx, MXRecordSet in local.MXRecordSets:
{
for MXRecord in MXRecordSet.MXRecords:
"${idx}-${MXRecord.Value}" => {
MXRecordSet = MXRecordSet
MXRecord = MXRecord["Value"]
Priority = MXRecord["Priority"]
}
}
]...)
}
resource "cloudflare_record" "com_records_mx" {
for_each = local.FlatMXRecordSets
zone_id = cloudflare_zone.example_com.id
name = each.value["MXRecordSet"].Name
value = each.value["MXRecord"].Value
type = each.value["MXRecordSet"].Type
proxied = false
ttl = 1
priority = each.value["MXRecord"].Priority
}
While running terraform apply, I am getting an error which says Can't access attributes on a primitive-typed value (string).
╷
│ Error: Unsupported attribute
│
│ on main.tf line 476, in resource "cloudflare_record" "com_records_mx":
│ 476: priority = each.value["MXRecord"].Priority
│ ├────────────────
│ │ each.value["MXRecord"] is "alt2.asdsd.l.google.com"
│
│ Can't access attributes on a primitive-typed value (string).
It appears that the object accessors have a couple issues. Correcting this should look like:
resource "cloudflare_record" "com_records_mx" {
for_each = local.FlatMXRecordSets
zone_id = cloudflare_zone.example_com.id
name = each.value["MXRecordSet"].Name
value = each.value["MXRecord"] # corrected
type = each.value["MXRecordSet"].Type
proxied = false
ttl = 1
priority = each.value["Priority"] # corrected
}

Terraform error while fetching value of subnet in oci

I have this code where I am trying to fetch the id of subnet via subnet name:
The code looks like this :
resource "oci_containerengine_node_pool" "node_pool" {
for_each = var.nodepools
cluster_id = oci_containerengine_cluster.cluster[0].id
compartment_id = var.compartment_id
depends_on = [oci_containerengine_cluster.cluster]
kubernetes_version = var.cluster_kubernetes_version
name = each.value["name"]
node_config_details {
placement_configs {
availability_domain = var.availability_domain
subnet_id = oci_core_subnet.snet-workers[each.value.subnet_name].id
}
size = each.value["size"]
}
node_shape = each.value["node_shape"]
node_shape_config {
#Optional
memory_in_gbs = each.value["memory"]
ocpus = each.value["ocpus"]
}
node_source_details {
image_id = each.value["image_id"]
source_type = "IMAGE"
}
ssh_public_key = file(var.ssh_public_key_path)
}
My subnet code looks like:
resource "oci_core_subnet" "snet-workers" {
cidr_block = lookup(var.subnets["snet-workers"], "subnet_cidr")
compartment_id = var.compartment_id
vcn_id = oci_core_virtual_network.base_vcn.id
display_name = lookup(var.subnets["snet-workers"], "display_name")
dns_label = lookup(var.subnets["snet-workers"], "dns_label")
prohibit_public_ip_on_vnic = true
security_list_ids = [oci_core_security_list.private_worker_nodes.id]
route_table_id = oci_core_route_table.rt-nat.id
}
variables looks like:
variable "subnets" {
description = "List of subnets to create for an environment"
type = map(object({
subnet_cidr = string
display_name = string
dns_label = string
}))
}
my tfvars looks like
nodepools = {
np1 = {
name = "np1"
size = 3
ocpus = 8
memory = 120
image_id = "test"
node_shape = "VM.Standard2.8"
subnet_name = "snet-worker1"
}
np2 = {
name = "np2"
size = 2
ocpus = 8
memory = 120
image_id = "test"
node_shape = "VM.Standard2.8"
subnet_name = "snet-worker2"
}
}
But in terraform plan I am getting error as
Error: Invalid index
│
│ on ../modules/oke/oke.tf line 39, in resource "oci_containerengine_node_pool" "node_pool":
│ 39: subnet_id = oci_core_subnet.snet-workers[each.value.subnet_name].id
│ ├────────────────
│ │ each.value.subnet_name is "snet-worker2"
│ │ oci_core_subnet.snet-workers is object with 22 attributes
│
│ The given key does not identify an element in this collection value.
╵
╷
│ Error: Invalid index
│
│ on ../modules/oke/oke.tf line 39, in resource "oci_containerengine_node_pool" "node_pool":
│ 39: subnet_id = oci_core_subnet.snet-workers[each.value.subnet_name].id
│ ├────────────────
│ │ each.value.subnet_name is "snet-worker1"
│ │ oci_core_subnet.snet-workers is object with 22 attributes
│
│ The given key does not identify an element in this collection value.
Can someone help
The following:
subnet_id = oci_core_subnet.snet-workers[each.value.subnet_name].id
would only work if you had used for_each while creating oci_core_subnet.snet-workers. Since you are not using for_each, it should be:
subnet_id = oci_core_subnet.snet-workers.id
UPDATE
To keep using original version:
resource "oci_core_subnet" "snet-workers" {
for_each = var.subnets
cidr_block = each.value["subnet_cidr"]
compartment_id = var.compartment_id
vcn_id = oci_core_virtual_network.base_vcn.id
display_name = leach.value[""display_name"]
dns_label = each.value["dns_label"]
prohibit_public_ip_on_vnic = true
security_list_ids = [oci_core_security_list.private_worker_nodes.id]
route_table_id = oci_core_route_table.rt-nat.id
}
You have to define a "oci_core_subnet" for each entry in "subnets" variable. Something like this:
resource "oci_core_subnet" "snet-workers" {
for_each = var.subnets
cidr_block = each.value.subnet_cidr
...
}

Resources