How to access parent resource block value in the child resource block? - azure

Here I want to create service bus with queue,topic & subcription in azure , so I want to access parent resource block value of topic_id with contains for_each loop
resource from child block of code which its already having for_each?
"azurerm_servicebus_topic" "default" {
resource "azurerm_servicebus_namespace" "default" {
name = var.resource_name
location = data.azurerm_resource_group.current.location
resource_group_name = data.azurerm_resource_group.current.name
sku = var.sku
capacity = var.capacity
tags = var.resource_tags
lifecycle {
ignore_changes = [
tags,
location
]
}
}
resource "azurerm_servicebus_queue" "default" {
for_each = toset(var.queues)
name = each.value
namespace_id = azurerm_servicebus_namespace.default.id
enable_partitioning = var.enable_partitioning
}
resource "azurerm_servicebus_topic" "default" {
for_each = toset(var.topics)
name = each.value
namespace_id = azurerm_servicebus_namespace.default.id
enable_partitioning = var.enable_partitioning
}
resource "azurerm_servicebus_subscription" "default" {
for_each = toset(var.servicebus_subscription)
name = each.value
topic_id = azurerm_servicebus_topic.default[each.key]
max_delivery_count = var.max_delivery_count
}
variable.tf
topics = ["test001"]
queues = ["test00_queue"]
ip_rules = []
virtual_network_subnet_ids = []
servicebus_subscription=["tf-sub"]
FYI: I'm able to create topic but error thronging from subscription creation time

How to access parent resource block value in the child resource block:
"ID" (topic_id) should be passed forazurerm_servicebus_topic.default[each.key] as azurerm_servicebus_topic.default[each.key].id because each.key doesn't not accept topic_id value which is the ID of the service bus topic to create it in a given subscription.
I made below changes to your code and was able to successfully create a service bus namespace in the given subscription.
resource "azurerm_servicebus_subscription" "default" {
for_each = toset(["topic1","topic2"])
name = each.value
topic_id = azurerm_servicebus_topic.default[each.key].id
max_delivery_count = 1
}
terraform init:
terraform plan:
terraform apply:
Deployed in portal without creation time errors:
Service Bus namespace -> Queues:
Service Bus namespace -> Topics:

Related

How to get object id of user which need to be add in resource group which is running in loop

I have above terraform which will create resource group from csv list and run loop, its showing me error, as object id is not reading.
Any idea how to add owner to resource group created in loop in terraform?
locals {
project_info = csvdecode(test.csv)
}
module "azurerm_resource_group" {
for_each = { for proj in local.project_info : proj.project_name => proj }
source = "../../../modules/azurerm_resource_group"
project_name = each.value.project_name
tags = {
costcenter = ""
expiration = each.value.end_date
owner = each.value.project_owner
project = each.value.project_name
}
}
#------------------------------------------------------------------------------
# Get Object ID of Owner
#------------------------------------------------------------------------------
data "azuread_user" "owner" {
for_each = module.azurerm_resource_group
user_principal_name = lookup(each.value.resourcegroup_tags, "owner")
}
#------------------------------------------------------------------------------
# Assign RG owner access to owner of this project
#------------------------------------------------------------------------------
module "azurerm_role_assignment" {
source = "../../../modules/azurerm_role_assignment"
for_each = module.azurerm_resource_group
scope_id = each.value.id
role_definition_name = "Owner"
principal_id = values(data.azuread_user.owner)[*].object_id
}
Try this:
module "azurerm_role_assignment" {
source = "../../../modules/azurerm_role_assignment"
for_each = module.azurerm_resource_group
scope_id = each.value.id
role_definition_name = "Owner"
principal_id = "${data.azuread_user.owner[each.key].object_id}
}
Share with me the error if it doesn't work.
Hope this helps!

Terraform complains parent resource does not exist even though exist

I am trying to create some resources in azure with terraform.
What I have:
resource "azurerm_log_analytics_workspace" "logws" {
name = lower("log-${var.env}-${local.location_prefix[coalesce(var.location)]}-${random_string.postfix.result}")
resource_group_name = azurerm_resource_group.rg[0].name
location = azurerm_resource_group.rg[0].location
sku = var.log_analytics_workspace_sku
retention_in_days = var.log_analytics_logs_retention_in_days
tags = local.common_tags
}
resource "azurerm_monitor_private_link_scoped_service" "logscopelink" {
name = "scoped-${azurerm_log_analytics_workspace.logws.name}"
resource_group_name = azurerm_resource_group.rg[0].name
scope_name = azurerm_log_analytics_workspace.logws.name
linked_resource_id = azurerm_log_analytics_workspace.logws.id
depends_on = [azurerm_log_analytics_workspace.logws]
}
log analytics workspace is created but its when it try to create private_link_scoped_service it fails saying, parent resource not found.
Error I get:
│ Error: creating/updating Private Link Scoped Service: (Scoped Resource Name "scoped-log-sbx-we-oe728m" / Private Link Scope Name "log-sbx-we-oe728m" / Resource Group "hub"): insights.PrivateLinkScopedResourcesClient#CreateOrUpdate: Failure sending request: StatusCode=404 -- Original Error: Code="ParentResourceNotFound" Message="Can not perform requested operation on nested resource. Parent resource 'log-sbx-we-oe728m' not found."
I verified via azure portal, that logws does exist.
Can someone suggest what is wrong here.
You need to create a new azurerm_monitor_private_link_scope resource, then reference it in the scope_name attribute of the azurerm_monitor_private_link_scoped_service resource, example:
resource "azurerm_log_analytics_workspace" "logws" {
name = lower("log-${var.env}-${local.location_prefix[coalesce(var.location)]}-${random_string.postfix.result}")
resource_group_name = azurerm_resource_group.rg[0].name
location = azurerm_resource_group.rg[0].location
sku = var.log_analytics_workspace_sku
retention_in_days = var.log_analytics_logs_retention_in_days
tags = local.common_tags
}
# New resource required
resource "azurerm_monitor_private_link_scope" "example" {
name = var.private_link_scope_name
resource_group_name = azurerm_resource_group.rg[0].name
}
resource "azurerm_monitor_private_link_scoped_service" "logscopelink" {
name = "scoped-${azurerm_log_analytics_workspace.logws.name}"
resource_group_name = azurerm_resource_group.rg[0].name
scope_name = azurerm_monitor_private_link_scope.example.name
linked_resource_id = azurerm_log_analytics_workspace.logws.id
}
Note that I've removed the explicit depends_on attribute as Terraform can infer on its own the dependencies between resources when you reference an attribute from a resource in another resource block.

Get ARNs of subnets and iterate over them

I have created some subnets. I want to share those subnets with other accounts. For that I need to retrieve the ARN of the subnets.
I am able to get a list of ARNs like this
data "aws_subnets" "dev_subnet" {
filter {
name = "vpc-id"
values = [module.vpc.vpc_id]
}
tags = {
Environment = "dev-*"
}
}
data "aws_subnet" "dev_subnet" {
for_each = toset(data.aws_subnets.dev_subnet.ids)
id = each.value
}
output "dev_subnet_arns" {
value = [for s in data.aws_subnet.dev_subnet : s.arn]
}
This results in
+ dev_subnet_arns = [
+ "arn:aws:ec2:ca-central-1:0097747:subnet/subnet-013987fd9651c3545",
+ "arn:aws:ec2:ca-central-1:0477747:subnet/subnet-015d76b264280321a",
+ "arn:aws:ec2:ca-central-1:0091747:subnet/subnet-026cd0402fe283c33",
]
Now I want to take the list of arns of the subnets and associate them with the resource_share_arn
What Im trying is something like this
resource "aws_ram_resource_association" "example" {
for_each = toset(data.aws_subnets.dev_subnet.ids)
resource_arn = each.value
resource_share_arn = aws_ram_resource_share.share_subnets_with_dev_account.arn
}
But this fails since it only gets the subnets ids and thats wrong
error associating RAM Resource Share: MalformedArnException: The specified resource ARN subnet-0c4afd736c18b3c28 is not valid. Verify the ARN and try again.
This also fails
resource "aws_ram_resource_association" "example" {
for_each = toset(data.aws_subnets.dev_subnet.arn)
resource_arn = each.value
resource_share_arn = aws_ram_resource_share.share_subnets_with_dev_account.arn
}
since arn is not an attribute. What am I missing here ?
You need to loop over the ARNs of the subnets and pass the ARN value for the resource_arn:
resource "aws_ram_resource_association" "example" {
for_each = toset([for s in data.aws_subnet.dev_subnet : s.arn])
resource_arn = each.value
resource_share_arn = aws_ram_resource_share.share_subnets_with_dev_account.arn
}
Or another solution would be:
resource "aws_ram_resource_association" "example" {
for_each = toset(values(data.aws_subnet.dev_subnet)[*].arn)
resource_arn = each.value
resource_share_arn = aws_ram_resource_share.share_subnets_with_dev_account.arn
}

Azure Databricks workspace using terraform

Trying to create Databricks workspace using terraform but unsupported arguments:
resource "azurerm_databricks_workspace" "workspace" {
name = "testdata"
resource_group_name = "cloud-terraform"
location = "east us"
sku = "premium"
virtual_network_id = azurerm_virtual_network.vnet.id
public_subnet_name = "databrickpublicsubnet"
public_subnet_cidr = "10.0.0.0/22"
private_subnet_name = "databrickprivatesubnet"
private_subnet_cidr = "10.0.0.0/22"
tags = {
Environment = "terraformtest"
}
}
Error: An argument named "virtual_network_id" is not expected here. An argument named "public_subnet_name" is not expected here. An argument named "public_subnet_cidr" is not expected here.
I haven't tried to set up databricks via Terraform, but I believe (per the docs) you need add those properties in a block:
resource "azurerm_databricks_workspace" "workspace" {
name = "testdata"
resource_group_name = "cloud-terraform"
location = "east us"
sku = "premium"
custom_parameters {
virtual_network_id = azurerm_virtual_network.vnet.id
public_subnet_name = "databrickpublicsubnet"
private_subnet_name = "databrickprivatesubnet"
}
tags = {
Environment = "terraformtest"
}
}
The two cidr entries aren't part of the TF documentation.
true. you can add terraform commands to create the subnets (assuming vnet already exists, you can use data azurerm_virtual_network then create the two new subnets, then reference the names of the two new public/private subnets.
Then you run into what seems to be a chicken/egg issue though.
You get Error: you must define a value for 'public_subnet_network_security_group_association_id' if 'public_subnet_name' is set.
Problem is, the network security group is typically auto-generated on creation of the databrick workspace (like databricksnsgrandomstring), which works when creating it in the portal, but via terraform, I have to define it to create the workspace, but it doesn't yet exist until I create the workspace. The fix is to not let it generate it's own nsg name, but name it yourself with an nsg resource block.
below is code I use (dbname means databricks name!). here I'm
adding to an existing resource group 'qa' and existing vnet as well, only showing the public subnet and nsg association, you can easily add the private ones). just copy/modify in your own tf file(s). and you'll definitely need to change the address_prefix to your own CIDR values that works within your vnet and not stomp on existing subnets within.
resource "azurerm_subnet" "public" {
name = "${var.dbname}-public-subnet"
resource_group_name = data.azurerm_resource_group.qa.name
virtual_network_name = data.azurerm_virtual_network.vnet.name
address_prefixes = ["1.2.3.4/24"]
delegation {
name = "databricks_public"
service_delegation {
name = "Microsoft.Databricks/workspaces"
}
}
}
resource "azurerm_network_security_group" "nsg" {
name = "${var.dbname}-qa-databricks-nsg"
resource_group_name = data.azurerm_resource_group.qa.name
location= data.azurerm_resource_group.qa.location
}
resource "azurerm_subnet_network_security_group_association" "nsga_public" {
network_security_group_id = azurerm_network_security_group.nsg.id
subnet_id = azurerm_subnet.public.id
}
Then in your databricks_workspace block, replace your custom parameters with
custom_parameters {
public_subnet_name = azurerm_subnet.public.name
public_subnet_network_security_group_association_id = azurerm_subnet_network_security_group_association.nsga_public.id
private_subnet_name = azurerm_subnet.private.name
private_subnet_network_security_group_association_id = azurerm_subnet_network_security_group_association.nsga_private.id
virtual_network_id = data.azurerm_virtual_network.vnet.id
}

Terraform - Creating Azure Event Grid Subscriptions - can it do it?

I've been struggling for a while in Terraform to create an Event Subscription in an Azure Event Grid
As-per screenshot....
EVENT SUBSCRIPTION DETAILS
NAME : EventGrid-Sub1
(don't need to change Event Schema)
TOPIC DETAILS
Event Grid Domain
Topic Resource: EDG-SBX-EventGrid1
Domain Type: EventGrid-DomainTopic1
ENDPOINT DETAILS
Endpoint Type: Event Hubs
Endpoint : eh-sbx-Ingestion
I've been using these as reference, but it seems not only a bit chicken-and-egg, but pieces missing?
https://www.terraform.io/docs/providers/azurerm/r/eventgrid_event_subscription.html
https://www.terraform.io/docs/providers/azurerm/r/eventgrid_topic.html
Has anyone got this working in Terraform?
Thanks in advance
Azure Screenshot on Event Grids / Create Event Subscription screen
#nmca70 There are a couple of ways to achieve this:
Create an ARM template from the final deployment and then run that ARM template using Terraform:
https://www.terraform.io/docs/providers/azurerm/r/template_deployment.html
Create resources in the below order:
Azure event hub: https://www.terraform.io/docs/providers/azurerm/r/eventhub.html
Azure event grid topic: https://www.terraform.io/docs/providers/azurerm/r/eventgrid_topic.html
Azure event grid domain: https://www.terraform.io/docs/providers/azurerm/r/eventgrid_domain.html
Azure event grid subscription: https://www.terraform.io/docs/providers/azurerm/r/eventgrid_event_subscription.html#storage_queue_endpoint
A sample:
resource "azurerm_resource_group" "test" {
name = "resourceGroup1"
location = "West US 2"
}
resource "azurerm_eventhub_namespace" "test" {
name = "acceptanceTestEventHubNamespace"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
sku = "Standard"
capacity = 1
kafka_enabled = false
tags = {
environment = "Production"
}
}
resource "azurerm_eventhub" "test" {
name = "acceptanceTestEventHub"
namespace_name = "${azurerm_eventhub_namespace.test.name}"
resource_group_name = "${azurerm_resource_group.test.name}"
partition_count = 2
message_retention = 1
}
resource "azurerm_eventgrid_topic" "test" {
name = "my-eventgrid-topic"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
tags = {
environment = "Production"
}
}
resource "azurerm_eventgrid_domain" "test" {
name = "my-eventgrid-domain"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
input_schema = "eventgridschema"
input_mapping_fields= {
topic = "my-eventgrid-topic"
}
tags = {
environment = "Production"
}
}
resource "azurerm_eventgrid_event_subscription" "default" {
name = "defaultEventSubscription"
scope = "${azurerm_resource_group.default.id}"
event_delivery_schema = "EventGridSchema"
topic_name = "my-eventgrid-topic"
eventhub_endpoint {
storage_account_id = "${azurerm_eventhub.test.id}"
}
}
Hope this helps!

Resources