Right method to create CustomScript in Azure JSON template - json

I am trying add a custom PowerShell script to an ARM template.
I have tried it in many different ways and always get an error, wrong URI, couldn't find file, or something similar. Could you guys please correct me?
So in variables I have the path to the file:
"CustomScriptScript": https://raw.githubusercontent.com/starwinddeploy/azure-sw-cluster/master/scripts/CustomScript.ps1
In the resource section I have a VM with another resource:
{
"type": "Microsoft.Compute/virtualMachines",
"resources": [
{
"name": "CustomScript",
"type": "extensions",
"location": "[parameters('location')]",
"apiVersion": "2015-06-15",
"dependsOn": [
"[concat('Microsoft.Compute/virtualMachines/', concat(variables('vmName'), copyindex(1)))]"
],
"tags": {
"displayName": "CustomScript"
},
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"typeHandlerVersion": "1.4",
"autoUpgradeMinorVersion": true,
"settings": {
"fileUris": [
"[concat(variables('CustomScriptScript'))]"
],
"commandToExecute": "[concat('powershell -ExecutionPolicy Unrestricted -File ', variables('CustomScriptScript'))]"
}
}
}
]
}

I see a couple problems:
Change "type": "extensions" to "type": "Microsoft.Compute/virtualMachines/extensions"
Variable CustomScriptScript should be the URI of the ps1 file that you want to execute. It doesn't make sense to try and use it as the URI, and then in commandToExecute use it as the name of the script. You would need two different variables.
There may be other mistakes in your template. I would recommend starting with this template: https://github.com/Azure/azure-quickstart-templates/blob/master/201-vm-custom-script-windows/azuredeploy.json
Once you have that working, modify it to fit your needs.

Related

How do I properly write an ARM template for topic and subscription

I have the following code:
// Create event topics and listeners
{
"comments": "Service Bus Topic - clusterprocessingcompletedevent",
"type": "Microsoft.ServiceBus/namespaces/topics",
"name": "[concat(variables('resource_names').service_bus_namespaces.core, '/clusterprocessingcompletedevent')]",
"apiVersion": "2017-04-01",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.ServiceBus/namespaces', variables('resource_names').service_bus_namespaces.core)]"
],
"resources": [
{
"comments": "Service Bus Topic Subscription - notification.clusterprocessingcompletedevent",
"apiVersion": "2017-04-01",
"name": "[concat(variables('resource_names').service_bus_namespaces.core, '/clusterprocessingcompletedevent', '/notification.clusterprocessingcompletedevent')]",
"type": "Microsoft.ServiceBus/namespaces/topics/subscriptions",
"dependsOn": [
"[resourceId('Microsoft.ServiceBus/namespaces/topics', variables('resource_names').service_bus_namespaces.core, '/clusterprocessingcompletedevent')]"
]
}
]
}
When trying to use it, I get this error:
Unable to evaluate template language function 'resourceId': function
requires exactly one multi-segmented argument which must be resource
type including resource provider namespace
How do I fix it?
I think this would be the issue:
"dependsOn": [
"[resourceId('Microsoft.ServiceBus/namespaces/topics', variables('resource_names').service_bus_namespaces.core, 'clusterprocessingcompletedevent')]"
]
so you have an extra / in the topic name. the same should apply to this: variables('resource_names').service_bus_namespaces.core. It should be a name of the namespace, without / in it.

How to create new alerts in azure for all webapps at same time

I want to create new alerts(High CPU,RAM) for all AppServicePlans in a given subscription. I could not find Powershell commands to create new alerts. Is there a way we can create these alerts for all appserviceplans with a single script? May be using ARM template?
Sorry for pasting a direct answer, but I cannot yet comment. You get the error because in the documentation for Add-AzMetricAlertruleV2 it states: "$act is the output of New-AzActionGroup cmdlet". Meaning you need to use for example:
$act = New-AzActionGroup -ActionGroupId "testActionGroup"
After that you need to add it in the parameter -ActionGroup $act for it to work.
If you look at Resource Explorer and navigate to a manually created (near-realtime) alert, you should see the "critera" object defined like below. Here is a full example of a resource that seems to be working. Create some variables for each of your values:
{
"type": "Microsoft.Insights/metricAlerts",
"apiVersion": "2018-03-01",
"name": "[variables('alertName')]",
"location": "global",
"dependsOn": [],
"tags": {
"[concat('hidden-link:', variables('applicationInsightsResourceId'))]": "Resource",
"[concat('hidden-link:', variables('webtestResourceId'))]": "Resource"
},
"properties": {
"description": "[concat('Alert for ', parameters('availibilityTestName'))]",
"severity": 4,
"enabled": true,
"scopes": [
"[variables('webtestResourceId')]",
"[variables('applicationInsightsResourceId')]"
],
"evaluationFrequency": "PT5M",
"windowSize": "PT15M",
"criteria": {
"odata.type": "Microsoft.Azure.Monitor.WebtestLocationAvailabilityCriteria",
"webTestId": "[variables('webtestResourceId')]",
"componentId": "[variables('applicationInsightsResourceId')]",
"failedLocationCount": 3
},
"actions": [
{
"actionGroupId": "[resourceId('microsoft.insights/actiongroups', 'webhook')]",
"webHookProperties": {
// Some properties to send to webhook
}
}
]
}
}

When i deploy my Azure ARM Template it creates a storage, not an alert

I created a Azure Template for an alert, because i want to upload the script (.json) with the new microservice the same time. But if I deploy this .json file it creates a new storage, not an alert. I used the Powershell commands New-AzureRmResourceGroupDeployment -Name ExampleDeployment -ResourceGroupName ExampleResourceGroup -TemplateFile c:\MyTemplates\storage.json -storageAccountType Standard_GRS. In my template i need to define the parameter kind, which is only acceptable with a value of Storage or Blobstorage, but i want non of these two. So how can i create an alert by using a script .json file and does anybody have a template, because MS isn't providing the correct one.
EDIT: Here is the .json file:
{
"$schema":
"http://schema.management.azure.com/schemas/2015-01-
01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"name": "[concat('storage', uniqueString(resourceGroup().id))]",
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2016-01-01",
"sku": {
"name": "Standard_LRS"
},
"kind": "Storage",
"id":
"/subscriptions/subscriptionID/resourceGroups/resourceGroupName/providers/Microsoft.Storage/storageAccounts/storageName",
"location": "westeurope",
"properties": {
"name": "tryAgain",
"description": null,
"isEnabled": true,
"condition": {
"$type":
"Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.ThresholdRuleCondition, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type":
"Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
"dataSource": {
"$type":
"Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleMetricDataSource, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type":
"Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
"resourceUri":
"/subscriptions/subscriptionID/resourcegroups/resourceGroupName/providers/microsoft.web/sites/name",
"resourceLocation": null,
"metricNamespace": null,
"metricName": "AverageMemoryWorkingSet",
"legacyResourceId": null
},
"operator": "GreaterThanOrEqual",
"threshold": 120000000,
"windowSize": "PT10M",
"timeAggregation": "Average"
},
"actions": [
{
"$type":
"Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleWebhookAction, Microsoft.WindowsAzure.Management.Mon.Client",
"odata.type":
"Microsoft.Azure.Management.Insights.Models.RuleWebhookAction",
"serviceUri":
"Logic-app URL",
"properties": {
"$type":
"Microsoft.WindowsAzure.Management.Common.Storage.CasePreservedDictionary`1[[System.String, mscorlib]], Microsoft.WindowsAzure.Management.Common.Storage",
"logicAppResourceId":
"/subscriptions/subscriptionID/resourceGroups/Default-Storage-WestEurope/providers/Microsoft.Logic/workflows/Microsoft-Teams-Notifier"
}
}
]
}
}
]
}
Please refer to the following reference for creating a metric alert via Azure Resource Manager template. If you want to create a single ARM template which creates a storage account and then a metric alert to monitor the created storage account, you should make sure you have a dependsOn so that the alert rule is only created after the storage account. The following document references the newer metric alerts, as opposed to the classic metric alerts.
https://learn.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-create-metric-alerts-with-templates

How to check if name already exists? Azure Ressource Manager Template

is it possible to check, in an ARM Template, if the name for my Virtual Machine already exists?
I am developing a Solution Template for the Azure Marketplace. Maybe it is possible to set a paramter in the UiDefinition uniqe?
The goal is to reproduce this green Hook
A couple notes...
VM Names only need to be unique within a resourceGroup, not within the subscription
Solution Templates must be deployed to empty resourceGroups, so collisions with existing resources aren't possible
For solution templates the preference is that you simply name the VMs for the user, rather than asking - use something that is appropriate for the workload (e.g. jumpbox) - not all solutions do this but we're trying to improve that experience
Given that it's not likely we'll ever build a control that checks for naming collisions on resources without globally unique constraints.
That help?
This looks impossible, according to the documentation.
There are no validation scenarious.
I assume that you should be using the Microsoft.Common.TextBox UI element in your createUiDefinition.json.
I have tried to reproduce a green check by creating a simple createUiDefinition.json as below with a Microsoft.Common.TextBox UI element as shown below.
{
"$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json",
"handler": "Microsoft.Compute.MultiVm",
"version": "0.1.2-preview",
"parameters": {
"basics": [
{
"name": "textBoxA",
"type": "Microsoft.Common.TextBox",
"label": "VM Name",
"defaultValue": "",
"toolTip": "Please enter a VM name",
"constraints": {
"required": true
},
"visible": true
}
],
"steps": [],
"outputs": {}
}
}
I am able to reproduce the green check beside the VM Name textbox as shown below:
However, this green check DOES NOT imply the VM Name is Available.
This is because based on my testing, even if I use an existing VM Name in the same subscription, it is still showing the green check.
Based on the official documented constraints that are supported by the Microsoft.Common.TextBox UI element, it DOES NOT VALIDATE Name Availability.
Hope this helps!
While bmoore's point is correct that it's unlikely you would ever need this for a VM (nor is there an API for it), there are other compute resources that do have global naming requirements.
As of 2022 this concept is possible now with the use of the ArmApiControl UI element. It allows you to call ARM apis as part of validation in the createUiDefinition.json. Here is an example using the check name API for an Azure App service.
{
"$schema": "https://schema.management.azure.com/schemas/0.1.2-preview/CreateUIDefinition.MultiVm.json#",
"handler": "Microsoft.Azure.CreateUIDef",
"version": "0.1.2-preview",
"parameters": {
"basics": [
{}
],
"steps": [
{
"name": "domain",
"label": "Domain Names",
"elements": [
{
"name": "domainInfo",
"type": "Microsoft.Common.InfoBox",
"visible": true,
"options": {
"icon": "Info",
"text": "Pick the domain name that you want to use for your app."
}
},
{
"name": "appServiceAvailabilityApi",
"type": "Microsoft.Solutions.ArmApiControl",
"request": {
"method": "POST",
"path": "[concat(subscription().id, '/providers/Microsoft.Web/checknameavailability?api-version=2021-02-01')]",
"body": "[parse(concat('{\"name\":\"', concat('', steps('domain').domainName), '\", \"type\": \"Microsoft.Web/sites\"}'))]"
}
},
{
"name": "domainName",
"type": "Microsoft.Common.TextBox",
"label": "Domain Name Word",
"toolTip": "The name of your app service",
"placeholder": "yourcompanyname",
"constraints": {
"validations": [
{
"regex": "^[a-zA-Z0-9]{4,30}$",
"message": "Alphanumeric, between 4 and 30 characters."
},
{
"isValid": "[not(equals(steps('domain').appServiceAvailabilityApi.nameAvailable, false))]",
"message": "[concat('Error with the url: ', steps('domain').domainName, '. Reason: ', steps('domain').appServiceAvailabilityApi.reason)]"
},
{
"isValid": "[greater(length(steps('domain').domainName), 4)]",
"message": "The unique domain suffix should be longer than 4 characters."
},
{
"isValid": "[less(length(steps('domain').domainName), 30)]",
"message": "The unique domain suffix should be shorter than 30 characters."
}
]
}
},
{
"name": "section1",
"type": "Microsoft.Common.Section",
"label": "URLs to be created:",
"elements": [
{
"name": "domainExamplePortal",
"type": "Microsoft.Common.TextBlock",
"visible": true,
"options": {
"text": "[concat('https://', steps('domain').domainName, '.azurewebsites.net - The main app service URL')]"
}
}
],
"visible": true
}
]
}
],
"outputs": {
"desiredDomainName": "[steps('domain').domainName]"
}
}
}
You can copy the above code and test it in the createUiDefinition.json sandbox azure provides.

ARM Error: The Template Resource is not found using resource(), copyIndex()

I'm trying to conditionally provide resource property values through translation of runtime resource properties within a copyIndex loop..
Upon deploying the following ARM template, I receive the error:
Unable to process template language expressions for resource '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vm-name}/extensions/Microsoft.EnterpriseCloud.Monitoring' at line '30' and column '10'. 'The template resource '/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Compute/virtualMachines/{vm-name}' is not found.' (Code: InvalidTemplate)
"type": "[variables('extensionType')[reference(concat('Microsoft.Compute/virtualMachines/', parameters('virtualMachines')[copyIndex()].name)).storageProfile.osDisk.osType]]",
However, the VM exists with the ID it provides, so it doesn't make sense that the engine cannot find it. If I hard-code the Extension Type, there are no errors and the Extension is installed on the VM with the same ID.
Unfortunately, I don't know if this is a bug within ARM or if I'm just doing something wrong..
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspaceResourceId": { "type": "string" },
"virtualMachines": { "type": "array" }
},
"variables": {
"extensionType": {
"Windows": "MicrosoftMonitoringAgent",
"Linux": "OmsAgentForLinux"
}
},
"resources": [
{
"copy": {
"name": "VMMonitoringExtensionsCopy",
"count": "[length(parameters('virtualMachines'))]"
},
"type": "Microsoft.Compute/virtualMachines/extensions",
"apiVersion": "2015-05-01-preview",
"location": "[parameters('virtualMachines')[copyIndex()].location]",
"name": "[concat(parameters('virtualMachines')[copyIndex()].name, '/Microsoft.EnterpriseCloud.Monitoring')]",
"properties": {
"publisher": "Microsoft.EnterpriseCloud.Monitoring",
"type": "[variables('extensionType')[reference(concat('Microsoft.Compute/virtualMachines/', parameters('virtualMachines')[copyIndex()].name)).storageProfile.osDisk.osType]]",
"typeHandlerVersion": "1.0",
"autoUpgradeMinorVersion": true,
"settings": {
"workspaceId": "[reference(parameters('workspaceResourceId'), '2015-11-01-preview').customerId]"
},
"protectedSettings": {
"workspaceKey": "[listKeys(parameters('workspaceResourceId'), '2015-11-01-preview').primarySharedKey]"
}
}
}
]
}
The object array being passed in for virtualMachines looks like this:
[
{ "name": "vm-name", "location": "azure-region" }
]
A couple things you can try:
1) Assuming the VM is not defined in the same template try using the "full" resourceId in the reference function. See the last example in this doc:
https://azure.microsoft.com/en-us/documentation/articles/resource-group-template-functions/#reference - it seems like the error already knows the full resourceId, but it's worth trying
2) the other thought is that the reference function is evaluated at runtime and the resource provider doesn't like the expression but that's a swag.
I will do some more poking and see if we can't nail this down.