I use the ARM template deployment task in my release pipeline. The task has a parameter called Location.
In my parameters.json file, I also have a parameter called Location. How could I change this file so that it reads the value set on the task itself ?
Currently the value is read from a variable group's variable coming from azure keyvault. But I think it's overkill to have this location parameter coming from the vault.
Based on my test, I notice that the value in xxx.parameters.json couldn't read the value of the variable in pipeline.
For example:
I set the variable(test : abc) in Pipeline variables. Then I use it in the xxx.parameters.json file.
When the Resource group creates, the vaiable doesn't be read in the resource group.
The parameters.json sample:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"adminUsername": {
"value": "test"
},
"location": {
"value": "$(test)"
}
}
}
From the result, it seems that the location value couldn't be automatic used in the json file.
You may need to use the tokenizer task to manually override the specific value in the json file. Then the value could be used in the resource group.
Or you could directly use the Override template parameters in the ARM Template task.
Hope this could help.
Location*:
For Resource Group deployment scope: Location for deploying the resource group. If the resource group already exists in the subscription, then this value will be ignored.
For other deployment scopes: Location for storing the deployment metadata.
https://github.com/microsoft/azure-pipelines-tasks/tree/master/Tasks/AzureResourceManagerTemplateDeploymentV3
Given this information, you can set the location of the resource group via the task, and use this for all of your resources as well. If you want your resources to be in a different location than your resource group, you will not be able to leverage the task parameter.
This is how it looks like in ARM:
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/resource-location?tabs=azure-powershell#use-location-parameter
Related
I am trying to deploy my logic app to multiple environments using CI/CD pipeline. I am getting an error -The client 'guid' with object id ''guid' ' has permission to perform action 'Microsoft.Logic/workflows/write' on scope 'Test Resource group'; however, it does not have permission to perform action 'Microsoft.Logic/integrationAccounts/join/action' on the linked scope(s) 'Development Resource group integration account' or the linked scope(s) are invalid.
Creating another integration account for test resource group doesnt come under free tier. Is there a way to share integration account across multiple resource groups
Not sure what the permissions issue is but you might need to give more information around this.
But try the below first in your pipeline. Works for us with 3 different resource groups and two integration accounts
"parameters": {
"IntegrationAccountName": {
"type": "string",
"minLength": 1,
"defaultValue": "inter-account-name"
},
"Environment": {
"type": "string",
"minLength": 1,
"defaultValue": "dev"
}
},
"variables": {
"resourceGroupName": "[if(equals(parameters('Environment'), 'prd'),'rg-resources-production','rg-resources-staging')]",
"LogicAppIntegrationAccount": "[concat('/subscriptions/3fxxx4de-xxxx-xxxx-xxxx-88ccxxxfbab4/resourceGroups/',variables('resourceGroupName'),'/providers/Microsoft.Logic/integrationAccounts/',parameters('IntegrationAccount'))]",
},
In the above sample, we had two different integration accounts one for testing and one for production. This is why I have set the integration account name as a parameter as it changes between environments.
I have created a variable "resourceGroupName" this is important because this url is setting up a direct link to the integration account which is stored in a known resource group. In this sample I have included an if statement using the value set at the "environment" parameter. This helps select which resource group is going to be used.
I then create another variable which stores the new URL. Replace the subscription guid with your own: 3fxxx4de-xxxx-xxxx-xxxx-88ccxxxfbab4.
Once that is created you need to change the ARM template to use the variable you just created. To set it,place in the properties object.
"properties": {
"state": "Enabled",
"integrationAccount": {
"id": "[variables('LogicAppIntegrationAccount')]"
},
So for you pipeline it should just be a normal arm template but with these two parameters above being set.
Let me know if you have more questions around this.
My current setup stores the environment specific application settings within a section the ARM parameter files. So, the structure of ARM parameters files looks something like this:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"deploymentSpecificValues": {
"value": {
"subscriptionId": "0ce7bbfc-9fa4-46b5-8f38-303db907fd89",
"environmentName": "dev",
"azureBlobUri": "https://mytestblob.blob.core.windows.net/"
}
},
"regions": {
"value": [
{
"location": "West US",
"additionalRegionData": "abc"
},
{
"location": "West US 2",
"additionalRegionData": "pqr"
}
]
},
"webAppInfo": {
"value": {
"appName": "mytestapp",
"appSettings": {
"SqlServerConnectionString": "mySqlServerConnectionString",
"Service1Url": "https://www.service1url.com",
"Service2Url": "https://www.service2url.com"
}
}
},
"sku": {
"value": "Dynamic"
}
}
}
Notice the appSettings located under the webAppInfo node of the above code. Each environment has it's own parameters file like the above. I believe that the number of appsettings can keep growing with time and it might clutter the parameters files.
Questions:
Is this the best practice to manage appsetting?
If the answer to the above question is a no, then what's the best practice to handle the appsettings in such scenarios?
A couple thoughts:
What you're doing is fine, but you're right in that 1) it could get unwieldy in param files and 2) generally these param files are in source control, so make sure what you have in there, should be in source.
Check to see if there are values that you can get from the deployment at deployment time, e.g. subscriptionId can be returned from the subscription() function (assuming you want the id of the subscription you are deploying to).
There are two resources in Azure that you can use to store "config" - you can use them slightly differently.
KeyVault can store arbitrary strings (e.g. blobs of json) securely and they can be dynamically referenced (via parameters) at deployment time.
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/key-vault-parameter
App-Config is a resource to store config values for just such an occasion - you can pull values out of the config store using the listKeyValue() template function
https://learn.microsoft.com/en-us/azure/azure-app-configuration/quickstart-resource-manager
https://github.com/Azure/azure-quickstart-templates/tree/master/101-app-configuration
That help?
Yes, I think this is a good practice to manage appsettings in ARM template like this.
But if you just want to add/update a setting, it is recommended to use azure portal or Azure CLI.
Reference:
az webapp config appsettings
I have an Azure Resource Manager template to spin up a storage account, and its name is being set using a parameter, like this:
"resources": [
{
"name": "[parameters('storageAccountName')]",
"type": "Microsoft.Storage/storageAccounts",
I want to output details of the resource, but can't see a way of referencing the storage account, as most examples I can find reference the resource by name.
I've tried this:
"outputs": {
"storageKey": {
"type": "string",
"value": "[reference([parameters('storageAccountName')])]"
}
}
But get the error message:
The template output 'storageKey' at line '49' and column '23' is not valid:
Unable to parse language expression 'reference([parameters('storageAccountName')])': expected token 'Identifier' and actual 'LeftSquareBracket'
So how do I reference the resource if its name is set using a parameters.json file?
just to add to existing answer (which is fine, but incomplete). a better way of doing this is using the resourceId() function:
reference(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), 'api-version-goes-here')
there are several reason for that.
this is a universal way of referencing a resource. you can reference a resource in another resource group\another subscription using this method (and not only resources in the same deployment). you can drop 'api-version-goes-here' for resources in the same deployment
the existing answer will fail if you have 2 or more resources of different type but having the same name (say storage account and virtual machine), because it wont be able to determine which resource you are targeting
ps. same goes for dependsOn, you can get away with just the name, but I find its always better\more reliable to use resourceId(), especially in big\complicated templates.
I figured it out. The internal square brackets were unnecessary:
"storageKey": {
"type": "Object",
"value": "[reference(parameters('storageAccountName'))]"
}
works.
Use of resourceId() is recommended.
Check MS documentation:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-template-functions-resource#resourceid
It returns the unique identifier of a resource. You use this function when the resource name is ambiguous or not provisioned within the same template.
status update: It appears the example values I was looking for were right there in front of me in the <resource group name> | automation script | template | parameters view and also if I click "Deploy" it produces a pretty UI with examples for all the parameters.json file entries defined based on the resource group settings that the script is derived from.
I created with azure portal wizard a resource group and within it a function app where the wizard created an associated consumption based app service plan, storage account and application insights resources to support it.
I then used the resource group's | settings | automation script | deployment option to get the template.json, parameters.json and bash deploy.sh / powershell deploy.ps1 scripts to automate recreating this configuration in another azure subscription, or same subscription but different resource group.
The issue i'm running into is what the meaning is and relevant values are for a few of the parameters i'm finding in the parameters.json shown below. When I run bash deploy.sh / powershell deploy.ps1 scripts I make it to the point of it processing the last parameter where it appears to fail. I've placed ??? marks beside entries below where it isn't clear what the value should look like and applies to. I haven't been able to find any insights in search hits or script error output suggested https://aka.ms/arm-deploy and https://aka.ms/arm-template/#resources references.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"sites_myfuncapp_name": {
"value": "myfuncapp1"
},
"components_myfuncapp_name": {
"value": "myfuncapp1" ???
},
"storageAccounts_mystoracct_name": {
"value": "mystoracct1"
},
"config_web_name": {
"value": "myfuncapp1" ???
},
"serverfarms_myappsvcplan_name": {
"value": "myappsvcplan1"
},
"alertrules_Failure_Anomalies___myfuncapp_name": {
"value": "myfuncapp1" ???
},
"hostNameBindings_myfuncapp.azurewebsites.net_name": {
"value": "myfuncapp1" ???
}
}
}
What I am interested in is reading the output parameters of another deployment in a different resource group.
My ARM templates are something like:
platform.json - sets up the DNS, virtual networks and security
storage.json - sets up databases and other stores
app.json - sets up the web app/api
Each is deployed in different resource groups as they have different life cycles. However, when I deploy the app.json I want to pull in the outputs of the latest platform and storage deployments and use them to configure the app.
Linked templates are not a solution as the linked templates end up deployed in the same resource group as the app which defeats the purpose of segregating your resources in resource groups.
Is there any way I can read the output parameters of a deployment from a different resource group? if not, is Azure planning to support it?
I know there is a way to get the resources by id, using the resourceId function, and look at their properties but I am trying to avoid doing that to not get into a resource reference spagetti.
I know this is an old question but for others who come along, as of 03/12/18 you can definitely do this.
You need to ensure your output is formatted as per the Microsoft documentation for output variables which broadly has the format
"outputs": {
"resourceID": {
"type": "string",
"value": "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIPAddresses_name'))]"
}
}
You can then use these outputs in your templates by referencing the deployment using a resource reference which has the format
reference(resourceName or resourceIdentifier, [apiVersion], ['Full'])
Note that you will need to provide the api version, as the deployment may use a different api version to the one your parent template uses.
Your reference would then look something like the following
{
"comments": "This would have an output named myOutput you want to use",
"apiVersion": "2017-05-10",
"type": "Microsoft.Resources/deployments",
"name": "my-deployment",
"resourceGroup": "...",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "...",
"contentVersion": "1.0.0.0"
},
"parameters": { }
},
{
"comments": "This makes use of myOutput from my-deployment",
"apiVersion": "2017-05-10",
"type": "Microsoft.Resources/deployments",
"name": "my-dependent-deployment",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "...",
"contentVersion": "1.0.0.0"
},
"parameters": {
"myValueFromAnotherDeployment": { "value": "[reference('my-deployment', '2017-05-10').outputs.myOutput.value]" }
}
}
}
Note the slightly awkward "repackaging" of the value, where we use myOutput.value as the input to the dependent deployment, and put that in an object with the key "value": "....". This is because ARM parameters must have a 'value' property in order to be valid.
You'll get invalid template errors if you try to use the output directly (because output variables have a 'type' and this is not an allowed key in a parameter). That's why you need to get the value property and then put it back into the value in downstream templates.
How are you doing your deployments? In PowerShell you can do something like:
(Get-AzureResourceGroupDeployment NameOfResourceGroup).Outputs.NameOfOuputProperty.Value
And that will give you the output of the most recent deployment. You can also throw the entire deployment object into a var and have at it that way.
$d = Get-AzureResourceGroupDeployment NameOfResourceGroup
Which would be faster if you needed a many output properties.
That help?
Update for AzureRM cmdlet
The syntax is largely the same:
(Get-AzureRmResourceGroupDeployment -ResourceGroupName NameOfResourceGroup -Name NameOfDeployment).Outputs.NameOfOutputProperty.value
If you have multiple deployments you can use:
Get-AzureRmResourceGroupDeployment -ResourceGroupName NameOfResourceGroup
To see them all and see what the names are...
Are you using Azure DevOps Release Pipelines? You could just set the output to be created as variables so you can re-use them in the same or a different stage.
We use these extensions on our projects
ARM Outputs
https://github.com/keesschollaart81/vsts-arm-outputs
VSTS replacetokens
https://github.com/qetza/vsts-replacetokens-task