Add authentication for private nuget feed in ARM template - azure

The ARM template requirements for importing/applying a site extension nuget package is clear, but requires a public feed. What method should be used with a private Azure DevOps artifact nuget feed that requires authentication?
Template snippet below works with public feed, but returns Invalid feed Uri when private.
{
"name": "[variables('webAppName')]",
"type": "Microsoft.Web/sites",
"kind": "app",
"location": "[resourceGroup().location]",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('appServiceName'))]"
],
"tags": {},
"properties": {
"name": "[variables('webAppName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('appServiceName'))]",
"siteConfig": {
"WindowsFxVersion": "[parameters('windowsFxVersion')]",
"ftpsState": "Disabled",
"phpVersion": "Off",
"use32BitWorkerProcess": false,
"http20Enabled": true,
"minTlsVersion": "1.2",
"defaultDocuments": [
"index.html"
]
},
"hostNames": [
"[concat('wa-', parameters('baseAppName'),'.azurewebsites.net')]"
],
"siteProperties": {
"metadata": null,
"properties": [{
"name": "LinuxFxVersion",
"value": null
},
{
"name": "WindowsFxVersion",
"value": "DOTNETCORE|2.2"
}
],
"appSettings": null,
"httpsOnly": true
},
"availabilityState": "Normal",
"sslCertificates": null,
"httpsOnly": true,
"csrs": [],
"cers": null,
"siteMode": null,
"enabledHostNames": [
"[concat('wa-', parameters('baseAppName'),'.azurewebsites.net')]",
"[concat('wa-', parameters('baseAppName'),'.scm.azurewebsites.net')]"
]
},
"resources": [{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[concat('Microsoft.Web/sites/', variables('webAppName'))]"
],
"properties": {
"SCM_SITEEXTENSIONS_FEED_URL": "[PRIVATE NUGET FEED]"
}
},
{
"apiVersion": "2015-08-01",
"name": "[SITE EXTENSION NAME]",
"type": "siteextensions",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('webAppName'))]",
"[concat(resourceId('Microsoft.Web/Sites', variables('webAppName')),'/config/appsettings')]"
],
"properties": {}
}
]
}

It's not possible to use a private endpoint in a template deployment at this time.

Related

Azure ARM template - set application settings and diagnostic log setitngs

I ran into an issue running arm template for an app service where II want to configure application settings and diagnostic log settings.
{
"type": "Microsoft.Web/sites",
"name": "[parameters('azureWebsiteName')]",
"apiVersion": "[variables('appServiceApiVersion')]",
"location": "[variables('location')]",
"tags": {
"Solution": "[parameters('solutionType')]",
"Sku": "[parameters('solutionSku')]"
},
"properties": {
"enabled": true,
"clientAffinityEnabled": false,
"serverFarmId": "[variables('hostingPlanName')]",
"siteConfig": {
"alwaysOn": true,
"siteAuthEnabled": true,
"siteAuthSettings": {
"clientId": "[parameters('aadClientId')]",
"clientSecret": "[parameters('aadClientSecret')]",
"unauthenticatedClientAction": "[parameters('apiSiteUnauthenticatedClientAction')]",
"defaultProvider": "[parameters('apiSiteDefaultProvider')]",
"allowedAudiences": [
"[parameters('aadAppIdUri')]"
]
},
"appSettings": [ ]
}
},
"identity": {
"type": "SystemAssigned"
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
],
"resources": [
{
"type": "config",
"name": "appsettings",
"apiVersion": "[variables('appServiceApiVersion')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', parameters('azureWebsiteName'))]",
"[resourceId('Microsoft.Web/sites/config/', parameters('azureWebsiteName'), 'logs')]",
"[resourceId('microsoft.insights/components/', parameters('appInsightsName'))]",
"Microsoft.ApplicationInsights.AzureWebSites",
"[resourceId('Microsoft.KeyVault/vaults/', parameters('keyVaultName'))]",
"[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), variables('storageAccountConnectionString'))]",
"[resourceId('Microsoft.KeyVault/vaults/secrets', parameters('keyVaultName'), variables('documentDBAccessKey'))]"
],
"properties": {
"AzureWebJobsStorage": "[concat('#Microsoft.KeyVault(SecretUri=', reference(variables('storageAccountConnectionString')).secretUriWithVersion, ')')]"
}
},
{
"type": "config",
"name": "logs",
"apiVersion": "[variables('appServiceApiVersion')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', parameters('azureWebsiteName'))]",
"[resourceId('Microsoft.Storage/storageAccounts/', parameters('storageName'))]",
"[concat('Microsoft.Storage/storageAccounts/', parameters('storageName'), '/blobServices/default/containers/', variables('appLogsContainerName'))]",
"[concat('Microsoft.Storage/storageAccounts/', parameters('storageName'), '/blobServices/default/containers/', variables('webServerLogsContainerName'))]"
],
"properties": {
"httpLogs": {
"azureBlobStorage": {
"sasUrl": "[concat('https://',parameters('storageName'),'.blob.core.windows.net/',variables('webServerLogsContainerName'),'?',listServiceSas(parameters('storageName'), '2018-11-01', variables('webServerLogsSasProperties')).serviceSasToken)]",
"retentionInDays": "[parameters('diagnosticsLogsRetentionInDays')]",
"enabled": true
}
},
"failedRequestsTracing": {
"enabled": true
},
"detailedErrorMessages": {
"enabled": true
}
}
},
{
"type": "siteextensions",
"name": "Microsoft.ApplicationInsights.AzureWebSites",
"apiVersion": "[variables('appServiceApiVersion')]",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('azureWebsiteName'))]"
],
"properties": {}
}
]
}
The problem is when I deploy this, the logs config is set temporarily set then somehow gets un-set.
I believe it has something to do with multiple config objects(one for app-settings and one for logs) f I were to remove the app-settings config, the logs are correctly set and remain set.
Can someone help me understand what is happening?
Thanks!
Figured it out. I needed to add a dependency in logs on app settings.
"dependsOn": [
...
"[resourceId('Microsoft.Web/sites/config/', parameters('azureWebsiteName'), 'appsettings')]"
...
]
So the logs config will look like
{
"type": "config",
"name": "logs",
"apiVersion": "[variables('appServiceApiVersion')]",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', parameters('azureWebsiteName'))]",
"[resourceId('Microsoft.Web/sites/config/', parameters('azureWebsiteName'), 'appsettings')]",
"[resourceId('Microsoft.Storage/storageAccounts/', parameters('storageName'))]",
"[concat('Microsoft.Storage/storageAccounts/', parameters('storageName'), '/blobServices/default/containers/', variables('appLogsContainerName'))]",
"[concat('Microsoft.Storage/storageAccounts/', parameters('storageName'), '/blobServices/default/containers/', variables('webServerLogsContainerName'))]"
],
"properties": {
"applicationLogs": {
"azureBlobStorage": {
"level": "[parameters('diagnosticsLogsLevel')]",
"sasUrl": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', parameters('storageName'))).primaryEndpoints.blob, variables('appLogsContainerName'), '?', listAccountSas(parameters('storageName'), variables('storageApiVersion'), variables('listAccountSasRequestContent')).accountSasToken)]",
"retentionInDays": "[parameters('diagnosticsLogsRetentionInDays')]"
}
},
"httpLogs": {
"azureBlobStorage": {
"sasUrl": "[concat(reference(concat('Microsoft.Storage/storageAccounts/', parameters('storageName'))).primaryEndpoints.blob, variables('webServerLogsContainerName'), '?', listAccountSas(parameters('storageName'), variables('storageApiVersion'), variables('listAccountSasRequestContent')).accountSasToken)]",
"retentionInDays": "[parameters('diagnosticsLogsRetentionInDays')]",
"enabled": true
}
},
"failedRequestsTracing": {
"enabled": true
},
"detailedErrorMessages": {
"enabled": true
}
}
},
Just merge properties of both configs into a single entity and apply that entity and it would work.
This happens because you overwrite the first write with the second write.

Azure app service slot different value app setting

I have a webapp with a slot. Both should have the app setting name DISABLE_CRON. The webapp (production slot) should have this setting set to false and the slot should have the setting set to true. I would like to do this with ARM-template. The webapp have many appsettings such as database name, database login username and password etc. I want all of those settings to be in a variable so I don't have to write them one time for the webapp and one time for the slot. Basically I just want to change the value to true on the slot and keep all other settings the same.
"variables": {
"appName": "[concat(parameters('applicationName'),'-',parameters('environment'),'-app')]",
"hostingPlanName": "[concat(parameters('applicationName'),'-',parameters('environment'),'-plan')]",
"dbserverName": "[concat('onlinecampaignsites-',parameters('environment'),'-dbs-01')]",
"connectionString": "[concat('Database=', parameters('applicationName'), ';Data Source=', concat('onlinecampaignsites-',parameters('environment'),'-dbs-01'),'.mysql.database.azure.com;User Id=',parameters('administratorLogin'),'#',concat('onlinecampaignsites-',parameters('environment'),'-dbs-01'),';Password=',parameters('administratorLoginPassword'))]",
"appInsightsName": "[concat(parameters('applicationName'),'-',parameters('environment'),'-appIn')]",
"databaseName": "[parameters('applicationName')]",
"storageName": "[concat(parameters('applicationName'),parameters('environment'),'stg')]",
"serverFarmResourceGroup": "[resourceGroup().name]",
"subscriptionId": "[subscription().subscriptionId]",
"containerName01": "[concat(parameters('applicationName'),'-',parameters('environment'),'-uploads')]",
"staging": "staging",
"appsettings": {
"DISABLE_CRON": "false",
"HEJSAN": "Den vann den"
}
},
"resources": [
{
"name": "[variables('appname')]",
"type": "Microsoft.Web/sites",
"location": "[resourceGroup().location]",
"apiVersion": "2018-02-01",
"dependsOn": [
"[concat('Microsoft.Web/serverfarms/', variables('hostingPlanName'))]"
],
"properties": {
"siteConfig": {
"appSettings": [
{
"name": "DISABLE_CRON",
"value": "true"
}
]
},
"hostNameSslStates":"[concat('{\"name\": \"',parameters('customDomain'),'\", \"sslState\": \"Disabled\", \"virtualIP\": null, \"thumbprint\": null, \"toUpdate\": null,\"hostType\": \"Standard\"}')]",
"serverFarmId": "[concat('/subscriptions/', variables('subscriptionId'),'/resourcegroups/', variables('serverFarmResourceGroup'), '/providers/Microsoft.Web/serverfarms/', variables('hostingPlanName'))]",
"hostingEnvironment": "",
"httpsOnly": true
},
"resources": [
{
"apiVersion": "2018-02-01",
"name": "slotconfignames",
"type": "config",
"dependsOn": [
"[concat('Microsoft.Web/sites/', variables('appName'))]"
],
"properties": {
"appSettingNames": [ "DISABLE_CRON" ]
}
},
{
"apiVersion": "2018-02-01",
"type": "config",
"name": "appsettings",
"dependsOn": [
"[concat('Microsoft.Web/sites/', variables('appName'))]"
],
"properties": "[variables('appsettings')]"
}
]
},
{
"apiVersion": "2018-02-01",
"type": "Microsoft.Web/sites/slots",
"name": "[concat(variables('appName'), '/', variables('staging'))]",
"location": "[resourceGroup().location]",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('appName'))]",
"[concat('Microsoft.Web/serverfarms/', variables('hostingPlanName'))]"
],
"properties": {},
"resources": [
{
"apiVersion": "2018-02-01",
"type": "config",
"name": "appsettings",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/slots', variables('appName'), variables('staging'))]"
],
"properties": "[variables('appsettings')]"
}
]
},
In the ARM-template example there are two appsettings. It does not work to set the DISABLE_CRON to true, I just wanted to show that with this example.

ARM Template App Service Config - Race Condition / Inconsistent Behavior

Using ARM template below, we enabled diagnostic settings for our app service as well as defining appSettings config under resources element. The issue is that intermittently after deploying our app service from template - the appSettings are not getting assigned, but the diagnostics settings are.
Can someone guide us if there is a better way to define config for logs and appSettings for an app service that provides a more consistent site output? We build and teardown dozens of app services daily for PR builds so this is very apparent.
The appSetting WEBSITE_LOAD_USER_PROFILE will just get randomly dropped when the app service is created. Are we missing a dependsOn or do we need to upgrade apiVersion?
ServerFarm with App Settings + Log Config
{
"$schema": "http://schema.management.azure.com/schemas/2018-05-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"siteName": {
"type": "string"
},
"siteHostingPlanName": {
"type": "string"
},
"resourceLocation": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2016-09-01",
"name": "[parameters('siteHostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[parameters('resourceLocation')]",
"properties": {
"name": "[parameters('siteHostingPlanName')]"
},
"sku": {
"name": "P2V2",
"tier": "PremiumV2",
"capacity": 2
}
},
{
"apiVersion": "2014-11-01",
"name": "[parameters('siteName')]",
"type": "Microsoft.Web/sites",
"location": "[parameters('resourceLocation')]",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', parameters('siteHostingPlanName'))]"
],
"properties": {
"name": "[parameters('siteName')]",
"serverFarm": "[parameters('siteHostingPlanName')]",
"siteConfig": {
"AlwaysOn": true,
"webSocketsEnabled": true,
"http20Enabled": true,
"requestTracingEnabled": true,
"requestTracingExpirationTime": "9999-12-31T23:59:00Z",
"httpLoggingEnabled": true,
"logsDirectorySizeLimit": 100,
"detailedErrorLoggingEnabled": true
}
},
"resources": [
{
"apiVersion": "2014-11-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]"
],
"properties": {
"WEBSITE_LOAD_USER_PROFILE": 1
}
},
{
"apiVersion": "2014-11-01",
"name": "logs",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]"
],
"properties": {
"applicationLogs": {
"fileSystem": {
"level": "Verbose"
}
},
"httpLogs": {
"fileSystem": {
"retentionInMb": 100,
"enabled": true
}
},
"failedRequestsTracing": {
"enabled": true
},
"detailedErrorMessages": {
"enabled": true
}
}
}
]
}
]
}
Instead of defining the settings in a separate resource, you should configure the app settings together with the functionApp Resource. I have used this and defined various app settings and it works fine. Try like the below example.
{
"apiVersion": "[variables('sitesApiVersion')]",
"type": "Microsoft.Web/sites",
"kind": "functionapp",
"location": "[resourceGroup().location]",
"name": "[parameters('functionAppName')]",
"scale": null,
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('functionApp_appServicePlanName'))]",
"siteConfig": {
"appSettings": [
{
"name": "WEBSITE_LOAD_USER_PROFILE",
"value": "1"
}
]
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', parameters('functionApp_appServicePlanName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
]
}
}

App Insights Status Monitor Extension Failing to deploy with ARM template

I just started getting this failure, not sure why; it was working fine yesterday. I only changed the appsettings and connectionstrings to be part or resources instead of the webapp to move the dependsOn down the chain. Previously, the site was dependsOn the dependencies for app settings and connection strings. Here is the ARM template for the website resource.
{
"comments": "Primary web app deployment.",
"name": "[variables('webAppName')]",
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"kind": "app",
"location": "[variables('rgLocation')]",
"tags": {},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms', variables('planName'))]"
],
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(variables('webAppName'), '.azurewebsites.net')]",
"sslState": "Disabled"
},
{
"name": "[concat(variables('webAppName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled"
}
],
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('planName'))]",
"siteConfig": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.6",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2015",
"httpLoggingEnabled": false,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"scmType": "None",
"use32BitWorkerProcess": false,
"webSocketsEnabled": false,
"alwaysOn": true,
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false
}
],
"autoHealEnabled": false,
"vnetName": ""
},
"microService": "WebSites",
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false
},
"resources": [
{
"name": "appsettings",
"type": "config",
"apiVersion":"2015-08-01",
"dependsOn":[
"[resourceId('Microsoft.Web/sites', variables('webAppName'))]",
"[resourceId('microsoft.insights/components', variables('insightsName'))]"
],
"properties": {
"APPINSIGHTS_INSTRUMENTATIONKEY":"[reference(resourceId('Microsoft.Insights/components', variables('insightsName')), '2015-05-01').InstrumentationKey]",
"UseAzureStorageEmulator": "false"
}
},
{
"name": "connectionstrings",
"type": "config",
"apiVersion":"2015-08-01",
"dependsOn":[
"[resourceId('Microsoft.Web/sites', variables('webAppName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('genStorageName'))]",
"[resourceId('Microsoft.Storage/storageAccounts', variables('jobStorageName'))]"
],
"properties": {
"AzureStorage": {
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('genStorageName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('genStorageName')), '2017-06-01').keys[0].value, ';EndpointSuffix=core.windows.net')]",
"type": "Custom"
},
"AzureWebJobsDashboard" : {
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('jobStorageName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('jobStorageName')), '2017-06-01').keys[0].value, ';EndpointSuffix=core.windows.net')]",
"type": "Custom"
},
"AzureWebJobsStorage" : {
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('jobStorageName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('jobStorageName')), '2017-06-01').keys[0].value, ';EndpointSuffix=core.windows.net')]",
"type": "Custom"
}
}
},
{
"apiVersion":"2015-08-01",
"name": "Microsoft.ApplicationInsights.AzureWebSites",
"type": "siteextensions",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('webAppName'))]"
],
"properties": {}
}
]
}
And the error I'm getting...
STATUS Conflict
PROVISIONING STATE Failed
TIMESTAMP7/14/2017, 10:40:23 AM
DURATION 1 minute 46 seconds
TYPE Microsoft.Web/sites/siteextensions
RESOURCE ID /subscriptions/.../providers/Microsoft.Web/sites/.../siteextensions/Microsoft.ApplicationInsights.AzureWebSites
STATUSMESSAGE{
"status": "Canceled",
"error": {
"code": "ResourceDeploymentFailure",
"message": "The resource operation completed with terminal provisioning state 'Canceled'."
}
}
Even with the error, it actually did install the extension correctly. During another test, it installed the extension, but when I opened it, the App Insights Profiler web job was not installed. Either way, not sure why there is a conflict. When I open the log in Kudu, there is pretty much nothing inside.
7/14/2017 2:44:38 PM: [Verbose] Starting Application Insights installation and configuration...
7/14/2017 2:44:38 PM: [Verbose] Loading assembly from D:\home\SiteExtensions\Microsoft.ApplicationInsights.AzureWebSites\Microsoft.ApplicationInsights.WebSiteManager.dll
7/14/2017 2:44:39 PM: [Verbose] No web.config detected. The web app may be empty. Assume classic ASP.NET by default.
That's the entirety of the log.
On a previous test...
7/13/2017 6:15:44 PM: [Verbose] Starting Application Insights installation and configuration...
7/13/2017 6:15:44 PM: [Verbose] Loading assembly from D:\home\SiteExtensions\Microsoft.ApplicationInsights.AzureWebSites\Microsoft.ApplicationInsights.WebSiteManager.dll
7/13/2017 6:15:44 PM: [Verbose] No web.config detected. The web app may be empty. Assume classic ASP.NET by default.
Same start of the file, but there are more entries. There is definitely a web config and the app is working so not sure what that's about.
7/13/2017 6:15:50 PM: [Verbose] Application is not instrumented with Application Insights.
7/13/2017 6:15:50 PM: [Verbose] Starting to download/install 'Microsoft.ApplicationInsights.Azure.WebSites' nuget package from D:\home\SiteExtensions\Microsoft.ApplicationInsights.AzureWebSites\appinsights...
7/13/2017 6:15:52 PM, [Verbose] Installing 'Microsoft.ApplicationInsights', version '2.3.0' ...
7/13/2017 6:15:53 PM, [Verbose] Installed 'Microsoft.ApplicationInsights', version '2.3.0'.
The app is definitely instrumented and uses version 2.4 which is newer than 2.3 which was installed.
According to your description, I think the reason why the siteextensions installed has been canceled is changed the appsetting the web app will restarted.So it will cancel the siteextensions installed thread.
After the deployment changed the web app appsetting, it will restart the web app. But your deployment still running the thread which installing the siteextensions. So you face the thread canceled error.
I suggest you could set the appsettings during the web app resource's siteConfig feature. When you deploy the template, it will not cause the web app restart while installing the siteextensions.
Some part of the template you could refer to below codes:
"siteConfig": {
"appSettings": [
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('Microsoft.Insights/components', variables('webSiteName')), '2015-05-01').InstrumentationKey]"
}
]
The whole test template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"hostingPlanName": {
"type": "string",
"minLength": 1
},
"skuName": {
"type": "string",
"defaultValue": "F1",
"allowedValues": [
"F1",
"D1",
"B1",
"B2",
"B3",
"S1",
"S2",
"S3",
"P1",
"P2",
"P3",
"P4"
],
"metadata": {
"description": "Describes plan's pricing tier and capacity. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
}
},
"skuCapacity": {
"type": "int",
"defaultValue": 1,
"minValue": 1,
"metadata": {
"description": "Describes plan's instance count"
}
}
},
"variables": {
"webSiteName": "brandotestarm11"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[parameters('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "HostingPlan"
},
"sku": {
"name": "[parameters('skuName')]",
"capacity": "[parameters('skuCapacity')]"
},
"properties": {
"name": "[parameters('hostingPlanName')]"
}
},
{
"apiVersion": "2014-04-01",
"name": "[variables('webSiteName')]",
"type": "Microsoft.Insights/components",
"location": "East US",
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
],
"tags": {
"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('webSiteName'))]": "Resource",
"displayName": "AppInsightsComponent"
},
"properties": {
"applicationId": "[variables('webSiteName')]"
}
},
{
"comments": "Primary web app deployment.",
"apiVersion": "2015-08-01",
"name": "[variables('webSiteName')]",
"type": "Microsoft.Web/sites",
"location": "[resourceGroup().location]",
"tags": {},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
"[resourceId('microsoft.insights/components', variables('webSiteName'))]"
],
"properties": {
"enabled": true,
"hostNameSslStates": [
{
"name": "[concat(variables('webSiteName'), '.azurewebsites.net')]",
"sslState": "Disabled"
},
{
"name": "[concat(variables('webSiteName'), '.scm.azurewebsites.net')]",
"sslState": "Disabled"
}
],
"siteConfig": {
"appSettings": [
{
"name": "APPINSIGHTS_INSTRUMENTATIONKEY",
"value": "[reference(resourceId('Microsoft.Insights/components', variables('webSiteName')), '2015-05-01').InstrumentationKey]"
}
],
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.6",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2015",
"httpLoggingEnabled": false,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"scmType": "None",
"use32BitWorkerProcess": false,
"webSocketsEnabled": false,
"alwaysOn": true,
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false
}
],
"autoHealEnabled": false,
"vnetName": ""
},
"microService": "WebSites",
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false,
"name": "[variables('webSiteName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "Microsoft.ApplicationInsights.AzureWebSites",
"type": "siteextensions",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('webSiteName'))]"
],
"properties": {}
}
]
}
]
}
The result:
Update:
I suggest you could firstly install the web site extensions, then change the appsetting.
In the web app config resources, you could set its depend on the web site extensions.
So the template will firstly install the extensions, then change the appsetting to make the web app restart. So you could install the extensions complete.
More details, you could refer to below template:
You could set the dependsOn with "Microsoft.ApplicationInsights.AzureWebSites".
"resources": [
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webSiteName'))]",
"[resourceId('microsoft.insights/components', variables('webSiteName'))]",
"Microsoft.ApplicationInsights.AzureWebSites"
],
"properties": {
"APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(resourceId('Microsoft.Insights/components', variables('webSiteName')), '2015-05-01').InstrumentationKey]",
"UseAzureStorageEmulator": "false"
}
},
The total template:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"hostingPlanName": {
"type": "string",
"minLength": 1
},
"skuName": {
"type": "string",
"defaultValue": "F1",
"allowedValues": [
"F1",
"D1",
"B1",
"B2",
"B3",
"S1",
"S2",
"S3",
"P1",
"P2",
"P3",
"P4"
],
"metadata": {
"description": "Describes plan's pricing tier and capacity. Check details at https://azure.microsoft.com/en-us/pricing/details/app-service/"
}
},
"skuCapacity": {
"type": "int",
"defaultValue": 1,
"minValue": 1,
"metadata": {
"description": "Describes plan's instance count"
}
}
},
"variables": {
"webSiteName": "brandotestarmfor"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[parameters('hostingPlanName')]",
"type": "Microsoft.Web/serverfarms",
"location": "[resourceGroup().location]",
"tags": {
"displayName": "HostingPlan"
},
"sku": {
"name": "[parameters('skuName')]",
"capacity": "[parameters('skuCapacity')]"
},
"properties": {
"name": "[parameters('hostingPlanName')]"
}
},
{
"apiVersion": "2015-08-01",
"name": "[variables('webSiteName')]",
"type": "Microsoft.Web/sites",
"location": "[resourceGroup().location]",
"tags": {
"[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
"displayName": "Website"
},
"dependsOn": [
"[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
],
"properties": {
"name": "[variables('webSiteName')]",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]",
"siteConfig": {
"numberOfWorkers": 1,
"defaultDocuments": [
"Default.htm",
"Default.html",
"Default.asp",
"index.htm",
"index.html",
"iisstart.htm",
"default.aspx",
"index.php",
"hostingstart.html"
],
"netFrameworkVersion": "v4.6",
"phpVersion": "",
"pythonVersion": "",
"nodeVersion": "",
"linuxFxVersion": "",
"requestTracingEnabled": false,
"remoteDebuggingEnabled": false,
"remoteDebuggingVersion": "VS2015",
"httpLoggingEnabled": false,
"logsDirectorySizeLimit": 35,
"detailedErrorLoggingEnabled": false,
"scmType": "None",
"use32BitWorkerProcess": false,
"webSocketsEnabled": false,
"alwaysOn": true,
"managedPipelineMode": "Integrated",
"virtualApplications": [
{
"virtualPath": "/",
"physicalPath": "site\\wwwroot",
"preloadEnabled": false
}
],
"autoHealEnabled": false,
"vnetName": ""
},
"clientAffinityEnabled": false,
"clientCertEnabled": false,
"hostNamesDisabled": false
},
"resources": [
{
"name": "appsettings",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', variables('webSiteName'))]",
"[resourceId('microsoft.insights/components', variables('webSiteName'))]",
"Microsoft.ApplicationInsights.AzureWebSites"
],
"properties": {
"APPINSIGHTS_INSTRUMENTATIONKEY": "[reference(resourceId('Microsoft.Insights/components', variables('webSiteName')), '2015-05-01').InstrumentationKey]",
"UseAzureStorageEmulator": "false"
}
},
{
"apiVersion": "2015-08-01",
"name": "Microsoft.ApplicationInsights.AzureWebSites",
"type": "siteextensions",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('webSiteName'))]"
],
"properties": {}
}
]
},
{
"apiVersion": "2014-04-01",
"name": "[variables('webSiteName')]",
"type": "Microsoft.Insights/components",
"location": "East US",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/', variables('webSiteName'))]"
],
"tags": {
"[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', variables('webSiteName'))]": "Resource",
"displayName": "AppInsightsComponent"
},
"properties": {
"applicationId": "[variables('webSiteName')]"
}
}
]
}
The result like this:
There seems to be no way to make the extension wait on app setting update so I moved the installation of the extension into a different task in the release environment. Now I have three tasks:
1. ARM deploy common resources
2. ARM deploy app dependencies and app service
3. ARM deploy status monitor site extension
4. Web Deploy code into app service
However, in order to do this, you have to still specify the website somehow in step 3.
Here is what I did using the output from step 2 which has the webAppName, I had to specify the site again and then place the extension into the resources for that site. You must be careful about what you specify here as to not disrupt the previous deployment.
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"webAppName": { "type": "string", "value": "<outputfrompreviousstep>" }
},
"variables": {
"planName": "[concat(variables('webAppName'), '-ServicePlan')]"
},
"resources": [
{
"name": "[variables('webAppName')]",
"type": "Microsoft.Web/sites",
"apiVersion": "2016-08-01",
"location": "[resourceGroup().location]",
"tags": {},
"dependsOn": [
],
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('planName'))]"
},
"resources": [
{
"apiVersion":"2015-08-01",
"name": "Microsoft.ApplicationInsights.AzureWebSites",
"type": "siteextensions",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', variables('webAppName'))]"
],
"properties": {}
}
]
}
],
"outputs": {
"webAppName": {
"type": "string",
"value": "[variables('webAppName')]"
}
}
}

Attach an existing Web Service plan to a new Website using Azure Resource Manager templates

I am trying to automate website deployment using the Azure Resource Manager. Website creation and code deployment is working fine, but I am unable to attach the new site to an existing Web Hosting plan.
I am using the 2015-08-01 API and from different examples I think that this template should work (it does not...):
The deployment fails at "Microsoft.Web/sites/config" and the site is beeing assigned a new default free hosting plan.
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"siteName": {
"type": "string"
},
"subscriptionId": {
"type": "string"
},
"setting1": {
"type": "string"
},
"setting2": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
"name": "[parameters('siteName')]",
"location": "[resourceGroup().location]",
"properties": {
"serverFarmId ": "/subscriptions/xxxxxx/resourceGroups/xxxxxx/providers/Microsoft.Web/serverfarms/xxxxxx"
},
"resources": [
{
"apiVersion": "2015-08-01",
"name": "web",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]"
],
"properties": {
"phpVersion": "off",
"netFrameworkVersion": "v4.6",
"use32BitWorkerProcess": false,
"webSocketsEnabled": true,
"alwaysOn": true,
"requestTracingEnabled": false,
"httpLoggingEnabled": false,
"logsDirectorySizeLimit": 40,
"detailedErrorLoggingEnabled": false,
"appSettings": [
{
"Name": "setting1",
"Value": "Value1"
},
{
"Name": "setting2",
"Value": "Value2"
}
]
}
},
{
"apiVersion": "2015-08-01",
"type": "extensions",
"name": "MSDeploy",
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('siteName'))]"
],
"properties": {
"packageUri": "xxxxxxxx",
"dbType": "None",
"connectionString": ""
}
}
]
}
],
"outputs": {
"siteUri": {
"type": "string",
"value": "[concat('http://',reference(resourceId('Microsoft.Web/sites', parameters('siteName'))).hostNames[0])]"
}
}
}
I ended up falling back to the 2014-06-01 API and with some adjustments to the script, was able to do what I wanted.
Providing the script for future references.
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"siteName": {
"type": "string"
},
"subscriptionId": {
"type": "string"
},
"hostingPlanName": {
"type": "string"
},
"setting1": {
"type": "string"
},
"setting2": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2014-06-01",
"type": "Microsoft.Web/sites",
"name": "[parameters('siteName')]",
"location": "[resourceGroup().location]",
"dependsOn": [
],
"properties": {
"name": "[parameters('siteName')]",
"serverFarm": "[parameters('hostingPlanName')]"
},
"resources": [
{
"apiVersion": "2014-06-01",
"name": "web",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]",
"[concat('Microsoft.Web/Sites/', parameters('siteName'), '/Extensions/MSDeploy')]"
],
"properties": {
"phpVersion": "off",
"netFrameworkVersion": "v4.6",
"use32BitWorkerProcess": false,
"webSocketsEnabled": true,
"alwaysOn": true,
"requestTracingEnabled": false,
"httpLoggingEnabled": false,
"logsDirectorySizeLimit": 40,
"detailedErrorLoggingEnabled": false
}
},
{
"apiVersion": "2014-11-01",
"name": "appsettings",
"type": "config",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]",
"[concat('Microsoft.Web/Sites/', parameters('siteName'), '/Extensions/MSDeploy')]"
],
"properties": {
"Setting1": "[parameters('setting1')]",
"Setting2": "[parameters('setting2')]"
}
},
{
"apiVersion": "2015-08-01",
"type": "extensions",
"name": "MSDeploy",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]"
],
"properties": {
"packageUri": "https://xxxxx.zip",
"dbType": "None",
"connectionString": ""
}
}
]
}
]
}

Resources