├── requirements.psd1 ├── StartVMOnTimer ├── function.json └── run.ps1 ├── StopVMOnTimer ├── function.json └── run.ps1 ├── host.json ├── profile.ps1 ├── LICENSE ├── README.md └── azuredeploy.json /requirements.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | Az = '1.*' 3 | } 4 | -------------------------------------------------------------------------------- /StartVMOnTimer/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "disabled": false, 3 | "bindings": [ 4 | { 5 | "name": "Timer", 6 | "type": "timerTrigger", 7 | "direction": "in", 8 | "schedule": "0 0 8 * * *" 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /StopVMOnTimer/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "disabled": false, 3 | "bindings": [ 4 | { 5 | "name": "Timer", 6 | "type": "timerTrigger", 7 | "direction": "in", 8 | "schedule": "0 0 20 * * *" 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "managedDependency": { 4 | "enabled": true 5 | }, 6 | "logging": { 7 | "logLevel": { 8 | "default": "Trace" 9 | }, 10 | "fileLoggingMode": "always" 11 | }, 12 | "functionTimeout": "00:10:00" 13 | } -------------------------------------------------------------------------------- /profile.ps1: -------------------------------------------------------------------------------- 1 | # Azure Functions profile.ps1 2 | # 3 | # This profile.ps1 will get executed every "cold start" of your Function App. 4 | # "cold start" occurs when: 5 | # 6 | # * A Function App starts up for the very first time 7 | # * A Function App starts up after being de-allocated due to inactivity 8 | # 9 | # You can define helper functions, run commands, or specify environment variables 10 | # NOTE: any variables defined that are not environment variables will get reset after the first execution 11 | 12 | # Authenticate with Azure PowerShell using MSI. 13 | # Remove this if you are not planning on using MSI or Azure PowerShell. 14 | if ($env:MSI_SECRET -and (Get-Module -ListAvailable Az.Accounts)) { 15 | Connect-AzAccount -Identity 16 | } 17 | 18 | # Uncomment the next line to enable legacy AzureRm alias in Azure PowerShell. 19 | # Enable-AzureRmAlias 20 | 21 | # You can also define functions or aliases that can be referenced in any of your PowerShell functions. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Eamon O'Reilly 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /StopVMOnTimer/run.ps1: -------------------------------------------------------------------------------- 1 | # Input bindings are passed in via param block. 2 | param($Timer) 3 | 4 | # Specify the VMs that you want to stop. Modify or comment out below based on which VMs to check. 5 | $VMResourceGroupName = "Contoso" 6 | #$VMName = "ContosoVM1" 7 | #$TagName = "AutomaticallyStop" 8 | 9 | # Stop on error 10 | $ErrorActionPreference = 'stop' 11 | 12 | # Check if managed identity has been enabled and granted access to a subscription, resource group, or resource 13 | $AzContext = Get-AzContext -ErrorAction SilentlyContinue 14 | if (-not $AzContext.Subscription.Id) 15 | { 16 | Throw ("Managed identity is not enabled for this app or it has not been granted access to any Azure resources. Please see https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity for additional details.") 17 | } 18 | 19 | try 20 | { 21 | # Get a single vm, vms in a resource group, or all vms in the subscription 22 | if ($null -ne $VMResourceGroupName -and $null -ne $VMName) 23 | { 24 | Write-Information ("Getting VM in resource group " + $VMResourceGroupName + " and VMName " + $VMName) 25 | $VMs = Get-AzVM -ResourceGroupName $VMResourceGroupName -Name $VMName 26 | } 27 | elseif ($null -ne $VMResourceGroupName) 28 | { 29 | Write-Information("Getting all VMs in resource group " + $VMResourceGroupName) 30 | $VMs = Get-AzVM -ResourceGroupName $VMResourceGroupName 31 | } 32 | else 33 | { 34 | Write-Information ("Getting all VMs in the subscription") 35 | $VMs = Get-AzVM 36 | } 37 | 38 | # Check if VM has the specified tag on it and filter to those. 39 | If ($null -ne $TagName) 40 | { 41 | $VMs = $VMs | Where-Object {$_.Tags.Keys -eq $TagName} 42 | } 43 | 44 | # Stop the VM if it is running 45 | $ProcessedVMs = @() 46 | 47 | foreach ($VirtualMachine in $VMs) 48 | { 49 | $VM = Get-AzVM -ResourceGroupName $VirtualMachine.ResourceGroupName -Name $VirtualMachine.Name -Status 50 | if ($VM.Statuses.Code[1] -eq 'PowerState/running') 51 | { 52 | Write-Information ("Stopping VM " + $VirtualMachine.Id) 53 | $ProcessedVMs += $VirtualMachine.Id 54 | Stop-AzVM -Id $VirtualMachine.Id -Force -AsJob | Write-Information 55 | } 56 | } 57 | # Sleep here a few seconds to make sure that the command gets processed before the script ends 58 | if ($ProcessedVMs.Count -gt 0) 59 | { 60 | Start-Sleep 10 61 | } 62 | } 63 | catch 64 | { 65 | throw $_.Exception.Message 66 | } 67 | -------------------------------------------------------------------------------- /StartVMOnTimer/run.ps1: -------------------------------------------------------------------------------- 1 | # Input bindings are passed in via param block. 2 | param($Timer) 3 | 4 | # Specify the VMs that you want to start. Modify or comment out below based on which VMs to check. 5 | $VMResourceGroupName = "Contoso" 6 | #$VMName = "ContosoVM1" 7 | #$TagName = "AutomaticallyStart" 8 | 9 | # Stop on error 10 | $ErrorActionPreference = 'stop' 11 | 12 | # Check if managed identity has been enabled and granted access to a subscription, resource group, or resource 13 | $AzContext = Get-AzContext -ErrorAction SilentlyContinue 14 | if (-not $AzContext.Subscription.Id) 15 | { 16 | Throw ("Managed identity is not enabled for this app or it has not been granted access to any Azure resources. Please see https://docs.microsoft.com/en-us/azure/app-service/overview-managed-identity for additional details.") 17 | } 18 | 19 | try 20 | { 21 | # Get a single vm, vms in a resource group, or all vms in the subscription 22 | if ($null -ne $VMResourceGroupName -and $null -ne $VMName) 23 | { 24 | Write-Information ("Getting VM in resource group " + $VMResourceGroupName + " and VMName " + $VMName) 25 | $VMs = Get-AzVM -ResourceGroupName $VMResourceGroupName -Name $VMName 26 | } 27 | elseif ($null -ne $VMResourceGroupName) 28 | { 29 | Write-Information("Getting all VMs in resource group " + $VMResourceGroupName) 30 | $VMs = Get-AzVM -ResourceGroupName $VMResourceGroupName 31 | } 32 | else 33 | { 34 | Write-Information ("Getting all VMs in the subscription") 35 | $VMs = Get-AzVM 36 | } 37 | 38 | # Check if VM has the specified tag on it and filter to those. 39 | If ($null -ne $TagName) 40 | { 41 | $VMs = $VMs | Where-Object {$_.Tags.Keys -eq $TagName} 42 | } 43 | 44 | # Start the VM if it is deallocated 45 | $ProcessedVMs = @() 46 | 47 | foreach ($VirtualMachine in $VMs) 48 | { 49 | $VM = Get-AzVM -ResourceGroupName $VirtualMachine.ResourceGroupName -Name $VirtualMachine.Name -Status 50 | if ($VM.Statuses.Code[1] -eq 'PowerState/deallocated') 51 | { 52 | Write-Information ("Starting VM " + $VirtualMachine.Id) 53 | $ProcessedVMs += $VirtualMachine.Id 54 | Start-AzVM -Id $VirtualMachine.Id -AsJob | Write-Information 55 | } 56 | } 57 | # Sleep here a few seconds to make sure that the command gets processed before the script ends 58 | if ($ProcessedVMs.Count -gt 0) 59 | { 60 | Start-Sleep 10 61 | } 62 | } 63 | catch 64 | { 65 | throw $_.Exception.Message 66 | } 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3a%2f%2fraw.githubusercontent.com%2feamonoreilly%2fStartStopPowerShellFunction%2fmaster%2fazuredeploy.json) 2 | 3 | 4 | 5 | 6 | # Sample to start / stop VMs on a schedule 7 | 8 | Create an Azure function application and deploy functions that starts or stops virtual machines in the specified resource group, subscription, or by tag on a schedule. 9 | 10 | ## Prerequisites 11 | 12 | Before running this sample, you must have the following: 13 | 14 | + Install [Azure Core Tools version 2.x](https://docs.microsoft.com/en-us/azure/azure-functions/functions-run-local) 15 | 16 | + Install the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) 17 | 18 | ### Create a new resource group and function application on Azure 19 | 20 | Run the following PowerShell command and specify the value for the function application name in the TemplateParameterObject hashtable. 21 | 22 | ```powershell 23 | New-AzResourceGroup -Name -Location 24 | 25 | New-AzResourceGroupDeployment -ResourceGroupName -TemplateParameterObject @{"functionAppName" = ""} -TemplateUri "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-functions-managed-identity/azuredeploy.json" -verbose 26 | ``` 27 | 28 | This should create a new resource group with a function application and a managed service identity enabled. The id of the service principal for the MSI should be returned as an output from the deployment. 29 | 30 | Example: principalId String cac1fa06-2ad8-437d-99f6-b75edaae2921 31 | 32 | ### Grant the managed service identity contributor access to the subscription or resource group so it can perform actions 33 | 34 | The below command sets the access at the subscription level. 35 | 36 | ```powershell 37 | $Context = Get-AzContext 38 | New-AzRoleAssignment -ObjectId -RoleDefinitionName Contributor -Scope "/subscriptions/$($Context.Subscription)" 39 | ``` 40 | 41 | ### Clone repository or download files to local machine 42 | 43 | + Download the repository files or clone to local machine. 44 | 45 | + Change to the PowerShell/StartStopVMOnTimer directory. 46 | 47 | ### Get the local.settings.json values from the function application created in Azure 48 | 49 | ```powershell 50 | func azure functionapp fetch-app-settings 51 | ``` 52 | 53 | This should create a local.settings.json file in the StartStopVMOnTimer directory beside the host.json with the settings from the Azure function app. 54 | 55 | ### Test the functions locally 56 | 57 | Start the function with the following command 58 | 59 | ```powershell 60 | func start 61 | ``` 62 | 63 | You can then call a trigger function by performing a post against the function on the admin api. Open up another Powershell console session and run: 64 | 65 | ```powershell 66 | Invoke-RestMethod "http://localhost:7071/admin/functions/StartVMOnTimer" -Method post -Body '{}' -ContentType "application/json" 67 | ``` 68 | 69 | Modify the values for each of the below variables in run.ps1 as needed. 70 | 71 | ```powershell 72 | # Specify the VMs that you want to stop. Modify or comment out below based on which VMs to check. 73 | $VMResourceGroupName = "Contoso" 74 | #$VMName = "ContosoVM1" 75 | #$TagName = "AutomaticallyStart" 76 | ``` 77 | 78 | Modify the start and stop time in the function.json file. They are currently set to 8am and 8pm UTC. You can change the timezone by modifying the application setting WEBSITE_TIME_ZONE. You can also pass in a parameter 'timezone' to the above [ARM template](https://raw.githubusercontent.com/eamonoreilly/AzureFunctions/master/PowerShell/ConsumptionAppWithTemplate/azuredeploy.json) that was used to create the function application if you want a different timezone so that daylight savings time will be honored. 79 | 80 | ```json 81 | { 82 | "disabled": false, 83 | "bindings": [ 84 | { 85 | "name": "Timer", 86 | "type": "timerTrigger", 87 | "direction": "in", 88 | "schedule": "0 0 20 * * *" 89 | } 90 | ] 91 | } 92 | ``` 93 | 94 | ## Publish the functions to the function application in Azure 95 | 96 | ```powershell 97 | func azure functionapp publish 98 | ``` -------------------------------------------------------------------------------- /azuredeploy.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", 3 | "contentVersion": "1.0.0.0", 4 | "parameters": { 5 | "functionAppName": { 6 | "type": "string", 7 | "defaultValue": "[uniqueString(resourceGroup().id)]", 8 | "metadata": { 9 | "description": "Specify the name of the function application" 10 | } 11 | }, 12 | "location": { 13 | "type": "string", 14 | "defaultValue": "[resourceGroup().location]", 15 | "metadata": { 16 | "description": "Specify the location for the function application resources" 17 | } 18 | }, 19 | "ApplicationInsightsLocation": { 20 | "type": "string", 21 | "defaultValue": "West Europe", 22 | "allowedValues": [ 23 | "East US", 24 | "South Central US", 25 | "North Europe", 26 | "West Europe", 27 | "Southeast Asia", 28 | "West US 2", 29 | "Central India", 30 | "Canada Central", 31 | "UK South" 32 | ], 33 | "metadata": { 34 | "description": "Specify the region for Application Insights data" 35 | } 36 | }, 37 | "runtimeStack": { 38 | "type": "string", 39 | "defaultValue": "powershell", 40 | "allowedValues": [ 41 | "powershell", 42 | "dotnet", 43 | "node", 44 | "java" 45 | ], 46 | "metadata": { 47 | "description": "Pick the language runtime that you want enabled" 48 | } 49 | }, 50 | "timezone": { 51 | "type": "string", 52 | "defaultValue": "UTC", 53 | "allowedValues": [ 54 | "Dateline Standard Time", 55 | "UTC-11", 56 | "Aleutian Standard Time", 57 | "Hawaiian Standard Time", 58 | "Marquesas Standard Time", 59 | "Alaskan Standard Time", 60 | "UTC-09", 61 | "Pacific Standard Time (Mexico)", 62 | "UTC-08", 63 | "Pacific Standard Time", 64 | "US Mountain Standard Time", 65 | "Mountain Standard Time (Mexico)", 66 | "Mountain Standard Time", 67 | "Central America Standard Time", 68 | "Central Standard Time", 69 | "Easter Island Standard Time", 70 | "Central Standard Time (Mexico)", 71 | "Canada Central Standard Time", 72 | "SA Pacific Standard Time", 73 | "Eastern Standard Time (Mexico)", 74 | "Eastern Standard Time", 75 | "Haiti Standard Time", 76 | "Cuba Standard Time", 77 | "US Eastern Standard Time", 78 | "Turks And Caicos Standard Time", 79 | "Paraguay Standard Time", 80 | "Atlantic Standard Time", 81 | "Venezuela Standard Time", 82 | "Central Brazilian Standard Time", 83 | "SA Western Standard Time", 84 | "Pacific SA Standard Time", 85 | "Newfoundland Standard Time", 86 | "Tocantins Standard Time", 87 | "E. South America Standard Time", 88 | "SA Eastern Standard Time", 89 | "Argentina Standard Time", 90 | "Greenland Standard Time", 91 | "Montevideo Standard Time", 92 | "Magallanes Standard Time", 93 | "Saint Pierre Standard Time", 94 | "Bahia Standard Time", 95 | "UTC-02", 96 | "Mid-Atlantic Standard Time", 97 | "Azores Standard Time", 98 | "Cape Verde Standard Time", 99 | "UTC", 100 | "Morocco Standard Time", 101 | "GMT Standard Time", 102 | "Greenwich Standard Time", 103 | "W. Europe Standard Time", 104 | "Central Europe Standard Time", 105 | "Romance Standard Time", 106 | "Sao Tome Standard Time", 107 | "Central European Standard Time", 108 | "W. Central Africa Standard Time", 109 | "Jordan Standard Time", 110 | "GTB Standard Time", 111 | "Middle East Standard Time", 112 | "Egypt Standard Time", 113 | "E. Europe Standard Time", 114 | "Syria Standard Time", 115 | "West Bank Standard Time", 116 | "South Africa Standard Time", 117 | "FLE Standard Time", 118 | "Israel Standard Time", 119 | "Kaliningrad Standard Time", 120 | "Sudan Standard Time", 121 | "Libya Standard Time", 122 | "Namibia Standard Time", 123 | "Arabic Standard Time", 124 | "Turkey Standard Time", 125 | "Arab Standard Time", 126 | "Belarus Standard Time", 127 | "Russian Standard Time", 128 | "E. Africa Standard Time", 129 | "Iran Standard Time", 130 | "Arabian Standard Time", 131 | "Astrakhan Standard Time", 132 | "Azerbaijan Standard Time", 133 | "Russia Time Zone 3", 134 | "Mauritius Standard Time", 135 | "Saratov Standard Time", 136 | "Georgian Standard Time", 137 | "Caucasus Standard Time", 138 | "Afghanistan Standard Time", 139 | "West Asia Standard Time", 140 | "Ekaterinburg Standard Time", 141 | "Pakistan Standard Time", 142 | "India Standard Time", 143 | "Sri Lanka Standard Time", 144 | "Nepal Standard Time", 145 | "Central Asia Standard Time", 146 | "Bangladesh Standard Time", 147 | "Omsk Standard Time", 148 | "Myanmar Standard Time", 149 | "SE Asia Standard Time", 150 | "Altai Standard Time", 151 | "W. Mongolia Standard Time", 152 | "North Asia Standard Time", 153 | "N. Central Asia Standard Time", 154 | "Tomsk Standard Time", 155 | "China Standard Time", 156 | "North Asia East Standard Time", 157 | "Singapore Standard Time", 158 | "W. Australia Standard Time", 159 | "Taipei Standard Time", 160 | "Ulaanbaatar Standard Time", 161 | "Aus Central W. Standard Time", 162 | "Transbaikal Standard Time", 163 | "Tokyo Standard Time", 164 | "North Korea Standard Time", 165 | "Korea Standard Time", 166 | "Yakutsk Standard Time", 167 | "Cen. Australia Standard Time", 168 | "AUS Central Standard Time", 169 | "E. Australia Standard Time", 170 | "AUS Eastern Standard Time", 171 | "West Pacific Standard Time", 172 | "Tasmania Standard Time", 173 | "Vladivostok Standard Time", 174 | "Lord Howe Standard Time", 175 | "Bougainville Standard Time", 176 | "Russia Time Zone 10", 177 | "Magadan Standard Time", 178 | "Norfolk Standard Time", 179 | "Sakhalin Standard Time", 180 | "Central Pacific Standard Time", 181 | "Russia Time Zone 11", 182 | "New Zealand Standard Time", 183 | "UTC+12", 184 | "Fiji Standard Time", 185 | "Kamchatka Standard Time", 186 | "Chatham Islands Standard Time", 187 | "UTC+13", 188 | "Tonga Standard Time", 189 | "Samoa Standard Time", 190 | "Line Islands Standard Time" 191 | ], 192 | "metadata": { 193 | "description": "Pick the timezone to use for the function" 194 | } 195 | } 196 | }, 197 | "variables": { 198 | "hostingPlanName": "[parameters('functionAppName')]", 199 | "storageAccountName": "[concat('storage', uniquestring(resourceGroup().id))]", 200 | "repoUrl": "https://github.com/eamonoreilly/StartStopPowerShellFunction", 201 | "branch": "master" 202 | }, 203 | "resources": [ 204 | { 205 | "name": "[parameters('functionAppName')]", 206 | "type": "Microsoft.Web/sites", 207 | "apiVersion": "2018-02-01", 208 | "location": "[parameters('location')]", 209 | "kind": "functionapp", 210 | "dependsOn": [ 211 | "[resourceId('Microsoft.Web/serverfarms/', variables('hostingPlanName'))]", 212 | "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]", 213 | "[resourceId('microsoft.insights/components/', parameters('functionAppName'))]" 214 | ], 215 | "identity": { 216 | "type": "SystemAssigned" 217 | }, 218 | "properties": { 219 | "siteConfig": { 220 | "appSettings": [ 221 | { 222 | "name": "FUNCTIONS_WORKER_RUNTIME", 223 | "value": "[parameters('runtimeStack')]" 224 | }, 225 | { 226 | "name": "AzureWebJobsStorage", 227 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',variables('storageAccountName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2017-06-01').keys[0].value)]" 228 | }, 229 | { 230 | "name": "FUNCTIONS_EXTENSION_VERSION", 231 | "value": "~2" 232 | }, 233 | { 234 | "name": "APPINSIGHTS_INSTRUMENTATIONKEY", 235 | "value": "[reference(resourceId('microsoft.insights/components/', parameters('functionAppName')), '2018-05-01-preview').InstrumentationKey]" 236 | }, 237 | { 238 | "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", 239 | "value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')),'2017-06-01').keys[0].value)]" 240 | }, 241 | { 242 | "name": "WEBSITE_CONTENTSHARE", 243 | "value": "[toLower(parameters('functionAppName'))]" 244 | }, 245 | { 246 | "name": "WEBSITE_TIME_ZONE", 247 | "value": "[parameters('timezone')]" 248 | } 249 | ] 250 | }, 251 | "name": "[parameters('functionAppName')]", 252 | "clientAffinityEnabled": false, 253 | "serverFarmId": "[resourceId('Microsoft.Web/serverfarms/', variables('hostingPlanName'))]" 254 | }, 255 | "resources": [ 256 | { 257 | "apiVersion": "2015-08-01", 258 | "name": "web", 259 | "type": "sourcecontrols", 260 | "dependsOn": [ 261 | "[resourceId('Microsoft.Web/Sites/', parameters('functionAppName'))]" 262 | ], 263 | "properties": { 264 | "RepoUrl": "[variables('repoURL')]", 265 | "branch": "[variables('branch')]", 266 | "IsManualIntegration": true 267 | } 268 | } 269 | ] 270 | }, 271 | { 272 | "type": "Microsoft.Web/serverfarms", 273 | "apiVersion": "2018-11-01", 274 | "name": "[variables('hostingPlanName')]", 275 | "location": "[parameters('location')]", 276 | "properties": { 277 | "name": "[variables('hostingPlanName')]" 278 | }, 279 | "sku": { 280 | "name": "Y1", 281 | "tier": "Dynamic", 282 | "size": "Y1", 283 | "family": "Y", 284 | "capacity": 0 285 | } 286 | }, 287 | { 288 | "apiVersion": "2017-06-01", 289 | "type": "Microsoft.Storage/storageAccounts", 290 | "name": "[variables('storageAccountName')]", 291 | "location": "[parameters('location')]", 292 | "sku": { 293 | "name": "Standard_LRS" 294 | } 295 | }, 296 | { 297 | "apiVersion": "2018-05-01-preview", 298 | "name": "[parameters('functionAppName')]", 299 | "type": "Microsoft.Insights/components", 300 | "location": "[parameters('ApplicationInsightsLocation')]", 301 | "tags": { 302 | "[concat('hidden-link:', resourceId('Microsoft.Web/sites/', parameters('functionAppName')))]": "Resource" 303 | }, 304 | "properties": { 305 | "ApplicationId": "[parameters('functionAppName')]" 306 | } 307 | } 308 | ], 309 | "outputs": { 310 | "principalId": { 311 | "type": "string", 312 | "value": "[reference(concat(resourceId('Microsoft.Web/sites/', parameters('functionAppName')), '/providers/Microsoft.ManagedIdentity/Identities/default'), '2015-08-31-PREVIEW').principalId]" 313 | } 314 | } 315 | } --------------------------------------------------------------------------------