I woudl like to create a Azure Dashboard template to monitor CPU percentage for my App Service Plan. Currently It look like this:
resource dashboardName_resource 'Microsoft.Portal/dashboards#2020-09-01-preview' = {
name: dashboardName
location: location
properties: {
lenses: [
{
order: 0
parts: [
{
position: {
x: 0
y: 4
rowSpan: 3
colSpan: 11
}
metadata: {
inputs: [
{
name: 'queryInputs'
value: {
timespan: {
duration: 'PT1H'
}
id: resourceId(appServicePlanResourceGroup, 'Microsoft.Web/serverfarms', appServicePlanName)
chartType: 0
metrics: [
{
name: 'CPU Percentage'
resourceId: resourceId(appServicePlanResourceGroup, 'Microsoft.Web/serverfarms', appServicePlanName)
}
]
}
}
]
type: 'Extension/Microsoft_Azure_Monitoring/PartType/MetricsChartPart'
}
}
]
}
]
}
}
The validation & deployment was succesfull, but when I get to this dashboard i got this:
Does anyon knows why?
By referring a document from MS sample replica of your bicep code is created and was able to deploy it successfully.
While I am doing a repro, I have changed type extension in .bicep file fromtype:'Extension/Microsoft_Azure_Monitoring/PartType/MetricsChartPart to type:'Extension/HubsExtension/PartType/MonitorChartPart' which got succeeded and able to view the CPU metrics.
Attaching a sample code for your reference:
param location string = resourceGroup().location
param appServicePlanResourceGroup string = 'xxxxx'
param appServicePlanName string = 'xxxxxxx'
resource symbolicname 'Microsoft.Portal/dashboards#2020-09-01-preview' = {
name: 'xxxxmydemo'
location: location
tags: {
demo: 'repro01'
}
properties: {
lenses: [
{
metadata: {}
order: 2
parts: [
{
metadata: {
type: 'Extension/HubsExtension/PartType/MonitorChartPart'
inputs: [
{
name: 'queryInputs'
value: {
timespan: {
duration: 'PT1H'
}
id: resourceId(appServicePlanResourceGroup, 'Microsoft.Web/serverfarms', appServicePlanName)
chartType: 0
metrics: [
{
name: 'CPU Percentage'
resourceId: resourceId(appServicePlanResourceGroup, 'Microsoft.Web/serverfarms', appServicePlanName)
}
]
}
}
]
}
position: {
colSpan: 11
metadata: {}
rowSpan: 5
x: 3
y: 4
}
}
]
}
]
metadata: {}
}
}
Output for your reference:
Note: Validate access control(IAM) permissions for the resource group ideally and it should be part of it.
Related
I am trying to deploy a bicep template to create a logic app and service bus using VS Code. But When I am trying to deploy the Bicep to azure portal
I am getting bad request error
enter image description here
Here is my Bicep look like
param prefix string
param location string = resourceGroup().location
param sendGridApiKey string
resource serviceBus 'Microsoft.ServiceBus/namespaces#2021-11-01' existing = {
name: '${prefix}sb'
}
resource serviceBusConnection 'Microsoft.Web/connections#2016-06-01' = {
name: '${prefix}sbconn'
location: location
properties: {
displayName: '${prefix}sb'
api: {
id: '${subscription().id}/providers/Microsoft.Web/locations/${location}/managedApis/servicebus'
}
parameterValueSet: {
name: 'managedIdentityAuth'
values: {
namespaceEndpoint: {
value: 'sb://${serviceBus.name}.servicebus.windows.net'
}
}
}
}
}
resource sendGridConnection 'Microsoft.Web/connections#2016-06-01' = {
name: '${prefix}sndgrdconn'
location: location
properties: {
displayName: '${prefix}sndgrdconn'
api: {
id: '${subscription().id}/providers/Microsoft.Web/locations/${location}/managedApis/sendgrid'
}
parameterValues: {
apiKey: sendGridApiKey
}
}
}
resource logicAppEmailSend 'Microsoft.Logic/workflows#2019-05-01' = {
name: '${prefix}logic-EmailSend'
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
state: 'Enabled'
definition: {
'$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#'
contentVersion: '1.0.0.0'
parameters: {
'$connections': {
defaultValue: {}
type: 'Object'
}
}
}
}
}
I have tried a lot but didn't find the error
thanks in advance.
I have modified a bit of code in the given code so it's working, and I have deployed the bicep file using VS Code to Azure
{subscription().id}/providers/Microsoft.Web/locations/{location}/servicebus
I have changed the above path to
{subscription().id}/providers/Microsoft.Web/locations/{location}/managedApis/servicebus
Thanks to #mattruma for Bicep template
param prefix string
param location string = resourceGroup().location
param sendGridApiKey string
resource serviceBus 'Microsoft.ServiceBus/namespaces#2021-11-01' existing = {
name: '${prefix}sb'
}
resource serviceBusConnection 'Microsoft.Web/connections#2016-06-01' = {
name: '${prefix}sbconn'
location: location
properties: {
displayName: '${prefix}sb'
api:
{
id: '${subscription().id}/providers/Microsoft.Web/locations/${location}/managedApis/servicebus'
}
parameterValueSet:
{
name: 'managedIdentityAuth'
values:
{
namespaceEndpoint:
{
value: 'sb://${serviceBus.name}.servicebus.windows.net'
}
}
}
}
}
resource logicAppEmailSend 'Microsoft.Logic/workflows#2019-05-01' = {
name: '${prefix}logic-EmailSend'
location: location
identity: {
type: 'SystemAssigned'
}
properties:
{
state: 'Enabled'
definition:
{
'$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#'
contentVersion: '1.0.0.0'
parameters:
{
'$connections': {
defaultValue: { }
type: 'Object'
}
}
triggers:
{
'When_a_message_is_received_in_a_queue_(auto-complete)': {
recurrence:
{
frequency: 'Minute'
interval: 3
}
evaluatedRecurrence:
{
frequency: 'Minute'
interval: 3
}
type: 'ApiConnection'
inputs:
{
host:
{
connection:
{
name: '#parameters(\'$connections\')[\'servicebus\'][\'connectionId\']'
}
}
method: 'get'
path: '/#{encodeURIComponent(encodeURIComponent(\'emailsend\'))}/messages/head'
queries:
{
queueType: 'Main'
}
}
}
}
actions:
{
'Dead-letter_the_message_in_a_queue': {
runAfter:
{
Send_email: [
'Failed'
'TimedOut'
]
}
type: 'ApiConnection'
inputs:
{
host:
{
connection:
{
name: '#parameters(\'$connections\')[\'servicebus\'][\'connectionId\']'
}
}
method: 'post'
path: '/#{encodeURIComponent(encodeURIComponent(\'emailsend\'))}/messages/deadletter'
queries:
{
deadLetterErrorDescription: ''
deadLetterReason: ''
lockToken: '#triggerBody()?[\'LockToken\']'
sessionId: '#triggerBody()?[\'SessionId\']'
}
}
}
Parse_message:
{
runAfter: { }
type: 'ParseJson'
inputs:
{
content: '#base64ToString(triggerBody()?[\'ContentData\'])'
schema:
{
properties:
{
body:
{
type: 'string'
}
subject:
{
type: 'string'
}
to:
{
type: 'string'
}
}
type: 'object'
}
}
}
Send_email:
{
runAfter:
{
Parse_message: [
'Succeeded'
]
}
type: 'ApiConnection'
inputs:
{
body:
{
from: 'someone#somewhere.com'
fromname: 'Someone'
ishtml: true
subject: '#body(\'Parse_message\')?[\'subject\']'
text: '<p>#{body(\'Parse_message\')?[\'body\']}</p>'
to: '#body(\'Parse_message\')?[\'to\']'
}
host:
{
connection:
{
name: '#parameters(\'$connections\')[\'sendgrid\'][\'connectionId\']'
}
}
method: 'post'
path: '/v4/mail/send'
}
}
}
outputs: { }
}
parameters:
{
'$connections': {
value:
{
servicebus:
{
connectionId: serviceBusConnection.id
connectionName: serviceBusConnection.name
connectionProperties: {
authentication:
{
type: 'ManagedServiceIdentity'
}
}
id: '${subscription().id}/providers/Microsoft.Web/locations/${location}/managedApis/servicebus'
}
}
}
}
}
}
After successfully deploying to azure portal
Click on Goto resource group it will redirect to below page
I have a bicep file which is supposed to create a virtual network gateway. I have broken it down by having a seperate bicep file that creates the virtual network. What I really ought to do is have a module for the vnet creation and another for the virtual network gateway, as bicep is new to me, I prefer to do things with little steps and then improve.
What am I trying to achieve ?
Create a virtual network gateway using bicep. I have it as an ARM template which currently works. I converted the ARM template to a bicep file, and this has failed to successfully deploy.
param location string = resourceGroup().location
param rg string = resourceGroup().name
param virtual_network_name string = 'my_virtual_network'
param gwSubnetName string = 'myGatewaySubnet'
param public_ip_gateway string = 'my_public_ip'
param p2s_vpn_name string = 'myPoint_toSite'
param p2s_subnet_name string = 'p2s_subnet'
resource public_ip_gateway_resource 'Microsoft.Network/publicIPAddresses#2022-01-01' = {
name: public_ip_gateway
location: location
sku: {
name: 'Basic'
tier: 'Regional'
}
properties: {
ipAddress: '40.161.130.50'
publicIPAddressVersion: 'IPv4'
publicIPAllocationMethod: 'Dynamic'
idleTimeoutInMinutes: 4
ipTags: []
}
}
resource virtual_network_name_GatewaySubnet 'Microsoft.Network/virtualNetworks/subnets#2022-01-01' = {
name: '${virtual_network_name}/GatewaySubnet'
properties: {
addressPrefix: '10.2.255.0/25'
delegations: []
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
dependsOn: [
virtual_network_name_resource
]
}
resource virtual_network_name_p2s_subnet 'Microsoft.Network/virtualNetworks/subnets#2022-01-01' = {
name: '${virtual_network_name}/p2s_subnet'
properties: {
addressPrefix: '10.2.1.0/24'
serviceEndpoints: []
delegations: []
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
dependsOn: [
virtual_network_name_resource
]
}
resource p2s_vpn_name_resource 'Microsoft.Network/virtualNetworkGateways#2022-01-01' = {
name: p2s_vpn_name
location: location
properties: {
enablePrivateIpAddress: false
ipConfigurations: [
{
name: 'default'
id: '${p2s_vpn_name_resource.id}/ipConfigurations/default'
properties: {
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: {
id: public_ip_gateway_resource.id
}
subnet: {
id: virtual_network_name_GatewaySubnet.id
}
}
}
]
natRules: []
enableBgpRouteTranslationForNat: false
disableIPSecReplayProtection: false
sku: {
name: 'VpnGw1'
tier: 'VpnGw1'
}
gatewayType: 'Vpn'
vpnType: 'RouteBased'
enableBgp: false
activeActive: false
vpnClientConfiguration: {
vpnClientAddressPool: {
addressPrefixes: [
'119.x.x.0/24'
]
}
vpnClientProtocols: [
'OpenVPN'
]
vpnAuthenticationTypes: [
'Certificate'
]
vpnClientRootCertificates: [
{
name: 'Rahman'
id: '${p2s_vpn_name_resource.id}/vpnClientRootCertificates/MyCert'
properties: {
publicCertData: 'xxxxxxxxxxx=='
}
}
]
vpnClientRevokedCertificates: []
radiusServers: []
vpnClientIpsecPolicies: []
}
bgpSettings: {
asn: 65515
bgpPeeringAddress: '10.2.255.126'
peerWeight: 0
bgpPeeringAddresses: [
{
ipconfigurationId: '${p2s_vpn_name_resource.id}/ipConfigurations/default'
customBgpIpAddresses: []
}
]
}
customRoutes: {
addressPrefixes: []
}
vpnGatewayGeneration: 'Generation1'
}
}
resource virtual_network_name_resource 'Microsoft.Network/virtualNetworks#2022-01-01' = {
name: virtual_network_name
location: location
properties: {
addressSpace: {
addressPrefixes: [
'10.2.0.0/16'
]
}
subnets: [
{
name: 'GatewaySubnet'
id: resourceId(rg, 'Microsoft.Network/virtualNetworks/subnets', virtual_network_name ,gwSubnetName)
properties: {
addressPrefix: '10.2.255.0/25'
delegations: []
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
type: 'Microsoft.Network/virtualNetworks/subnets'
}
{
name: 'p2s_subnet'
// id: virtual_network_name_p2s_subnet.id
id: resourceId(rg, 'Microsoft.Network/virtualNetworks/subnets', virtual_network_name ,p2s_subnet_name)
properties: {
addressPrefix: '10.1.1.0/24'
serviceEndpoints: []
delegations: []
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
type: 'Microsoft.Network/virtualNetworks/subnets'
}
]
virtualNetworkPeerings: []
enableDdosProtection: false
}
}
what have I done ?
I have tried to get around circular reference issues by creating the virtual network first, and referencing it using the example below.
instead of id: virtual_network_name_p2s_subnet.id I have changed it to
id: resourceId(rg, 'Microsoft.Network/virtualNetworks/subnets', virtual_network_name ,p2s_subnet_name)
However I'm unsure as to how to deal with cases like
ipconfigurationId: '${p2s_vpn_name_resource.id}/ipConfigurations/default' when the virtual networ gateway has not been created, I have no way of knowing what the ipconfigurationID would be.
This leads to the error
This expression is referencing its own declaration, which is not allowed.bicep(BCP079)
Few things here,
You're defining the subnets multiple times: in the vnet resource and separately. You only need to define them once inside the vnet resource. As you suggested you could then reference them like that:
resourceId(rg, 'Microsoft.Network/virtualNetworks/subnets', virtual_network_name_resource.name ,p2s_subnet_name)
If you need to reference the same resource, you could always do it like that as well:
resourceId('Microsoft.Network/virtualNetworkGateways/ipConfigurations', p2s_vpn_name, 'default')
Here is is simplified version of your template:
param location string = resourceGroup().location
param virtual_network_name string = 'my_virtual_network'
param gwSubnetName string = 'myGatewaySubnet'
param public_ip_gateway string = 'my_public_ip'
param p2s_vpn_name string = 'myPoint_toSite'
param p2s_subnet_name string = 'p2s_subnet'
resource public_ip_gateway_resource 'Microsoft.Network/publicIPAddresses#2022-01-01' = {
name: public_ip_gateway
location: location
sku: {
name: 'Basic'
tier: 'Regional'
}
properties: {
ipAddress: '40.161.130.50'
publicIPAddressVersion: 'IPv4'
publicIPAllocationMethod: 'Dynamic'
idleTimeoutInMinutes: 4
ipTags: []
}
}
resource virtual_network_resource 'Microsoft.Network/virtualNetworks#2022-01-01' = {
name: virtual_network_name
location: location
properties: {
addressSpace: {
addressPrefixes: [
'10.2.0.0/16'
]
}
subnets: [
{
name: gwSubnetName
properties: {
addressPrefix: '10.2.255.0/25'
delegations: []
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
type: 'Microsoft.Network/virtualNetworks/subnets'
}
{
name: p2s_subnet_name
properties: {
addressPrefix: '10.1.1.0/24'
serviceEndpoints: []
delegations: []
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
}
type: 'Microsoft.Network/virtualNetworks/subnets'
}
]
virtualNetworkPeerings: []
enableDdosProtection: false
}
}
resource p2s_vpn_name_resource 'Microsoft.Network/virtualNetworkGateways#2022-01-01' = {
name: p2s_vpn_name
location: location
properties: {
enablePrivateIpAddress: false
ipConfigurations: [
{
name: 'default'
properties: {
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: {
id: public_ip_gateway_resource.id
}
subnet: {
id: resourceId('Microsoft.Network/virtualNetworks/subnets', virtual_network_resource.name, gwSubnetName)
}
}
}
]
natRules: []
enableBgpRouteTranslationForNat: false
disableIPSecReplayProtection: false
sku: {
name: 'VpnGw1'
tier: 'VpnGw1'
}
gatewayType: 'Vpn'
vpnType: 'RouteBased'
enableBgp: false
activeActive: false
vpnClientConfiguration: {
vpnClientAddressPool: {
addressPrefixes: [
'119.x.x.0/24'
]
}
vpnClientProtocols: [
'OpenVPN'
]
vpnAuthenticationTypes: [
'Certificate'
]
vpnClientRootCertificates: [
{
name: 'Rahman'
properties: {
publicCertData: 'xxxxxxxxxxx=='
}
}
]
vpnClientRevokedCertificates: []
radiusServers: []
vpnClientIpsecPolicies: []
}
bgpSettings: {
asn: 65515
bgpPeeringAddress: '10.2.255.126'
peerWeight: 0
bgpPeeringAddresses: [
{
ipconfigurationId: resourceId('Microsoft.Network/virtualNetworkGateways/ipConfigurations', p2s_vpn_name, 'default')
customBgpIpAddresses: []
}
]
}
customRoutes: {
addressPrefixes: []
}
vpnGatewayGeneration: 'Generation1'
}
}
I am deploying schedules for the azure update management service through bicep. My code is as below:
param parSchedules array = [
{
name: 'mysched1'
monthlyOccurrencesDay: null
monthlyOccurrencesOccurence: null
DaysOfWeek: 'Wednesday'
StartTime: '${parBaseTimeForUpdateSchedules}T19:00:00'
tag: {
Update: [
'tag1'
]
}
}
{
name: 'mysched2'
monthlyOccurrencesDay: 'Wednesday'
monthlyOccurrencesOccurence: 1
DaysOfWeek: 'Wednesday'
StartTime: '${parBaseTimeForUpdateSchedules}T07:00:00'
tag: {
Update: [
'tag2'
]
}
}
]
resource resUpdateschedule 'Microsoft.Automation/automationAccounts/softwareUpdateConfigurations#2019-06-01' = [for schedule in parSchedules: {
name: schedule.name
parent: resAutomationAccount
properties: {
scheduleInfo: {
advancedSchedule: {
monthlyOccurrences: [
{
day: schedule.monthlyOccurrencesDay
occurrence: schedule.monthlyOccurrencesOccurence
}
]
weekDays: [
schedule.DaysOfWeek
]
}
description: ''
frequency: 'Week'
interval: 1
isEnabled: true
startTime: schedule.StartTime
timeZone: 'UTC'
}
updateConfiguration: {
duration: 'PT2H'
operatingSystem: 'Windows'
targets: {
azureQueries: [
{
locations: [
parLocation
]
scope: [
subscription().id
]
tagSettings: {
tags: schedule.tag
}
}
]
}
windows: {
includedUpdateClassifications: 'Critical, Security'
rebootSetting: 'IfRequired'
}
}
}
}]
I am getting error with this because null value is not accepted for monthlyOccurrencesDay and monthlyOccurrencesOccurence. So what I want is to be able to use the same list containing different types of schedules (with and without monthlyOccurrencesOccurence) by looping the same resource. Like if the values of monthlyOccurrencesOccurence is null, it shouldn't take into consideration this property. Is that possible at all?
You should be able to conditionally set the monthly occurence like that:
resource resUpdateschedule 'Microsoft.Automation/automationAccounts/softwareUpdateConfigurations#2019-06-01' = [for schedule in parSchedules: {
name: schedule.name
...
properties: {
scheduleInfo: {
advancedSchedule: {
monthlyOccurrences: schedule.monthlyOccurrencesOccurence != null ? [
{
day: schedule.monthlyOccurrencesDay
occurrence: schedule.monthlyOccurrencesOccurence
}
] : []
...
}
...
}
...
}
}]
I created an Azure Function App by Bicep and tried to get the signalr_extension's value to use in the "upstream" configuration section of a serverless Azure SignalR Service. This is how I try to obtain this value in Bicep:
var signalRKey = listKeys(resourceId('Microsoft.Web/sites/host', funcAppName, 'default'), '2022-03-01').systemkeys.signalr_extension
This is how I configure the signalR service's upstream:
urlTemplate: 'https://${funcAppName}.azurewebsites.net/runtime/webhooks/signalr?code=${signalRKey}'
Running the bicep templates leads to the failure below:
Encountered an error (ServiceUnavailable) from host runtime.
When I remove the {signalRKey} from urlTemplate and replace it with a fictitious hard-coded value, the signalR is provisioned successfully.
The other thing that I noticed was that the singalr_extension key value was not populated after the function app was provisioned.
What am I missing in this exercise?
This feature is not available and feasible in App Service Plans. The signalr_extension must be populated manually after deploying the function app and signalR.
The signalr_extension is only created once you've deployed your function app with a SignalRTrigger function.
You can generate this key upfront if you're deploying the Function App and signalR service at the same time:
param functionAppName string
// Create the function app key for signalR
resource signalRKey 'Microsoft.Web/sites/host/systemkeys#2021-03-01' = {
name: '${functionAppName}/default/signalr_extension'
properties: {
name: 'signalr_extension'
}
}
The ARM API to generate function keys is just pointing to the function app API so it could take some time before it become available (see issue on github).
I managed to get this working consistently by deploying the systemkey and signalr using module.
Also for function app running on linux, the AzureWebJobsStorage setting is mandatory.
functionapp-systemkey.bicep module:
param functionAppName string
param keyName string
resource signalRKey 'Microsoft.Web/sites/host/systemkeys#2021-03-01' = {
name: '${functionAppName}/default/${keyName}'
properties: {
name: keyName
}
}
signalr.bicep module:
param location string = resourceGroup().location
param signalRName string
param functionAppName string
resource signalR 'Microsoft.SignalRService/signalR#2022-02-01' = {
name: signalRName
location: location
sku: {
name: 'Free_F1'
tier: 'Free'
capacity: 1
}
properties: {
features: [
{
flag: 'ServiceMode'
value: 'Serverless'
}
{
flag: 'EnableConnectivityLogs'
value: 'true'
}
]
cors: {
allowedOrigins: [
'*'
]
}
tls: {
clientCertEnabled: false
}
upstream: {
templates: [
{
hubPattern: '*'
eventPattern: '*'
categoryPattern: '*'
auth: {
type: 'None'
}
urlTemplate: 'https://${signalRName}.azurewebsites.net/runtime/webhooks/signalr?code=${listKeys(resourceId('Microsoft.Web/sites/host', functionAppName, 'default'), '2022-03-01').systemkeys.signalr_extension}'
}
]
}
}
}
main.bicep:
param location string = resourceGroup().location
param storageName string
param appServicePlanName string
param functionAppName string
param signalRName string
resource storage 'Microsoft.Storage/storageAccounts#2021-09-01' = {
name: storageName
location: location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
properties: {
supportsHttpsTrafficOnly: true
minimumTlsVersion: 'TLS1_2'
}
}
resource appServicePlan 'Microsoft.Web/serverfarms#2021-03-01' = {
name: appServicePlanName
location: location
sku: {
name: 'Y1'
tier: 'Dynamic'
size: 'Y1'
family: 'Y'
capacity: 0
}
kind: 'functionapp'
properties: {
perSiteScaling: false
elasticScaleEnabled: false
maximumElasticWorkerCount: 1
isSpot: false
reserved: true
isXenon: false
targetWorkerCount: 0
targetWorkerSizeId: 0
zoneRedundant: false
}
}
resource functionApp 'Microsoft.Web/sites#2021-03-01' = {
name: functionAppName
location: location
kind: 'functionapp,linux'
properties: {
serverFarmId: appServicePlan.id
clientAffinityEnabled: false
clientCertEnabled: false
httpsOnly: true
siteConfig:{
linuxFxVersion: 'DOTNET|6.0'
use32BitWorkerProcess: true
ftpsState: 'FtpsOnly'
cors: {
allowedOrigins: [
'https://portal.azure.com'
]
supportCredentials: false
}
minTlsVersion: '1.2'
appSettings: [
{
name: 'FUNCTIONS_EXTENSION_VERSION'
value: '~4'
}
{
name: 'FUNCTIONS_WORKER_RUNTIME'
value: 'dotnet'
}
{
name: 'AzureWebJobsStorage'
value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};AccountKey=${listKeys(storage.id, '2019-06-01').keys[0].value};EndpointSuffix=core.windows.net;'
}
]
}
}
}
var signalrKeyName = 'signalr_extension'
module signalrKey 'modules/functionapp-systemkey.bicep' = {
name: '${functionAppName}-systemkey-${signalrKeyName}'
params: {
functionAppName: functionApp.name
keyName: signalrKeyName
}
}
module signalr 'modules/signalr.bicep' = {
name: signalRName
params: {
location: location
functionAppName: functionApp.name
signalRName: signalRName
}
dependsOn:[
signalrKey
]
}
I have a Bicep template to create an Azure SignalR Service per the following script. How can I obtain the upstream's code value within the bicep template and populate the urlTemplate's code value based on it? (the keyword TBD exhibits the exact spot in the following code.)
targetScope = 'resourceGroup'
param location string = resourceGroup().location
param signalRName string
resource signalR 'Microsoft.SignalRService/signalR#2022-02-01' = {
name: signalRName
location: location
kind: 'SignalR'
sku: {
name: 'Free_F1'
tier: 'Free'
capacity: 1
}
properties: {
features: [
{
flag: 'ServiceMode'
value: 'Serverless'
}
{
flag: 'EnableConnectivityLogs'
value: 'true'
}
{
flag: 'EnableMessagingLogs'
value: 'true'
}
{
flag: 'EnableLiveTrace'
value: 'true'
}
]
liveTraceConfiguration: {
enabled: 'true'
categories: [
{
name: 'ConnectivityLogs'
enabled: 'true'
}
{
name: 'MessagingLogs'
enabled: 'true'
}
{
name: 'HttpRequestLogs'
enabled: 'true'
}
]
}
cors: {
allowedOrigins: [
'*'
]
}
upstream: {
templates: [
{
hubPattern: '*'
eventPattern: '*'
categoryPattern: '*'
auth: {
type: 'None'
}
urlTemplate: 'https://${signalRName}.azurewebsites.net/runtime/webhooks/signalr?code=TBD'
}
]
}
}
}
I'm assuming that you are using a function app that has the same name as your signalR service.
Looking at the documentation:
The url always looks like that <Function_App_URL>/runtime/webhooks/signalr?code=<API_KEY>
the API_KEY is a function app systemkey called signalr_extension.
So you should be able to retrieve the key and use it like that:
var signalRKey = listKeys(resourceId('Microsoft.Web/sites/host', signalRName, 'default'), '2022-03-01').systemkeys.signalr_extension
resource signalR 'Microsoft.SignalRService/signalR#2022-02-01' = {
name: signalRName
...
properties: {
...
upstream: {
templates: [
{
...
urlTemplate: 'https://${signalRName}.azurewebsites.net/runtime/webhooks/signalr?code=${signalRKey}'
}
]
}
}
}