We are developing an application which uses the following two resources:
Azure Functions for the backend
Azure Storage as a static website for the front end
This is being deployed automatically by our CI pipeline using ARM templates. However, for the application to work we need to set the CORS rules on the Azure function to allow the static website to perform the api calls.
This is now performed by the following resource configuration:
{
"type": "Microsoft.Web/sites/config",
"name": "[concat(variables('functionAppName'), '/web')]",
"apiVersion": "2016-08-01",
"location": "[parameters('location')]",
"properties": {
"cors": {
"allowedOrigins": [
"[concat('https://', variables('storageAccountName'),'.z21', '.web.core.windows.net']"
],
}
},
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', variables('functionAppName'))]"
]
}
However we are hardcoding the .z21 parameter since we know that the location parameter will be South Central US. However, this is not something that we desire to hardcode since probably the application could be deployed to another location.
Reading upon the documentation for static website hosting it states that
The URL of your site contains a regional code. For example the URL https://contosoblobaccount.z22.web.core.windows.net/ contains regional code z22.
While that code must remain the URL, it is only for internal use, and you won't have to use that code in any other way.
However I couldnt find a reference to which regional codes are being used by Azure. Is there a way to know that so that we stop hardcoding this value into our ARM template?
Another approach would be to dynamically access the storage account properties on the ARM template through an ARM template function, however I am unsure of which function could help us retrieve the regional code for the storage account.
Thanks in advance!
Ugly solution to extract regional code with PowerShell.
$stgname = '0708static'
$start = "https://$stgname."
$end = (Get-AzStorageAccount -Name $stgname -ResourceGroupName 'deleteme').PrimaryEndpoints.Web.TrimEnd('.web.core.windows.net/')
$result = $end.TrimStart("$start")
$result
If you want the entire URI then you can use:
[reference(variables('storageAccountId'), '2019-04-01').primaryEndpoints.web
If you want just the region code you can use:
[split(reference(variables('storageAccountId'), '2019-04-01').primaryEndpoints.web, '.')[1]]
Related
I am new to Azure. I am trying to create an environment that should be fairly straightforward - App Service and Azure SQL with a Private Endpoint. I decided to try this ARM template:
https://azure.microsoft.com/en-us/resources/templates/web-app-regional-vnet-private-endpoint-sql-storage/
https://github.com/Azure/azure-quickstart-templates/tree/master/demos/web-app-regional-vnet-private-endpoint-sql-storage
I am not quite sure what to put for the V Nets (sic) entry. I have tried for hours and read through all the documentation I can find, which is lacking. Can someone please provide advice or an example. Thanks.
Azure Image
UPDATE
This is what I ended up putting in the VNets parameter:
[{"name":"hub-vnet","addressPrefixes":["10.1.0.0/16"],"subnets":[{"name":"PrivateLinkSubnet","addressPrefix":"10.1.1.0/24","udrName":null,"nsgName":null,"delegations":null,"privateEndpointNetworkPolicies":"Disabled","privateLinkServiceNetworkPolicies":"Enabled"}]},{"name":"spoke-vnet","addressPrefixes":["10.2.0.0/16"],"subnets":[{"name":"AppSvcSubnet","addressPrefix":"10.2.1.0/24","udrName":null,"nsgName":null,"privateEndpointNetworkPolicies":"Enabled","privateLinkServiceNetworkPolicies":"Enabled","delegations":[{"name":"appservice","properties":{"serviceName":"Microsoft.Web/serverFarms"}}]}]}]
In the same repo, check out the azuredeploy.parameters.json file, and you'll see an example of the vNets object it's looking for.
You can use the parameters file as-is and deploy it to your subscription or feel free to customize the names, address spaces, etc. by adjusting the properties
snippet
"parameters": {
"vNets": {
"value": [
{
"name": "hub-vnet",
// ...
},
{
"name": "spoke-vnet",
// ...
}
]
},
I am using Azure function hosted in premium plan. I want to enable runtime scale monitoring using ARM template.
Screenshot is attached for setting.
Please suggest how can I enable this setting via ARM.
If you click on the "Learn More" link in your screenshot it will take you to a doc that describes how to do it via CLI. That command is setting a property in web config named functionsRuntimeScaleMonitoringEnabled to true. So in your template you would do the same. How depends a bit on how your template is setting config -- it could be on the webApp itself or on a child resource of type Microsoft.Web/sites/config.
{
"type": "Microsoft.Web/sites/config",
"apiVersion": "2019-08-01",
"name": "foo",
"location": "...",
"properties": {
"...": "...",
"functionsRuntimeScaleMonitoringEnabled": true
}
}
Note that ARM is declarative so you can't use that example literally as it will wipe all of your other settings. You need to fill in the ... accordingly.
That help?
Azure Functions Consumption Plan running on Linux is now GA.
How can I provision such application with an ARM Template?
Basically, I want this template but on Linux.
If you want to create a new Linux Consumption Plan, set the reserved property to true for Microsoft.Web/serverfarms (see FAQ):
{
"type": "Microsoft.Web/serverfarms",
"apiVersion": "2016-09-01",
"name": "[parameters('serverfarms_NorthEuropeLinuxDynamicPlan_name')]",
"location": "North Europe",
"sku": {
"name": "Y1",
"tier": "Dynamic",
"size": "Y1",
"family": "Y",
"capacity": 0
},
"kind": "functionapp",
"properties": {
"name": "[parameters('serverfarms_NorthEuropeLinuxDynamicPlan_name')]",
"reserved": true
}
},
If you rather want to deploy a Function App to a built-in Linux Consumption Plan, set the kind property for Microsoft.Web/sites:
"kind": "functionapp,linux"
See this link:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-infrastructure-as-code#create-a-consumption-plan
Primary this line:
The Consumption plan cannot be explicitly defined for Linux. It will be created automatically.
One simple way I found out during my trial and error is, download the ARM template from the Azure for this purpose and then modify with appropriate naming convention for consumption plan. Then deploy the ARM template to create the function app.
Steps are as below:
Downloading ARM template from Azure:
Try to create a new function app with Linux consumption plan. At this point in time on GUI, azure does not allow us to select the name for the consumption plan (screenshot below)
Complete other steps (monitoring, tags, etc) and then go to "Review and Create" step. Let the validation pass here. Once this step is done, do not click "Create" button. On the right side down now you can see "Download a template for automation" link. Click this link and download the template. Modify the parameters with the required ones'. Change the Hosting plan name to required name.
Modify the parameters file and deploy to create function app:
In Azure, go to "Custom Deployment" blade and then upload both Template and parameters file. Deploy this ARM template. It will easily create the function app with Linux consumption plan with desired naming convention for Consumption plan (dynamic)
How can I deploy my function app attached to a VNet using an arm template?
Right now my arm template deploys an AppServicePlan based function app just fine and sets the "vnetName" in the "site" resource "properties" section...but after the deploy the function app still shows as "not configured" for any VNet. I can then go into the portal and add to the desired VNet in a couple of clicks...but why doesn't it work via the arm template? Can someone please provide a sample arm template to do this?
Upon further review this is not possible via only ARM. Here are the instructions to connect a web app to a VNet: https://learn.microsoft.com/en-gb/azure/app-service-web/app-service-vnet-integration-powershell
Old Answer: Here is another post trying to achieve the same with Web Apps (Functions is built on Web Apps): https://stackoverflow.com/a/39518349/5915331
If I had to guess based on the powershell command, try adding a sub resource to the site of type config with name web, similar to the arm template for a github deployment: https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/app-service-web/app-service-web-arm-from-github-provision.md#web-app
There may be some magic happening under the hood, however.
{
"name": "[parameters('siteName')]",
"type": "Microsoft.Web/sites"
"location": ...,
"apiVersion": ...,
"properties": ...,
"resources": [
"name": "web",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]"
],
"properties": {
"vnetName": "[parameters('vnetName')]"
},
]
}
I can do everything with ARM except create the VPN package - which is what makes the difference between just setting the resource properties and actually making the app connect to the VNET correctly.
Everything in this article (https://learn.microsoft.com/en-gb/azure/app-service-web/app-service-vnet-integration-powershell) can be easily converted from PowerShell to ARM except for Get-AzureRmVpnClientPackage
Hypothetically, if you are using a legacy VNET, you could get the VPN client package URL via ARM because the legacy VNET resource provider supports that operation (https://learn.microsoft.com/en-us/azure/active-directory/role-based-access-control-resource-provider-operations):
Microsoft.ClassicNetwork/virtualNetworks/gateways/listPackage/action
The ARM VNET provider does not seem to
I'm trying to learn Azure Resource Templates and am trying to understand the workflow behind when to use them and when to use the REST API.
My sense is that creating a Virtual Network and Subnets in Azure is a fairly uncommon occurance, once you get that set up as you want you don't modify it too frequently, you deploy things into that structure.
So with regard to an ARM Template let's say I have a template with resources for VNET and Subnet. To take the example from https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-template-walkthrough#virtual-network-and-subnet I might have:
{
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/virtualNetworks",
"name": "[parameters('vnetName')]",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"10.0.0.0/16"
]
},
"subnets": [
{
"name": "[variables('subnetName')]",
"properties": {
"addressPrefix": "10.0.0.0/24"
}
}
]
}
}
which I deploy to a Resource Group. Let's say I then add a Load Balancer and redeploy the template. In this case the user then gets asked to supply the value for the vnetName parameter again and of course cannot supply the same value so we would end up with another VNET which is not what we want.
So is the workflow that you define your ARM Template (VNET, LBs, Subnets, NICs etc) in one go and then deploy? Then when you want to deploy VMs, Scale Sets etc you use the REST API to deploy then to the Resource Group / VNET Subnet? Or is there a way to incrementally build up an ARM Template and deploy it numerous times in a way that if a VNET already exists (for example) the user is not prompted to supply details for another one?
I've read around and seen incremental mode (default unless complete is specified) but not sure if this is relevant and if it is how to use it.
Many thanks for any help!
Update
OK so I can now use azure group deployment create -f azuredeploy.json -g ARM-Template-Tests -m Incremental and have modified the VNET resource in my template from
{
"apiVersion": "2016-09-01",
"type": "Microsoft.Network/virtualNetworks",
"name": "[variables('virtualNetworkName')]",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[variables('addressPrefix')]"
]
},
"subnets": [
{
"name": "[variables('subnetName')]",
"properties": {
"addressPrefix": "[variables('subnetPrefix')]"
}
}
]
}
},
to
{
"apiVersion": "2015-05-01-preview",
"type": "Microsoft.Network/virtualNetworks",
"name": "[parameters('virtualNetworkName')]",
"location": "[resourceGroup().location]",
"properties": {
"addressSpace": {
"addressPrefixes": [
"[parameters('addressPrefix')]"
]
},
"subnets": [
{
"name": "[parameters('subnet1Name')]",
"properties": {
"addressPrefix": "[parameters('subnet1Prefix')]"
}
},
{
"name": "[parameters('gatewaySubnet')]",
"properties": {
"addressPrefix": "[parameters('gatewaySubnetPrefix')]"
}
}
]
}
},
but the subnets don't change. Should they using azure group deployment create -f azuredeploy.json -g ARM-Template-Tests -m Incremental
I am going to piggy back on this Azure documentation. Referencing appropriate section below:
Incremental and complete deployments
When deploying your resources,
you specify that the deployment is either an incremental update or a
complete update. By default, Resource Manager handles deployments as
incremental updates to the resource group.
With incremental deployment, Resource Manager
leaves unchanged resources that exist in the resource group but are not specified in the template
adds resources that are specified in the template but do not exist in the resource group
does not reprovision resources that exist in the resource group in the same condition defined in the template
reprovisions existing resources that have updated settings in the template
With complete deployment, Resource Manager:
deletes resources that exist in the resource group but are not specified in the template
adds resources that are specified in the template but do not exist in the resource group
does not reprovision resources that exist in the resource group in the same condition defined in the template
reprovisions existing resources that have updated settings in the template
To choose Incremental update or Complete update it depends on if you have resources that are in use. If devops requirement is to always have resources in sync with what is defined in the json template then Complete Update mode should be used. The biggest benefit of using templates and source code for deploying resources is to prevent configuration drift and it is beneficial to use Complete Update mode.
As for specifying the parameters if you specify in parameters file then you don't have to specify them again.
A new template can be deployed in incremental mode which would add new resources to the existing resource group. Define only the new resources in the template, existing resources would not be altered.
From powershell use the following cmdlet
New-AzureRmResourceGroupDeployment -ResourceGroupName "YourResourceGroupName" -TemplateFile "path\to\template.json" -Mode Incremental -Force
My rule of thumb is for things that I want to tear down, or for things I want to replicate across Subscriptions, I use ARM templates.
For example we want things in test environments, I just ARM it up, build on the scripts as developers request things ("Hey I need a cache", "Oh by the way I need to start using a Service Bus"), using incremental mode we can just push it out to Dev, then as we migrate up to different environments you just deploy to a different Subscription in Azure, and it should have everything ready to go.
Also, we've started provisioning our own Cloud Load Test agents in a VMSS, a simple ARM template that's called by a build to scale up to x number of machines, then when done, we just trash the Resource Group. It's repeatable and reliable, sure you can script it up, but as TFS has a task to deploy these things (also with schedules)...
One of the beautiful things I've come across is Key Vault, when you ARM it up and poke all the values from your service busses, storage accounts/whatevers, you can simply get the connection strings/keys/whatevers and put them straight into the Key Vault, so you never need to worry about it, and if you want to regenerate anything (say a dev wants to change the name of a cache or whatever, or accidentally posted the key to GitHub), just redeploy (often I'll just trash the whole Resource Group) and it updates the vault for you.