Provision classic cloud service via ARM template - azure

In one of our project, we are trying to automate deployment of cloud components on Azure. For majority of components (basically all ARM components like Redis, Service bus, App Service etc.) we were able to achieve it using ARM templates and Powershell script.
However, we are stuck at Cloud Service (classic) component. Cloud service component contains only WebRole in it and no VM needs to be provisioned.
We can go via classic deployment model i.e. using ASM commands in power shell. But since, ARM model supports provisioning and deployment from azure portal so I was wondering ARM REST API's must have out of box support for this component as well. I try to figure out but couldn't find any related documentation to it.
What I have tried so far
Azure template (AzureDeploy.json)
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"parameters": {
"name": {
"type": "string"
},
"location": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2014-06-01",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"type": "Microsoft.ClassicCompute/domainNames"
}
]
}
Powershell script:
Param(
[string] $ResourceGroupLocation = 'South India',
[string] $ResourceGroupName = 'FreeTrial',
[string] $TemplateFile = 'AzureDeploy.json'
)
$TemplateFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $TemplateFile))
New-AzureRmResourceGroup -Name $ResourceGroupName -Location $ResourceGroupLocation -Verbose -Force -ErrorAction Stop
New-AzureRmResourceGroupDeployment -Name ((Get-ChildItem $TemplateFile).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) `
-ResourceGroupName $ResourceGroupName `
-TemplateFile $TemplateFile `
-Force -Verbose
If I try to execute the above script, execution gets stuck at Checking deployment for an hour or so and have to manually kill the script execution.
.
However, if I ran following command in power shell, it succesfully creates a resource in portal:
New-AzureRmResource -Location "South India" -ResourceName
"cloudsmplservice" -ResourceType
"Microsoft.ClassicCompute/domainNames" -ResourceGroupName "FreeTrial"
But I do not understand what's an issue with ARM template approach. Can someone please direct me to the problem in first approach?
Addendum:
I found a strange behaviour. If I hardcode the resource name value in the resource definition OR pass it when powershell prompt for it, deployment works fine.
However, if I set some default Value for parameter OR pass it via parameter file, its not working.
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"cloudName": {
"type": "string",
"defaultValue": "cloudsrvc"
}
},
"resources": [
{
"apiVersion": "2015-06-01",
"name": "[parameters('cloudName')]",
"location": "[resourceGroup().location]",
"type": "Microsoft.ClassicCompute/domainNames"
}
]
}
Addendum2:
Seems like some powershell configuration issue. Will report it to Azure team with more details. So, far was able to reproduce it with simple steps:
Created a fresh VM in azure.
Imported AzureRM modules.
Try to provision cloud service with default value template. (Stuck as mentioned)
Try to provision now by passing the parameter from powershell. (Worked fine)
Now try again with default value template. (Worked fine)

I will recommend you to validate your Cloud Service ARM Template from the Template Deployment in the Azure portal.
I am able to deploy a bare metal Cloud Service using the template below and the deployment is successful within seconds.
You can also "reverse engineer" the Cloud Service ARM Template by clicking on the Automation option when try to create a new Cloud Service from the Azure portal.
I didn't see the problem in automating Cloud Service by the ARM Template approach.
Note:
I have deployed this in South India location and it works.
Addendum:
I have deployed the template as below using your PowerShell script and it works as well.
Azure PowerShell version is 4.3.1 (August 2017).
Screenshot as below.
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string"
},
"location": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2016-11-01",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"type": "Microsoft.ClassicCompute/domainNames"
}
]
}
Addendum 2:
Try with template with default param values and the deployment is also working successful.
Note: I notice your api version is older and the api version for my cloud service is 2016-11-01
{
"$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string",
"defaultValue": "[resourceGroup().name]"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
}
},
"resources": [
{
"apiVersion": "2016-11-01",
"name": "[parameters('name')]",
"location": "[parameters('location')]",
"type": "Microsoft.ClassicCompute/domainNames"
}
]
}

We also could use the REST API to do that,I test it with fiddler.
https://management.azure.com/subscriptions/{subscriptionid}/resourceGroups/{resourcegroupname}/providers/Microsoft.ClassicCompute/domainNames/{cloudservicename}?api-version=2016-04-01
Note: please make sure that your subcription support to create the cloudservice in that location. If it is not supported, we will get the following error.
The location constraint is not valid

Related

ARM Template: How to create connection to storage from different resource group?

I'm trying to write an ARM template to deploy a connection to the storage account for my Logic App. The problem is that my Logic App belongs to one resource group & the storage account in another.
When I run the deployment pipeline I get the following deployment error:
The Resource 'Microsoft.Storage/storageAccounts/StorageAccountName'
under resource group 'Logic App Resource Group' was not found.
I understand that the storage account does not belong to this resource group but how do I write the ARM template to look for the storage account from another group?
Here is my template for the connection:
{
"type": "Microsoft.Web/connections",
"apiVersion": "2016-06-01",
"name": "[parameters('storageConName')]",
"location": "[parameters('logicAppLocation')]",
"properties": {
"displayName": "[parameters('storageConName')]",
"parameterValues": {
"accountName": "[parameters('storageAccountName')]",
"accessKey": "[listKeys(variables('storageAccountId'),'2019-06-01').keys[0].value]"
},
"api": {
"id": "[concat('/subscriptions/',parameters('resourceGroupId'),'/providers/Microsoft.Web/locations/northeurope/managedApis/azureblob')]"
}
}
}
I've worked out what was wrong, the properties:api:id was using the logic App resource group id where it should be using the storage accounts resource group id.
I misunderstood that this was the resource group where I wanted the connection to be created.

powershell command to show application insight availability percentage

Looking to get availability percentage from azure application insight using powershell commands. I have BASH command az monitor app-insights metrics show, but since I want to run script in automation runbook, they dont support BASH commands. Does anyone have an idea for how to get same result with PS commands?
My last resort is to use invoke-webrequest or cURL but it has other challenges like API Keys.
Thanks
Need to save availability.json from the json file and Modify the resource as required and save the json as availabilityalert.parameters.json from the json file
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"appName": {
"value": "Replace with your Application Insights resource name"
},
"pingURL": {
"value": "https://www.yoursite.com"
},
"actionGroupId": {
"value": "/subscriptions/replace-with-subscription-id/resourceGroups/replace-with-resourceGroup-name/providers/microsoft.insights/actiongroups/replace-with-action-group-name"
},
"location": {
"value": "Replace with the location of your Application Insights resource"
}
}
}
Get the actionGroupId in Activity log -> select a specific log here you can get resourceid.
You can create the availability test and associated alert using the template and parameters file using PowerShell.
Connect-AzAccount
New-AzResourceGroup -Name AvailabilityAlertDeployment -Location westus2
New-AzResourceGroupDeployment -ResourceGroupName AvailabilityAlertDeployment -TemplateFile ./availabilityalert.json -TemplateParameterFile ./availabilityalert.parameters.json
For further refer

How to give default value to resource group field in ARM template deployment?

I have sample ARM template given below. The fields subscription, resource group and location are provided in first section ARM template to user while deploying and parameters section is provided after this. Resource group is drop down field provided by Azure ARM itself, where I need to provide any one resource group as default resource group present in list. How can this possible?
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"writePermission": {
"defaultValue": "No",
"allowedValues": [
"No",
"Yes"
],
"type": "String",
"metadata": {
"description": "the permission type"
}
}
},
"variables": {
"location": "[resourceGroup().location]",
"templateUri": "[deployment().properties.templateLink.uri]"
},
"resources": [
],
"outputs": {
"result": {
"type": "String",
"value": "[variables('templateUri')]"
}
}
}
This is how template is rendered.
Expected solution:
Instead of blank value in resource group, it should be pre-populated with first field from drop-down of resource group.
A deployment with ARM templates is always providing the deployment resource group outside the template. A deployment is always based in a resource group that you provide as a parameter outside the template. The name of the command to deploy using PS is: New-AzResourceGroupDeployment indicating that you have the provided resource group as a base and the argument to choose the Resource Group is named: -ResourceGroup
So basically you can't choose the base resource group inside your ARM template since that's provided outside for the API to know where to start the deployment.
This is the PS command to do the deployment:
New-AzResourceGroupDeployment
[-Name <String>]
-ResourceGroupName <String>
[-Mode <DeploymentMode>]
[-DeploymentDebugLogLevel <String>]
[-RollbackToLastDeployment]
[-RollBackDeploymentName <String>]
[-Tag <Hashtable>]
[-WhatIfResultFormat <WhatIfResultFormat>]
[-WhatIfExcludeChangeType <String[]>]
[-Force]
[-AsJob]
-TemplateFile <String>
[-SkipTemplateParameterPrompt]
[-ApiVersion <String>]
[-Pre]
[-DefaultProfile <IAzureContextContainer>]
[-WhatIf]
[-Confirm]
[<CommonParameters>]
The PS command is using the ARM Rest API which is the same API used by the Azure Portal, looking at the Rest API you can also see that ResourceGroup is a parameter that needs to be provided outside the ARM template:
https://learn.microsoft.com/en-us/rest/api/resources/deployments/createorupdate
So what I'm saying is that you can't use the template to manipulate the drop down box for the base Resource Group, the only way you can do this is by limiting the access for the users using RBAC so that the user only can see the resource groups the user is supposed to be able to deploy to.

Get the Sku of Azure automation account

I am trying to enable diagnostic settings on existing automation accounts in different subscriptions.
So far my script exist out of the following topics.
Retrieve all Automation Accounts
Loop through every single on of them.
Change the value of the parameters in the ARM template to the value of the retrieved automation account
Deploy the ARM template that enable diagnostic settings on that specific automation account.
{
"name": "[parameters('AutomationAccountName')]",
"type": "Microsoft.Automation/automationAccounts",
"apiVersion": "2015-10-31",
"properties": {
"sku": {
"name" : "Basic"
}
},
"location": "[parameters('location')]",
"resources": [
{
"type": "providers/diagnosticSettings"
Enabling all sort of logs in the diagnostic settings ..
This works fine.
But the problem I am facing right now is that the sku is set to basic right here. But I can't be sure that is the case to every single automationaccount I retrieve with the get-AzAutomationAccount command.
I have searched to get the plan value from the get-AzAutomationAccount and save this inside the ARM template but seems to be empty.
Is there any other way to retrieve the sku of each Azure Automation account.
ALSO the SKU object normally is not required if I read the official doc of Microsoft. But whenever I delete the sku object or leave it empty the deployment fails.
Is there anyone who know how to fix this ?
The command Get-AzAutomationAccount will not return the sku property, it just returns the Plan.
If you want to get the sku, you could use the command as below.
$sku = (Get-AzResource -ResourceGroupName "<resource group name>" -ResourceType Microsoft.Automation/automationAccounts -ResourceName "<automation account name>").properties.sku
$sku | ConvertTo-Json

Add a subnet to a vnet in another resource group

I need to add a subnet to a VNET in another resource group. I have an arm template (below) which adds a subnet to an existing resource group and it works okay but I need this subnet to be added to a VNET in another resource group.
example - there are 2 resource groups
Resource Group A - Contains the VNET
Resource Group B - VM deployed here but needs to connect to VNET in Resource Group A
When I deploy the template which created the VM to Resource Group B, i need to reference resource group A from within this ARM template, how can I do this?
I am deploying via Visual Studio at the moment so I am using right click then Deploy to and selecting the resource group where the VM is being deployed to eg Resource Group B. The below code works but it deploys to the wrong resource group, it should add the subnet to Resource group where the VNET is but adds it to the resource group the VM is being deployed to!
"vnetID": "[resourceId(parameters('ResourceGroupName'),'Microsoft.Network/virtualNetworks',parameters('existingVNETName'))]"
"apiVersion": "2015-06-15",
"type": "Microsoft.Network/virtualNetworks/subnets",
"name": "[concat(parameters('existingVNETName'), '/', parameters('newSubnetName'))]",
"location": "[resourceGroup().location]",
"properties": {
"addressPrefix": "[parameters('newSubnetAddressPrefix')]"
This isn't possible. The subnets in a VNET are properties of that VNET, so you cannot create a subnet in a different resource group.
You can however add users to a certain subnet, so only a certain user could only add machines to his " allowed" subnets.
It is not possible to add a Subnet to a VNET in another resource group, because a Subnet is not a top level resource in Azure. All Subnets within a virtual network always role up to the virtual network resource in your resource group.
Actually it can be done. Using Azure resource explorer I got the id of the subnet I wanted to add the virtual machine to. Then in the resource which builds the NIC (usually the "type": "Microsoft.Network/networkInterfaces"),under the subnet properties you can paste this id. Im working on parametizing this but worked. Azure resource explorer is the tool I used
"name": "NIC",
"type": "Microsoft.Network/networkInterfaces",
"location": "[resourceGroup().location]",
"apiVersion": "2016-03-30",
"dependsOn": [
],
"tags": {
"displayName": "[variables('NicName')]"
},
"properties": {
"ipConfigurations": [
{
"name": "ipconfig1",
"properties": {
"privateIPAddress": "[parameters('primaryPrivateIPAddress')]",
"privateIPAllocationMethod": "Static",
"subnet": {
"id": ""/subscriptions/abcd123456789/resourceGroups/ResourceGroupA/providers/Microsoft.Network/virtualNetworks/ResourceGroupVirtualNetwork/subnets/newsubnet""
}

Resources