So I'm trying to write something that will allow me to create topics and subscriptions in a loop and while I think I've achieved that thanks to code founded here, I'm facing some problems and I'n not sure how to resolve them. It looks like sometimes bicep fails because it try to create subscription when topics creation is not yet finished. When I re-run my pipeline, it works just fine. I guess this is the reason:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/linter-rule-use-parent-property
The error I get is:
The incoming request is not recognized as a namespace policy put request. ttps://aka.ms/sbResourceMgrExceptions. TrackingId:e1d2c50d-fe92-43d8-abfe-8eb2c1917a70_G5, SystemTracker:ihdev-nonprod-servicebus.servicebus.windows.net:dev-sb-topic-test/subscriptions/dev-sb-sub-test, Timestamp:2024-04-08T13:33:29 (Code: MessagingGatewayNotFoundStatusCode
I'm not sure how to avoid this error.
Is there a way to create particular subscription only if corresponding topic was created? I guess I cannot simply add dependsOn[i]
as I would have to change from for topic in topicsAndSubscriptions
to something like for (topic, i) in topicsAndSubscriptions
but maybe I'm wrong?
Main.bicepparam:
using './main.bicep'
param serviceBusNamespaceName = '#{SBUS_NAMESPACE_NAME}#'
param topicsAndSubscriptions = [
{
name: 'dev-sb-top-failure'
subscriptions: [
'dev-sb-sub-failure'
]
}
{
name: 'xrm-dev-sb-report-completion'
subscriptions: [
'dev-sb-sub-report-completion'
]
}
{
name: 'dev-sb-top-completion'
subscriptions: [
'dev-sb-sub-completion'
]
}
{
name: 'dev-sb-top-discharge'
subscriptions: [
'dev-sb-sub-discharge'
]
}
]
Here is the code for main.bicep
@description('Name of the Service Bus namespace')
param serviceBusNamespaceName string
@description('Location for all resources.')
param location string = resourceGroup().location
param topicsAndSubscriptions array
resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2022-01-01-preview' = {
name: serviceBusNamespaceName
location: location
sku: {
name: 'Premium'
}
properties: {}
}
resource serviceBusTopic 'Microsoft.ServiceBus/namespaces/topics@2022-10-01-preview' = [
for topic in topicsAndSubscriptions: {
parent: serviceBusNamespace
name: topic.name
properties: {}
}
]
module subs 'modules/subscription.bicep' = [
for topic in topicsAndSubscriptions: {
name: '${topic.name}-subs'
params: {
servicebusNamespaceName: serviceBusNamespaceName
topicName: topic.name
subscriptions: topic.subscriptions
}
}
]
module file:
param servicebusNamespaceName string
param topicName string
param subscriptions array = ['asubscription', 'anotherone']
resource sub 'Microsoft.ServiceBus/namespaces/topics/subscriptions@2022-10-01-preview' = [
for i in subscriptions: {
name: '${servicebusNamespaceName}/${topicName}/${i}'
properties: {}
}
]
Implicit dependency is recommended in your circumstance
main.bicep
@description('Name of the Service Bus namespace')
param serviceBusNamespaceName string
@description('Location for all resources.')
param location string = resourceGroup().location
param topicsAndSubscriptions array
resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2022-01-01-preview' = {
name: serviceBusNamespaceName
location: location
sku: {
name: 'Premium'
}
properties: {}
}
resource serviceBusTopic 'Microsoft.ServiceBus/namespaces/topics@2022-10-01-preview' = [ for topic in topicsAndSubscriptions: {
parent: serviceBusNamespace
name: topic.name
properties: {}
}
]
module subs 'modules/subscription.bicep' = [ for (topic, i) in topicsAndSubscriptions: {
name: '${topic.name}-subs'
params: {
servicebusNamespaceName: serviceBusNamespaceName
topicName: serviceBusTopic[i].name
subscriptions: topic.subscriptions
}
}
]
subscription.bicep
param servicebusNamespaceName string
param topicName string
param subscriptions array = ['asubscription', 'anotherone']
resource sub 'Microsoft.ServiceBus/namespaces/topics/subscriptions@2022-10-01-preview' = [ for i in subscriptions: {
name: '${servicebusNamespaceName}/${topicName}/${i}'
properties: {}
}
]
main.bicepparam
using './main.bicep'
param serviceBusNamespaceName = '#{SBUS_NAMESPACE_NAME}#'
param topicsAndSubscriptions = [
{
name: 'dev-sb-top-failure'
subscriptions: [
'dev-sb-sub-failure'
]
}
{
name: 'xrm-dev-sb-report-completion'
subscriptions: [
'dev-sb-sub-report-completion'
]
}
{
name: 'dev-sb-top-completion'
subscriptions: [
'dev-sb-sub-completion'
]
}
{
name: 'dev-sb-top-discharge'
subscriptions: [
'dev-sb-sub-discharge'
]
}
]
topicName: serviceBusTopic[i].name here will allow topic deployment before corresponding subscription. I have test it, works well.
update to modules
main.bicep
@description('Name of the Service Bus namespace')
param serviceBusNamespaceName string
@description('Location for all resources.')
param location string = resourceGroup().location
param topicNames array
param subscriptionNames array
resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces@2022-01-01-preview' = {
name: serviceBusNamespaceName
location: location
sku: {
name: 'Premium'
}
properties: {}
}
module topics 'modules/topic.bicep' = {
name: 'topicDeployment'
params: {
serviceBusNamespaceName: serviceBusNamespaceName
topicNames: topicNames
}
dependsOn:[
serviceBusNamespace
]
}
module subscriptions 'modules/subscription.bicep' = {
name: 'subsDeployment'
params: {
servicebusNamespaceName: serviceBusNamespaceName
subscriptionNames: subscriptionNames
topicNames: topicNames
}
dependsOn:[
serviceBusNamespace
topics
]
}
topic.bicep
param serviceBusNamespaceName string
param topicNames array
resource topicModule 'Microsoft.ServiceBus/namespaces/topics@2022-10-01-preview' = [for (item, i) in topicNames: {
name: '${serviceBusNamespaceName}/${item}'
}]
subscription.bicep
param servicebusNamespaceName string
param topicNames array
param subscriptionNames array
resource sub 'Microsoft.ServiceBus/namespaces/topics/subscriptions@2022-10-01-preview' = [ for (item, i) in subscriptionNames: {
name: '${servicebusNamespaceName}/${topicNames[i]}/${item}'
properties: {}
}
]
main.bicepparam
using './main.bicep'
param serviceBusNamespaceName = 'wbevent'
param topicNames = [
'dev-sb-top-failure'
'xrm-dev-sb-report-completion'
'dev-sb-top-completion'
'dev-sb-top-discharge'
]
param subscriptionNames = [
'dev-sb-sub-failure'
'dev-sb-sub-report-completion'
'dev-sb-sub-completion'
'dev-sb-sub-discharge'
]