ARM Template resources tags with condition - tags

I've created my ARM templates to publish azure resources on my dev environment.
Now I need to add a condition in template.json for resource tags, that it will create tags only if subscription().displayName is 'Dev'.
Other than 'Dev', it should not create any tags from that template.json under resources.
"resources": [
{
"type": "Microsoft.Web/connections",
"apiVersion": "2016-06-01",
"name": "[parameters('connections_office365_name')]",
"location": "[resourceGroup().location]",
"properties": {
"displayName": "manish.jain#gmail.com",
"customParameterValues": {},
"api": {
"id": "[concat('/subscriptions/',subscription().subscriptionId,'/providers/Microsoft.Web/locations/',resourceGroup().location,'/managedApis/office365')]"
}
},
"tags": {
"Creator": "Manish Jain",
"Environment": "Dev",
"Date": "08/31/2019"
}
}

The following ARM template demonstrates how to make the whole tags dictionary conditional:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string"
},
"storageAccountName": {
"type": "string"
},
"accountType": {
"type": "string"
},
"kind": {
"type": "string"
},
"accessTier": {
"type": "string"
},
"supportsHttpsTrafficOnly": {
"type": "bool"
},
"createTag": {
"type": "bool"
}
},
"variables": {},
"resources": [
{
"name": "[parameters('storageAccountName')]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"location": "[parameters('location')]",
"properties": {
"accessTier": "[parameters('accessTier')]",
"supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]"
},
"dependsOn": [],
"sku": {
"name": "[parameters('accountType')]"
},
"kind": "[parameters('kind')]",
"tags": "[if(parameters('createTag'),json('{\"tag1\": \"value1\",\"tag2\":\"value2\"}'), json('{}'))]"
}
],
"outputs": {}
}
To apply this to your particular scenario, instead of [if(parameters('createTag')... it would be [if(equals(subscription().displayName,'Dev')...

The conditional tags using an if block works; however, is it the best practice?
If you are creating tags conditionally based on environment, why not create the tag values as parameters and pass them into your ARM template.
That would avoid the whole conditional piece and instead the specific tag values defined in the parameters template will be inserted into the ARM template.
The downside to this approach would be that the tag values would be required for each environment as opposed to just your lower environment. However; your consistency would improve as each environment can all have the same tags and just different values.

Related

listKeys problems in ARM template using inside variables or parameters

I'm setting up an ARM template for my Azure Functions. I have functions_app.json which will function as the "main" template and will be used for other release pipelines as well.
Then there will be project specific parameter templates, like:
counter_function_arm.parameters.test.json
counter_function_arm.parameters.acceptance.json
weather_function_arm.parameters.test.json
etc.
But I'm stuck at this part where it creates the actual Function resource inside the functions_app.json template:
"resources": [
{
"apiVersion": "2018-11-01",
"name": "[variables('resourceName')]",
"type": "Microsoft.Web/sites",
"properties": {
"name": "[variables('resourceName')]",
"siteConfig": {
"appSettings": [
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~4"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('resourceName'))]"
}
]
}
}
}
I left some things out for brevity. The import part is the appSettings section.
My initial idea was to put that array in variables. Those will be the "default" settings. Then from my counter_function_arm.parameters.test.json file I would add another array specific to that application and then union those two together so all AppSettings are configured.
Something like this:
counter_function_arm.parameters.test.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"customAppSettings":{
"value": [
{
"name": "CustomProperty",
"value": "some value"
}
]
}
}
}
functions_app.json
"variables": {
"defaultAppSettings": [
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~4"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower(variables('resourceName'))]"
}
]
},
"resources": [
{
"apiVersion": "2018-11-01",
"name": "[variables('resourceName')]",
"type": "Microsoft.Web/sites",
"properties": {
"name": "[variables('resourceName')]",
"siteConfig": {
"appSettings": "[union(variables('defaultAppSettings'), parameters('customAppSettings'))]"
}
}
}
So in this case I union the variable variables('defaultAppSettings') and parameters('customAppSettings') together.
But, the problem is that I can't use listKeys in the variables section. I also can't move this to the parameters section and set it as defaultValue because listKeys is also not allowed there.
Adding a hard coded array to union also doesn't work:
"appSettings": "[union([1,2,3], parameters('customAppSettings'))]"
So I am out of ideas.
Is there a way to do this?
I've found a way around this, it is not pretty but it works... Basically I have an array of purely static app settings (in your case FUNCTIONS_EXTENSION_VERSION, FUNCTIONS_WORKER_RUNTIME, WEBSITE_CONTENTSHARE) that you can create in variables, an array of customAppSettings from parameters, and another array that I have to write as raw JSON.
Here's an example :
"resources": [
{
"apiVersion": "2018-11-01",
"name": "[variables('resourceName')]",
"type": "Microsoft.Web/sites",
"properties": {
"name": "[variables('resourceName')]",
"siteConfig": {
"appSettings": "[union(variables('staticAppSettings'), parameters('customAppSettings'), json(concat('[{\"name\": \"AzureWebJobsStorage\",\"value\": \"', concat('DefaultEndpointsProtocol=https;AccountName=', parameters('azureFunctionParameters').functionStorageName,';AccountKey=', listKeys(resourceId(parameters('azureFunctionParameters').mainStorageResourceGroup, 'Microsoft.Storage/storageAccounts', parameters('azureFunctionParameters').functionStorageName), '2021-08-01').keys[1].value, ';EndpointSuffix=core.windows.net'),'\"}]')))]"
}
}
}
]
Sadly this is the best I could come up with, it is very prone to syntax error but if you're using multi-line strings you could format it in a way to avoid errors (but be careful if you're using Azure Devops it is not compatible).
EDIT :
There is another way to accomplish this that may be more suitable for you, which is to use a linkedTemplate :
Main template
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "yourResourceDeployment",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('blobBaseUrl'), '/', parameters('resourceGroupName'), '/azurefunctions/baseazurefunction.json')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"azureFunctionParameters": {
"value": "[parameters('baseAzureFunctionParameters')]"
},
"appSettings": {
"value" : "[union(variables('staticAppSettings'), parameters('customAppSettings'))]"
},
"someMoreAppSettings": {
"value" : [
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('xxxx-xxxx','MyResourceGroup','Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2019-06-01').keys[0].value,';EndpointSuffix=','core.windows.net')]"
}
]
}
}
}
}
]
In the baseazurefunction.json linkedTemplate you can just use
{
"apiVersion": "2018-11-01",
"name": "[variables('resourceName')]",
"type": "Microsoft.Web/sites",
"properties": {
"name": "[variables('resourceName')]",
"siteConfig": {
"appSettings": "[union(parameters('appSettings'), parameters('moreAppSettings'))]"
}
}
}
If you have a security concern over sending connection strings as parameters to other templates, you could wrap your appsettings in a secureobject with a property called array which would contain all your settings and then use it like this instead
"appSettings": {
"type": "secureobject",
"metadata": {
"description": "Secure object with an array property which contains the appsettings"
}
},
"moreAppSettings": {
"type": "secureobject",
"metadata": {
"description": "Secure object with an array property which contains more appsettings"
}
}
.
.
.
"appSettings": "[union(parameters('appSettings').array, parameters('moreAppSettings').array)]"

How to reference already existing Azure Portal created storage accounts in an ARM template

I want to create a function app with ARM template such that the ARM template references already existing storage accounts (inputstgdev and outputstgdev) which I have already parameterized. I would like the ARM template to use the inputstgdev storage account as its attached storage account such that it does not have to create a new storage account. The source control of the function app is referenced to a Gitrepo which I have also parameterized in the ARM template. Each time I run the ARM template I get the following error message
##[error]Deployment template validation failed: 'The resource '/subscriptions/bea8ac84-24a4-4e53-9198-e3b0107547d4/resourceGroups/dev-rgp/providers/Microsoft.Web/sites/functionapp/sourcecontrols/web' at line '1' and column '3069' doesn't depend on parent resource '/subscriptions/bea8ac84-24a4-4e53-9198-e3b0107547d4/resourceGroups/dev-rgp/providers/Microsoft.Web/sites/functionapp'. Please add dependency explicitly using the 'dependsOn' syntax. Please see aka.ms/arm-template/#resources for
Any suggestions what the issue might be or possible solutions.
I look forward to your response
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"InputstorageAccount": {
"defaultValue": "inputstgdev",
"type": "String"
},
"GitrepoBranch": {
"type": "string",
"defaultValue": "master",
"metadata": {
"description": "Name of the branch to use when deploying (Default = master)."
}
},
"GitrepoURL": {
"type": "string",
"defaultValue": "https://github.com/FBoucher/AzUnzipEverything.git",
"metadata": {
"description": "URL to repo (Default = master)."
}
},
"InputcontainerName": {
"type": "string",
"defaultValue": "inputcontainer",
"metadata": {
"description": "Specifies the name of the blob container."
}
},
"OutputstorageAccount": {
"defaultValue": "outputstgdev",
"type": "String"
},
"OutputcontainerName": {
"type": "string",
"defaultValue": "outputcontainer",
"metadata": {
"description": "Specifies the name of the blob container."
}
}
},
"variables": {},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('InputstorageAccount'), '/default/', parameters('InputcontainerName'))]",
"properties": {
"publicAccess": "None"
}
},
{
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
"apiVersion": "2019-06-01",
"name": "[concat(parameters('OutputstorageAccount'), '/default/', parameters('OutputcontainerName'))]",
"properties": {
"publicAccess": "None"
}
},
{
"name": "serviceplan",
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2018-02-01",
"location": "[resourceGroup().location]",
"sku": {
"name": "F1",
"capacity": 1
},
"tags": {
"displayName": "serviceplan"
},
"properties": {
"name": "serviceplan"
}
},
{
"name": "functionapp",
"type": "Microsoft.Web/sites",
"apiVersion": "2018-11-01",
"location": "[resourceGroup().location]",
"kind": "functionapp",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', 'serviceplan')]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('InputstorageAccount'))]"
],
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', 'serviceplan')]",
"siteConfig": {
"appSettings": [
{
"name": "AzureWebJobsDashboard",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('InputstorageAccount'), ';AccountKey=', listKeys(parameters('InputcontainerName'),'2015-05-01-preview').key1)]"
},
{
"name": "WEBSITE_CONTENTSHARE",
"value": "[toLower('functionapp')]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~2"
},
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('microsoft.insights/components/', 'applicationInsightsName'), '2015-05-01').InstrumentationKey]"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
}
]
}
},
"resources":[
{
"apiVersion": "2015-08-01",
"name": "web",
"type": "sourcecontrols",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', parameters('InputstorageAccount'))]"
],
"properties": {
"RepoUrl": "[parameters('GitrepoURL')]",
"branch": "[parameters('GitrepoBranch')]",
"publishRunbook": true,
"IsManualIntegration": true
}
}
]
}
]
}
You encountered this error message due to the wrong dependency.
You should use "[resourceId('Microsoft.Web/sites/', 'functionapp')]" instead of "[resourceId('Microsoft.Web/sites/', parameters('InputstorageAccount'))]".
And you should delete the storage dependency.
"[resourceId('Microsoft.Storage/storageAccounts', parameters('InputstorageAccount'))]"
By the way, as you already have a storage account, you just need to paste your connection string in the value of AzureWebJobsStorage and AzureWebJobsDashboard.
Just like
{
"name": "AzureWebJobsDashboard",
"value": "{connectionstring}"
}

Input for create or update policy is not in proper format (.json Template in PowerShell-Script)

I'm trying to deploy a resource group from a powershell script. The script gets the parameters etc. from a .json template.
For another resource group it worked fine (I just had to insert the "adminPassword" parameter), but now I have another resoruce group, which I can't redeploy from this script. First I thougt I just have to add the parameter before, but this template has a different structure, etc. So that means that I cannot find the place to insert the parameter.
But this isn't the problem. When I run the script, I'm getting the following error:
New-AzureRmResourceGroupDeployment : 08:35:01 - Resource Microsoft.RecoveryServices/vaults/backupPolicies 'alp-prd-core-rsvault1/DefaultPolicy' failed with message '{
"error": {
"code": "BMSUserErrorInvalidPolicyInput",
"message": "Input for create or update policy is not in proper format\r\nPlease check format of parameters like schedule time, schedule days, retention time and retention days ",
"target": null,
"details": null,
"innerError": null
(Sorry for bad format)
I looked in the template and one of the parameter the powershell doesn't like is the following:
"backupPolicies_DefaultPolicy_name": {
"type": "String",
"defaultValue": "DefaultPolicy"
},
It's like the documentation from Microsoft (https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-deploy)
So for that I don't know why this doesn't work, for the other Resource Group with their template it worked.
I hope you understand my issue.
Thanks in advance!
P.S. Template: {
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"virtualNetworks_alp_prd_core_vnet1_name": {
"defaultValue": "alp-prd-core-vnet1",
"type": "String"
},
"vaults_alp_prd_core_rsvault1_name": {
"defaultValue": "alp-prd-core-rsvault1",
"type": "String"
},
"subnets_internal_name": {
"defaultValue": "internal",
"type": "String"
},
"backupPolicies_DefaultPolicy_name": {
"defaultValue": "DefaultPolicy",
"type": "String"
},
"backupPolicies_HourlyLogBackup_name": {
"defaultValue": "HourlyLogBackup",
"type": "String"
},
"backupPolicies_%name%_Backup_Policy_name": {
"defaultValue": "%name%-Backup-Policy",
"type": "String"
},
"replicationAlertSettings_defaultAlertSetting_name": {
"defaultValue": "defaultAlertSetting",
"type": "String"
},
"virtualNetworkPeerings_alp_prd_core_vnet1_Net_Sync_name": {
"defaultValue": "alp-prd-core-vnet1-Net-Sync",
"type": "String"
},
"virtualNetworks_alp_prd_core_vnet1_id": {
"defaultValue": "/subscriptions/%subsciptionID%/resourceGroups/NemetschekgroupAD/providers/Microsoft.Network/virtualNetworks/Net-Sync",
"type": "String"
},
"virtualNetworkPeerings_alp_prd_core_vnet1_Net_Sync_id": {
"defaultValue": "/subscriptions/%subsciptionID%/resourceGroups/NemetschekgroupAD/providers/Microsoft.Network/virtualNetworks/Net-Sync",
"type": "String"
}
},
"variables": {},
"resources": [
{
"comments": "Generalized from resource: '/subscriptions/%subsciptionID%/resourceGroups/alp-prd-core-rg/providers/Microsoft.Network/virtualNetworks/alp-prd-core-vnet1'.",
"type": "Microsoft.Network/virtualNetworks",
"name": "[parameters('virtualNetworks_alp_prd_core_vnet1_name')]",
"apiVersion": "2018-02-01",
"location": "westeurope",
"scale": null,
"properties": {
"provisioningState": "Succeeded",
"resourceGuid": "940c1d33-bbf4-4b01-a331-8096e8066a0a",
"addressSpace": {
"addressPrefixes": [
"10.11.0.112/28"
]
},
"subnets": [
{
"name": "internal",
"etag": "W/\"b5fce13f-36b0-4d55-aa19-755a78b696f2\"",
"properties": {
"provisioningState": "Succeeded",
"addressPrefix": "10.11.0.112/28"
}
}
],
"virtualNetworkPeerings": [
{
"name": "[concat(parameters('virtualNetworks_alp_prd_core_vnet1_name'),'-Net-Sync')]",
"etag": "W/\"b5fce13f-36b0-4d55-aa19-755a78b696f2\"",
"properties": {
"provisioningState": "Succeeded",
"peeringState": "Connected",
"remoteVirtualNetwork": {
"id": "[parameters('virtualNetworks_alp_prd_core_vnet1_id')]"
},
"allowVirtualNetworkAccess": true,
"allowForwardedTraffic": false,
"allowGatewayTransit": false,
"useRemoteGateways": true,
"remoteAddressSpace": {
"addressPrefixes": [
"10.11.0.0/28",
"10.11.0.16/28"
]
}
}
}
],
"enableDdosProtection": false,
"enableVmProtection": false
},
"dependsOn": []
},
{
"comments": "Generalized from resource: '/subscriptions/%subsciptionID%/resourceGroups/alp-prd-core-rg/providers/Microsoft.RecoveryServices/vaults/alp-prd-core-rsvault1'.",
"type": "Microsoft.RecoveryServices/vaults",
"sku": {
"name": "RS0",
"tier": "Standard"
},
"name": "[parameters('vaults_alp_prd_core_rsvault1_name')]",
"apiVersion": "2018-01-10",
"location": "westeurope",
"scale": null,
"properties": {},
"dependsOn": []
},
{
"comments": "Generalized from resource: '/subscriptions/%subsciptionID%/resourceGroups/alp-prd-core-rg/providers/Microsoft.Network/virtualNetworks/alp-prd-core-vnet1/subnets/internal'.",
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[concat(parameters('virtualNetworks_alp_prd_core_vnet1_name'), '/', parameters('subnets_internal_name'))]",
"apiVersion": "2018-02-01",
"scale": null,
"properties": {
"provisioningState": "Succeeded",
"addressPrefix": "10.11.0.112/28"
},
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworks_alp_prd_core_vnet1_name'))]"
]
},
{
"comments": "Generalized from resource: '/subscriptions/%subsciptionID%/resourceGroups/alp-prd-core-rg/providers/Microsoft.Network/virtualNetworks/alp-prd-core-vnet1/virtualNetworkPeerings/alp-prd-core-vnet1-Net-Sync'.",
"type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings",
"name": "[concat(parameters('virtualNetworks_alp_prd_core_vnet1_name'), '/', parameters('virtualNetworkPeerings_alp_prd_core_vnet1_Net_Sync_name'))]",
"apiVersion": "2018-02-01",
"scale": null,
"properties": {
"provisioningState": "Succeeded",
"peeringState": "Connected",
"remoteVirtualNetwork": {
"id": "[parameters('virtualNetworkPeerings_alp_prd_core_vnet1_Net_Sync_id')]"
},
"allowVirtualNetworkAccess": true,
"allowForwardedTraffic": false,
"allowGatewayTransit": false,
"useRemoteGateways": true,
"remoteAddressSpace": {
"addressPrefixes": [
"10.11.0.0/28",
"10.11.0.16/28"
]
}
},
"dependsOn": [
"[resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworks_alp_prd_core_vnet1_name'))]"
]
},
{
"comments": "Generalized from resource: '/subscriptions/%subsciptionID%/resourcegroups/alp-prd-core-rg/providers/Microsoft.RecoveryServices/vaults/alp-prd-core-rsvault1/backupPolicies/%name%-Backup-Policy'.",
"type": "Microsoft.RecoveryServices/vaults/backupPolicies",
"name": "[concat(parameters('vaults_alp_prd_core_rsvault1_name'), '/', parameters('backupPolicies_%name%_Backup_Policy_name'))]",
"apiVersion": "2016-12-01",
"scale": null,
"properties": {
"backupManagementType": "AzureIaasVM",
"protectedItemsCount": 0
},
"dependsOn": [
"[resourceId('Microsoft.RecoveryServices/vaults', parameters('vaults_alp_prd_core_rsvault1_name'))]"
]
},
{
"comments": "Generalized from resource: '/subscriptions/%subsciptionID%/resourcegroups/alp-prd-core-rg/providers/Microsoft.RecoveryServices/vaults/alp-prd-core-rsvault1/backupPolicies/HourlyLogBackup'.",
"type": "Microsoft.RecoveryServices/vaults/backupPolicies",
"name": "[concat(parameters('vaults_alp_prd_core_rsvault1_name'), '/', parameters('backupPolicies_HourlyLogBackup_name'))]",
"apiVersion": "2016-12-01",
"scale": null,
"properties": {
"backupManagementType": "AzureWorkload",
"protectedItemsCount": 0
},
"dependsOn": [
"[resourceId('Microsoft.RecoveryServices/vaults', parameters('vaults_alp_prd_core_rsvault1_name'))]"
]
},
{
"comments": "Generalized from resource: '/subscriptions/%subsciptionID%/resourcegroups/alp-prd-core-rg/providers/Microsoft.RecoveryServices/vaults/alp-prd-core-rsvault1/backupPolicies/DefaultPolicy'.",
"type": "Microsoft.RecoveryServices/vaults/backupPolicies",
"name": "[concat(parameters('vaults_alp_prd_core_rsvault1_name'), '/', parameters('backupPolicies_DefaultPolicy_name'))]",
"apiVersion": "2016-12-01",
"scale": null,
"properties": {
"backupManagementType": "AzureIaasVM",
"protectedItemsCount": 0
},
"dependsOn": [
"[resourceId('Microsoft.RecoveryServices/vaults', parameters('vaults_alp_prd_core_rsvault1_name'))]"
]
},
{
"comments": "Generalized from resource: '/Subscriptions/%subsciptionID%/resourceGroups/alp-prd-core-rg/providers/Microsoft.RecoveryServices/vaults/alp-prd-core-rsvault1/replicationAlertSettings/defaultAlertSetting'.",
"type": "Microsoft.RecoveryServices/vaults/replicationAlertSettings",
"name": "[concat(parameters('vaults_alp_prd_core_rsvault1_name'), '/', parameters('replicationAlertSettings_defaultAlertSetting_name'))]",
"apiVersion": "2018-01-10",
"scale": null,
"properties": {
"sendToOwners": "DoNotSend",
"customEmailAddresses": [],
"locale": ""
},
"dependsOn": [
"[resourceId('Microsoft.RecoveryServices/vaults', parameters('vaults_alp_prd_core_rsvault1_name'))]"
]
}
]
}
To me it seems like your template is missing the actual schedule, required for a successfuly backup policy deployment. I realize that you have exported the template from an existing deployment, but for some reason the policy itself is included, without the actual schedule (meaning when to back up virtual machines). Not sure why it is not included in the exported template.
I suggest you take an existing template - for example this https://github.com/Azure/azure-quickstart-templates/blob/master/101-recovery-services-daily-backup-policy-create/azuredeploy.json as a baseline and edit your existing template to include all the necessary properties. Use that template as a reference, and you should end up with a working template.

Azure ARM Template and PowerShell Module

I have a module published on PowerShell Gallery and I want to deploy this module with Azure ARM Template. And I did not find how!
Here is my template:
"resources": [
{
"name": "[variables('automationAccountName')]",
"type": "Microsoft.Automation/automationAccounts",
"apiVersion": "2015-10-31",
"location": "[parameters('AutomationLocation')]",
"tags": {
"displayName": "Compte Automation"
},
"properties": {
"sku": {
"name": "Basic",
"family": "B"
}
},
"resources": [
{
"name": "[variables('powerShellGalleryModuleName')]",
"type": "modules",
"apiVersion": "2015-10-31",
"location": "[parameters('AutomationLocation')]",
"properties": {
"isGlobal": false,
"sizeInBytes": 0,
"contentLink": {
"uri": "[variables('powerShellGalleryModule')]"
}
}
}
]
}
]
What should be provided for the variable powerShellGalleryModule?
I found a way to do via the PowerShellGallery
This way :
{
"name": "[variables('powerShellGalleryModule')]",
"type": "modules",
"apiVersion": "2015-10-31",
"location": "[parameters('AutomationLocation')]",
"properties": {
"isGlobal": false,
"sizeInBytes": 0,
"contentLink": {
"uri": "[concat('https://www.powershellgallery.com/api/v2/package/', variables('powerShellGalleryModule'))]"
}
},
"dependsOn": [
"[resourceId('Microsoft.Automation/automationAccounts', variables('automationAccountName'))]"
]
We can import these integration modules into Azure Automation using any of the following methods:
1.Using the New-AzureRmAutomationModule cmdlet in the AzureRm.Automation module.
2.Using the Azure portal and navigating to the Assets within automation account.
3.Using Azure Resource Manager (ARM) template
We can use ARM template to deploy our custom integration modules. Here is an example template:
"$schema": "http://schemas.microsoft.org/azure/deploymentTemplate?api-version=2015-01-01-preview#",
"contentVersion": "1.0",
"parameters": {
"automationAccountType": {
"type": "string",
"allowedValues": [
"New",
"Existing"
]
},
"automationAccountName": {
"type": "string"
},
"moduleName": {
"type": "string"
},
"moduleUri":{
"type": "string"
}
},
"variables": {
"templatelink": "[concat('https://devopsgallerystorage.blob.core.windows.net/azureautomationpackages/templates%5Corigtemplates%5C', parameters('automationAccountType'), 'AccountTemplate.json')]"
},
"resources": [
{
"apiVersion": "2015-01-01",
"name": "nestedTemplate",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "incremental",
"templateLink": {
"uri": "[variables('templatelink')]",
"contentVersion": "1.0"
},
"parameters": {
"accountName": {
"value": "[parameters('automationAccountName')]"
},
"accountLocation": {
"value": "[resourceGroup().Location]"
},
"moduleName": {
"value": "[parameters('moduleName')]"
},
"moduleUri": {
"value": "[parameters('moduleUri')]"
}
}
}
}
]
}
More information about deploy custom Azure Automation Integration module using ARM template, please refer to this link writed by Ravikanth.

Authoratative Source Dcoumentation for Azure ARM Template Schema

I am looking for the official documentation for Azure Desired State Configuration JSON schemas. Documentation and examples I find online go back quite a while and I feel the schemas I am using are not current. I am currently seeking the most current schema and a description of the fields for Microsoft.Powershell.DSC. This is the schema Visual Studio provides but I would like to have a complete understanding of each field and values they expect.
{
"name": "Microsoft.Powershell.DSC",
"type": "extensions",
"location": "[parameters('location')]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines', parameters('vm-SP1-Name'))]"
],
"tags": {
"displayName": "test"
},
"properties": {
"publisher": "Microsoft.Powershell",
"type": "DSC",
"typeHandlerVersion": "2.9",
"autoUpgradeMinorVersion": true,
"forceUpdateTag": "[parameters('testUpdateTagVersion')]",
"settings": {
"configuration": {
"url": "[concat(parameters('_artifactsLocation'), '/', variables('testArchiveFolder'), '/', variables('testArchiveFileName'))]",
"script": "test.ps1",
"function": "Main"
},
"configurationArguments": {
"nodeName": "[parameters('vm-SP1-Name')]"
}
},
"protectedSettings": {
"configurationUrlSasToken": "[parameters('_artifactsLocationSasToken')]"
}
}
}
The official schema definition for the ARM PowerShell Desired State Configuration (DSC) JSON Schema can be found at the link below:
Schema Json
"dscExtension": {
"type": "object",
"properties": {
"publisher": {
"enum": ["Microsoft.Powershell"]
},
"type": {
"enum": ["DSC"]
},
"typeHandlerVersion": {
"type": "string",
"minLength": 1
},
"autoUpgradeMinorVersion": {
"type": "boolean"
},
"settings": {
"type": "object",
"properties": {
"modulesUrl": {
"type": "string"
},
"configurationFunction": {
"type": "string"
},
"properties": {
"type": "string"
},
"wmfVersion": {
"type": "string"
},
"privacy": {
"type": "object",
"properties": {
"dataCollection": {
"type": "string"
}
}
}
},
"required": ["modulesUrl", "configurationFunction"]
},
"protectedSettings": {
"type": "object",
"properties": {
"dataBlobUri": {
"type": "string"
}
}
}
},
"required": ["publisher", "type", "typeHandlerVersion", "autoUpgradeMinorVersion", "settings", "protectedSettings"]
},
The schema was documented in this blog. Feel free to ping me on the PowerShell slack (preferred) or twitter if you have any questions, #TravisPlunk. If I don't know, I can direct them to the right place.