How can I link a template in an Azure ARM template? - azure

I have multiple ARM templates that I want to link. But when I use "[uri(deployment().properties.templateLink.uri, 'transform.json')]" I get an error telling me that deployment() gives an object that does not contain templateLink when running it locally or through the Azure DevOps pipeline.
So then I tried to send in the path to the artifact that I create when I build the project in Azure DevOps, "[concat(parameters('templateDirectory'), '/transform.json')]", and then provide it as a parameter when calling the template.
But then I get this error instead
At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-debug for usage details.
Details:
BadRequest: {
"error": {
"code": "InvalidContentLink",
"message": "The provided content link 'file:///D:/a/r1/a/_Infrastructure/ARM/shared/transform.json' is invalid or not supported. Content link must be an absolute URI not referencing local host or UNC path."
}
} undefined
Task failed while creating or updating the template deployment.
So my question is how should I handle the linking of templates when I deploy through the Azure DevOps pipeline?
Do I have to copy it to a storage in the build step so that I can access it with http or https in the deploy step, and if so, how is the best way to that? it seems a little complex.
Solution update
So the solution I went for was to upload all the template files to a temporary storage that I created and then added the path to that to the main template that refers to all the templates.
Task overview to get a better understanding of how it was done:
Copy templates to blob:
Deploy ARM template:
And here a snippet of how it was used in the main template referring other templates:
"resources": [
{
"apiVersion": "2015-01-01",
"name": "dashboard-24h",
"type": "Microsoft.Resources/deployments",
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat(parameters('templateBasePath'), '/dashboard/24h/azuredeploy-dashboard-deploy.json')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"templateBasePath": {
"value": "[parameters('templateBasePath')]"
},
"appName": {
"value": "[parameters('appName')]"
}
}
}
},
...
]

so, if you want to use the deployment().properties.templateLink.uri your template has to be deployed from a url, not from a local disk.
nested templates ALWAYS have to be deployed from url. so, if you want to use the aforementioned method, everything has to be uploaded to someplace that is accessible publicly (or auth has to be done through URL, like SAS token).
What I usually do - run a simple powershell script before deployment that uploads all the templates to a common location, after that I just use deployment function.

Expanding on the above if you are generating your ARM
Or
Using AzureResourceManagerTemplateDeployment#3 to deploy the generated templates you can override the variables like this
- task: AzureResourceManagerTemplateDeployment#3
inputs:
deploymentScope: 'Resource Group'
... other values
deploymentMode: 'Validation'
overrideParameters: '-LinkedTemplatesBaseUrl "$(BASE_URL)" -LinkedTemplatesUrlQueryString $(SAS_TOKEN)'
The LinkedTemplatesBaseUrl and LinkedTemplatesUrlQueryString must be defined in the *-parameters.json file
Use LinkedTemplatesUrlQueryString only when fetching from secured storage (which is a preferred way)
You can use AzureFileCopy#4 to copy your templates
steps:
- task: AzureFileCopy#4
name: AzureFileCopyTask
inputs:
SourcePath: '$(System.DefaultWorkingDirectory)/build_dir/*.json'
azureSubscription: $(AZURE_SUBSCRIPTION)
Destination: 'AzureBlob'
storage: $(STORAGE_ACCOUNT)
ContainerName: $(STORAGE_CONTAINER)
CleanTargetBeforeCopy: true
BlobPrefix: $(STORAGE_PREFIX)
And use the output variables like mentioned here

Related

Sample ARM template for Azure Function deployment (linux) using multistage YAML (MSY)

I need sample ARM template which I can refer to deploy Function app in Azure portal. I am using multi stage YAML deployment (not classic deployment). The App service plan kind is Linux.
I need the configuration step which is responsible for deploying code to Function app.
I know we can use MS deploy in case of Window App service plan . I need for linux environment.
Basically, I need confirmation if we can do zip deployment using multi stage yaml deployment for linux environment.
Windows example:
{
"name": "MSDeploy",
"type": "extensions",
"location": "[parameters('location')]",
"apiVersion": "2019-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('functionAppName'))]"
],
"properties": {
"packageUri": "[concat(parameters('containerUri'), parameters('functionAppPackageName'), parameters('containerSasToken'))]",
"AppOffline": true
}
}
I am not sure why you want ARM template to deploy the azure function, the DevOps pipeline itself can handle this operation.
steps:
- task: AzureFunctionApp#1
displayName: 'Azure Function App Deploy'
inputs:
azureSubscription: 'xxx'
appType: functionAppLinux
appName: xxx
deployToSlotOrASE: true
resourceGroupName: xxx
runtimeStack: 'xxx'
But if you need ARM template, you can refer to this official document:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-infrastructure-as-code#customizing-a-deployment
Yes, it supports zip deployment using multi stage YAML deployment for Linux environment.
Multi-Stage Pipelines using YAML for Continuous Delivery – Azure DevOps
The above reference has all the requirements and configuration steps of deploying any code to the Azure Function App.
steps:
- task: AzureFunctionApp#1
- displayName: Azure Function App Deploy
inputs:
azureSubscription: $(azureSubscription)
appName: samplefunctionapp
package: $(System.DefaultWorkingDirectory)/**/*.zip
This Microsoft documentation provides a good example of deploying the azure functions in linux environment through Multi Stage YAML. Also please check this reference.

can I pass the URL of build artifact to linked ARM template deployment?

I am trying to pass the build artifact path for the linked template but its throwing the below error.
InvalidContentLink: The provided content link
'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Data.Entities.Deployments.DeploymentTemplateContentLink'
is invalid or not supported. Content link must be an absolute URI not
referencing local host or UNC path.
Details:
I have the build artifacts inside the folder manifest. I have a token replacement task to replace files in the manifest like this -> manifest/swagger.json. then I have a deployment task which has one master template and linked template. master template I am able to provide the link such as $(Pipeline.Workspace)/Manifest/Changes/master.json inside that I have parameters for the linked template path and I am passing the path like $(Pipeline.Workspace)/Manifest/Changes/Artifact/something.json.
Does the link for the linked template always has to be an URL like in the samples from storage account. If that's the case, right now we don't have the need for storage account in our project, is there any alternatives to achieve that?
update:
though I am passing it from parameter, I am providing the sample directly to make the context clear.
{
"properties": {
"mode": "Incremental",
"templateLink": {
"uri": "[concat('$(Pipeline.Workspace)/Manifest/Changes/linkedtemplates', '/initial.api.template.json')]",
"contentVersion": "1.0.0.0"
},
"parameters": {
"ServiceName": {
"value": "[parameters('ServiceName')]"
}
}
}
You can't use the pipeline artifact, you need a publicly accessible URL. This is why the samples use a storage account.
When referencing a linked template, the value of uri can't be a local file or a file that is only available on your local network. Azure Resource Manager must be able to access the template. Provide a URI value that downloadable as http or https.
https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/linked-templates#linked-template

How to test within Azure - Azure Resource Manager (ARM Templates)

Assume we have a Checkpoint Firewall Template created on Azure Portal. Is there a way to test the Template within Azure? Also if the Template is modified, is there a way to Test that new modified Template within Azure?
You can test an ARM Template by using it in a deployment. You can also use the what-if setting to produce hypothetical output without actually deploying anything.
Microsoft Azure Docs for What-If
To create a What-If deployment you can proceed a number of ways; Azure CLI, PowerShell, REST, etc. Here is an example using REST (Postman).
Use the endpoint
POST https://management.azure.com/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.Resources/deployments/{deploymentName}/whatIf?api-version=2020-06-01
Provide a body payload:
{
"location": "westus2",
"properties": {
"mode": "Incremental",
"parameters": {},
"template": {}
}
}
Add your template and parameters. Supply a bearer token for authentication and deploy.
You can check the Azure What-If REST API docs here.

Mechanism to upload ARM template into storage

I want to use linked templates in my ARM deployment model. Every article I've read mentions that the linked template needs to be in an accessible location (such as blob storage).
This works OK if I manually upload the files to storage but I'm looking for a mechanism to upload a template to Storage as part of the build or Deployment process.
I'd hoped to use the Artifact Storage Account option but it is unavailable when deploying infrastructure only.
Is there a built-in method to achieve this or would it require either an extra step such as powershell script or VSTS build step?
The Artifact Storage Account option becomes available as soon as you introduce the two parameters _artifactsLocation and _artifactsLocationSasToken into your deployment.
"parameters": {
"_artifactsLocation": {
"type": "string",
"metadata": {
"description": "Auto-generated container in staging storage account to receive post-build staging folder upload"
}
},
"_artifactsLocationSasToken": {
"type": "securestring",
"metadata": {
"description": "Auto-generated token to access _artifactsLocation"
}
}
}

Can an Azure ARM nested template be deployed with a mode of Complete?

All the examples have the mode of nested templates set to 'Incremental'.
When I set it to 'Complete', I get the following error:
error: InvalidNestedDeploymentMode : Specified deployment mode 'Complete' is not supported for nested deployment 'shared'. Please see https://aka.ms/arm-deploy for usage details.
error: Deployment validate failed.
error: Error information has been recorded to /Users/.../.azure/azure.err
verbose: Error: Deployment validate failed.
I've tried running the deployment creation w/ both incremental and complete mode, getting the same error.
Wasn't sure if this was even possible - can't find any docs related to the error 'InvalidNestedDeploymentMode'.
Portion of the ARM template :
{
"name": "[concat('node', copyIndex())]",
"type": "Microsoft.Resources/deployments",
"apiVersion": "2015-01-01",
"dependsOn": [
"[resourceId('Microsoft.Resources/deployments', 'shared')]"
],
"copy": {
"name": "nodecopy",
"count": "[parameters('vmCount')]"
},
"properties": {
"mode": "Complete",
"templateLink": {
"uri": "...",
"contentVersion": "1.0.0.0"
}
}
Can an Azure ARM nested template be deployed with a mode of Complete?
Firstly, we could know Incremental and Complete mode that used to deploy resources from this documentation.
Besides, as Andrew W said, only the root-level template is allowed Complete for the deployment mode. If you use Azure PowerShell with Resource Manager templates to deploy your resources to Azure and use -Debug parameter, you could see detailed error message.
See the note under "Link Templates for Deployment".
TL;DR: if your nested template targets the same resource group as the top level template and you deploy the top level template in "Complete" mode the nested template will be treated as being deployed in "Complete" mode but otherwise it will be deployed in "Incremental" mode.

Resources