Search code examples
azuredeploymentazure-web-app-serviceazure-resource-managerdacpac

Azure Resource Manager template - deploy dacpac and two web projects into one web app


We are trying to use ARM to requisition and deploy a fairly complex setup into Azure. Here are the basic components:

  • 2 Web projects which should go into one Web App, one in a virtual sub-directory
  • 2 Sql databases on the same db server, using a DACPAC (not bacpac)
  • Azure Service Bus
  • VM for middleware
  • Some other stuff

I have most of this working. Two main parts I cannot seem to figure out how to do:

  1. I cannot find a template or way to do the DACPAC deployment. We have our schema in a Sql Database Project, which compiles neatly into the dacpac format. I was expecting to be able to add it into the ARM deployment template using the Azure Resource Group deployment project. But so far I could only find a way to do a database import using a BACPAC file, which doesn't make much sense in our case.
  2. I'm trying to find a way to deploy two separate web projects into azure web app, but into two different virtual applications. I found a way to configure the virtual app paths on one WebDeploy, but I can't add a second project into the same WebSite node.

Here's the snippet from the deployment template for the web site for one app:

{
          "name": "[variables('UxWebAppName')]",
          "type": "Microsoft.Web/sites",
          "location": "[resourceGroup().location]",
          "apiVersion": "2015-08-01",
          "dependsOn": [
              "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
          ],
          "tags": {
              "[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
              "displayName": "UxWebApp"
          },
          "properties": {
              "name": "[variables('UxWebAppName')]",
              "serverFarmId": "[resourceId('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
          },
        "resources": [
          {
            "apiVersion": "2015-08-01",
            "name": "web",
            "type": "config",
            "dependsOn": [
              "[resourceId('Microsoft.Web/Sites', variables('UxWebAppName'))]"
            ],
            "properties": {
              "phpVersion": "5.5",
              "netFrameworkVersion": "v4.6",
              "use32BitWorkerProcess": false, /* 64-bit platform */
              "webSocketsEnabled": true,
              "alwaysOn": true,
              "remoteDebuggingEnabled": false,
              "virtualApplications": [
                {
                  "virtualPath": "/",
                  "physicalPath": "site\\wwwroot"
                },
                {
                  "virtualPath": "/api",
                  "physicalPath": "site\\wwwroot\\api"
                }
              ],

              "defaultDocuments": [
                "index.html",
                "hostingstart.html"
              ]
            }
          },
          {
            "name": "MSDeploy",
            "type": "extensions",
            "location": "[resourceGroup().location]",
            "apiVersion": "2015-08-01",
            "dependsOn": [
              "[concat('Microsoft.Web/sites/', variables('UxWebAppName'))]"
            ],
            "tags": {
              "displayName": "UxDeploy"
            },
            "properties": {
              "packageUri": "[concat(parameters('_artifactsLocation'), '/', parameters('UxDeployPackageFolder'), '/', parameters('UxDeployPackageFileName'), parameters('_artifactsLocationSasToken'))]",
              "dbType": "None",
              "connectionString": "",
              "setParameters": {
                "IIS Web Application Name": "[variables('UxWebAppName')]"
              }
            }
          }

I was trying to add a second MSDeploy extension element, but that caused an error during the deploy saying that there was a duplicate node.

Here's the snippet for the sql server part:

{
      "name": "[variables('sqlserverName')]",
      "type": "Microsoft.Sql/servers",
      "location": "[resourceGroup().location]",
      "tags": {
        "displayName": "SqlServer"
      },
      "apiVersion": "2014-04-01-preview",
      "properties": {
        "administratorLogin": "[parameters('administratorLogin')]",
        "administratorLoginPassword": "[parameters('administratorLoginPassword')]"
      },
      "resources": [
        {
          "name": "[parameters('coreDatabaseName')]",
          "type": "databases",
          "location": "[resourceGroup().location]",
          "tags": {
            "displayName": "CoreDatabase"
          },
          "apiVersion": "2014-04-01-preview",
          "dependsOn": [
            "[concat('Microsoft.Sql/servers/', variables('sqlserverName'))]"
          ],
          "properties": {
            "edition": "[parameters('edition')]",
            "collation": "[parameters('collation')]",
            "maxSizeBytes": "[parameters('maxSizeBytes')]",
            "requestedServiceObjectiveName": "[parameters('requestedServiceObjectiveName')]"
          },
            "resources": [
                {
                    "name": "Import",
                    "type": "extensions",
                    "apiVersion": "2014-04-01-preview",
                    "dependsOn": [
                        "[parameters('coreDatabaseName')]"
                    ],
                    "tags": {
                        "displayName": "CoreDb"
                    },
                  "properties": {
                    "storageKeyType": "[parameters('CoreDbStorageKeyType')]",
                    "storageKey": "[parameters('primaryKey')]",
                    "storageUri": "[concat(parameters('_artifactsLocation'), '/', parameters('CoreDbStoragePackageFolder'), '/', parameters('CoreDbStoragePackageFileName'))]",
                    "administratorLogin": "[parameters('administratorLogin')]",
                    "administratorLoginPassword": "[parameters('administratorLoginPassword')]",
                    "operationMode": "Import"
                  }
                }
            ]
        },
        {
          "type": "firewallrules",
          "apiVersion": "2014-04-01-preview",
          "dependsOn": [
            "[concat('Microsoft.Sql/servers/', variables('sqlserverName'))]"
          ],
          "location": "[resourceGroup().location]",
          "name": "AllowAllWindowsAzureIps",
          "properties": {
            "endIpAddress": "0.0.0.0",
            "startIpAddress": "0.0.0.0"
          }
        }
      ]
    }

This only seems to work with a bacpac file, but not with a dacpac. I just can't find much useful information on this anywhere on the web. I found maybe a couple of entries which were talking about including the dacpac in the web app project, but that approach seems pretty odd to me. I tried setting the operationMode to Publish (assuming it's using sqlpackage under the hood), but it said it's not supported.

Has anyone had any experience with these two types of deployment using ARM? Or am I just one of the first guinea pigs to try and do this?

I guess I can just execute the deploy for the dacpac and the web app separately using powershell / msbuild deploy (where I can specify virtual directories etc), but that sort of defeats the purpose of ARM as far as I understand?

Any useful hints are appreciated!

EDIT I have the deployment working without the ARM and the requisitioning part using MSBuild like so: For the web apps using the publishprofile it's easy to

"C:\Program Files (x86)\MSBuild\12.0\Bin\MSBuild.exe" ../xx/SomeApp.csproj /p:DeployOnBuild=true /p:PublishProfile=SomeApp.pubxml /p:VisualStudioVersion=12.0 /p:Password=******

For the sql deploy like this:

"C:\Program Files (x86)\Microsoft SQL Server\120\DAC\bin\sqlpackage.exe" /Action:Publish /SourceFile:"U:\bin\Database\Database.dacpac" /TargetConnectionString:"Server=some.database.windows.net,1433;Database=SomeDatabase;User ID=someUser;Password=*******;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" /p:GenerateSmartDefaults=True /p:RegisterDataTierApplication=True /p:BlockWhenDriftDetected=False /p:BlockOnPossibleDataLoss=False

The question is purely about ARM template deployment. I mean, I can split requisitioning (using ARM) and deployment (using msdeploy or Powershell DSC), but I assume I'm just not doing it right, since some parts of the deployment (e.g. web packages) are working. Is really only half the stuff supported, but half of it not (yet)?


Solution

  • At this time it is not supported to deploy a dacpac to Azure Database using Azure Template Deployment.

    https://social.msdn.microsoft.com/Forums/sqlserver/en-US/9305ac76-2ca7-4e89-b705-84cc1db82513/azure-resource-manager-template-deploy-dacpac-into-azure-sql-database?forum=ssdsgetstarted