How to deploy multiple Azure resources from a local environment? (VS Code) - azure

I have a web app that requires an Azure App Service, Azure Function, and Cosmos DB Database to run. I'm thinking about setting up a way for myself and the other developers to trigger a deployment of the full application to a development resource group specific to the developer that will contain a full version of the app. For example, a dev-John resource group that would contain a dev-John-AppService, dev-John-Function, and dev-John-CosmosDB. Is there an easy way to do this in VSCode using ARM templates?

The Azure Resource Manager Tools for Visual Studio Code provide language support, resource snippets, and resource autocompletion. These tools help create and validate Azure Resource Manager templates (ARM templates).
Create and open with Visual Studio Code a new file for example deploy.json. Just enter arm! into the code editor, which initiates Azure Resource Manager snippets. You can use this snippet to create your ARM template as you desire.
You can achieve your goal by using the Parameters and Functions element of your ARM template.
In the parameters section of the template, you specify the values that are provided when deployment is executed to customize resource deployment. Similarly you can also use functions, ARM template functions add flexibility to your ARM template by dynamically getting values during deployment.
The below ARM template can be used to deploy same resource with customization with the help of parameters and functions.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageName": {
"type": "string",
"minLength": 3,
"maxLength": 24
}
},
"functions": [],
"variables": {},
"resources": [{
"name": "[parameters('storageName')]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-06-01",
"tags": {
"displayName": "[parameters('storageName')]"
},
"location": "[resourceGroup().location]",
"kind": "StorageV2",
}],
"outputs": {}
}
Here when we added "[parameters('storageName')]" we used the parameters function. Lastly you can even create PowerShell scripts to call the ARM templates.
I would suggest to read this Deploy to multiple Azure environments by using JSON ARM template features document and Exploring ARM Templates: Azure Resource Manager Tutorial for more information.

Related

Automatically create an Azure DevOps Organization with an ARM Template

Since it is not possible to create an organization with the DevOps Rest API and the SDK for organizations is still in preview and not functional, we currently try to programmatically create an organization with an ARM template.
In the Azure Portal, it is possible to create a new organization with an ARM template like this:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/Microsoft.Resources.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"organizationName": {
"type": "string",
"defaultValue": ""
},
"organizationIdentifier": {
"type": "string",
"defaultValue": ""
},
"administrator": {
"type": "string",
"defaultValue": ""
}
},
"resources": [
{
"name": "[parameters('organizationIdentifier')]",
"type": "microsoft.visualstudio/account",
"location": "West Europe",
"description": "[parameters('organizationName')]",
"apiVersion": "2014-02-26",
"properties": {
"operationType": "Create",
"accountName": "[parameters('organizationIdentifier')]",
"ownerUpn": "[parameters('administrator')]"
}
}
]
}
Unfortunately we couldn't find a solution to create this within a C# Azure Function programmatically, since the SDK would want a resource group, which doesn't make sense in this context. Is there a way to do this or is it simply not possible to create an organization automatically at this point?
Yes, as of now there is no ways to create an DevOps organization using REST API.
The way to create Azure DevOps Organization is Manual creation or using ARM Template.
Using ARM Template, you have to specify the Resource name as a parameter. That is also we need to mention the Organization Name before deploying the ARM Template.
As of now the REST API is available for some of the services.
References
-Automating organization and project creation in Azure DevOps Blog gives the clear view

Parallel deployment of Azure AppService using ARM template

I am trying to solve a use-case of deploying 20 to 30 Azure AppServices using ARM template based on Admin decision.
This is happening through c# webapi using Microsoft Fluent library(Microsoft.Azure.Management.Fluent & Microsoft.Azure.Management.ResourceManager.Fluent),
var creds = new AzureCredentialsFactory().FromServicePrincipal(clientId,
clientSecret,
tenantId,
AzureEnvironment.AzureGlobalCloud);
var azure = Azure.Authenticate(creds).WithSubscription(subscriptionId);
var deployment = azure.Deployments.Define($"deployment-{userName}")
.WithExistingResourceGroup(resourceGroupName)
.WithTemplate(templateJson.ToString())
.WithParametersLink(templateParamsBlobURL, "1.0.0.0")
.WithMode(Microsoft.Azure.Management.ResourceManager.Fluent.Models.DeploymentMode.Incremental)
.Create();
Problem statement
When the admin decides to run 20 AppServices, then the above lines of code will execute and provision these AppServices, the decision is based on admin.
For me the Deployment is happening in sequential manner i.e., upon completing one AppService deployment then it triggers the next AppService deployment, which takes huge time to complete the entire operation. I am trying to achieve the deployment of 20 AppServices(decided by admin) in parallel so that the provisioning completes at the earliest
Kindly assist me on how to achieve the parallel deployment of AppServices using ARM template
Thanks for confirming #Guptha, posted the same as an answer to help other community members for the similar query , To iteration multiple resources at a time in ARM TEMPLATE .
Use your Azure Resource Manager template to create multiple instances
of a resource (ARM template). You can dynamically set the quantity of
resources to deploy by adding a copy loop to the resources section of
your template.
For example to create multiple storage accounts ;
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageCount": {
"type": "int",
"defaultValue": 3
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2019-04-01",
"name": "[concat(copyIndex(),'storage', uniqueString(resourceGroup().id))]",
"location": "[resourceGroup().location]",
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage",
"properties": {},
"copy": {
"name": "storagecopy",
"count": "[parameters('storageCount')]"
}
}
]
}
For complete setup please refer this MICROSOFT DOCUMENTATION|Resource iteration in ARM templates

How can I use slotted deployments in Azure DevOps for an Azure App Service?

I'm having some problems with slotted deployments in Azure DevOps. The problem is that my app goes down during deployment. But once the deployment finishes, it comes up again.
My app comes with an azuredeploy.json file: https://pastebin.com/CPVzE5hM.
While trying to access my web app once it is deploying, it seems to go down at the first step:
Azure Deployment: Create Or Update Resource Group acti...
There are usually no changes to the azuredeploy.json file, so I don't understand why it goes down at this step. There is nothing to create -- it exists before, and there is nothing to update either.
I have set up the slots manually in Azure Portal. The deployment mode is incremental.
How can I use slotted deployments in Azure DevOps for an Azure App Service?
According to your description, we need to create new deployment slot for an existing WebApp.
So, we need to check if we create or update for the new deployment slot instead of the Production:
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"siteName": {
"type": "string"
},
"slotName": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2015-04-01",
"type": "Microsoft.Web/Sites/Slots",
"name": "[concat(parameters('siteName'), '/', parameters('slotName'))]",
"location": "[resourceGroup().location]",
"properties": {},
"resources": []
}
]
}
The template on GitHub.
You could check the document this, this and the similar thread for some more details. If this not resolve this issue, please share your json file to use.

Connect Azure Function App to VNet

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

Azure ARM templates - using the output of other deployments

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

Resources