Data sinks can’t be reused in different settings on the same category for the same resource

Developing Logic Apps in Azure is quite a nice experience. Using the Azure Portal to design and implement your workflow is easy.

Less pleasurable is creating ARM templates for Logic Apps (perhaps another post another time). Let’s just say now that this requires some manual labor, but the results are very rewarding;)

Using Azure DevOps we are deploying our Azure resources into the ‘Development’ Resourcegroup as the first step in our pipeline. In the case of a Logic App this means overwriting the version you created manually in the Portal. This means that you have to verify the ARM template was correct comparing the current version of the Logic App with the previous one.

Another thing that can happen during this process is an error I ran into today for the second time. It can take some time to figure out what exactly happened so I decided to document this for when it happens again…

If you have linked your Logic App to an instance of Log Analytics, either at creation time or later, you can run into this error at the deploy:

Data sink '/subscriptions/xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/rg-monitoring/providers/Microsoft.OperationalInsights/workspaces/ws-monitoring' is already used in diagnostic setting 'service' for category 'WorkflowRuntime'. Data sinks can't be reused in different settings on the same category for the same resource. (Code: Conflict)

To resolve this error you have to delete the existing diagnostic setting, so ARM can deploy a new one and will not see this setting as duplicate. Subsequent deployments will succeed after this change.

Azure DevOps – AzureFileCopy task breaking change?

The surprise,

At my team we have been happily using Azure DevOps (formerly known as VSTS, Visual Studio Online) building and releasing our projects into Azure. Yesterday, out of the blue, one of our releases broke. Azure DevOps AzureFileCopy Error. InvalidContentLink, unable to download deployment content from ‘https://…..’

Huh?

the analysis…

After some inspection this turned out to be a combination of the power of a Software as a Service like Azure Devops, combined with our desire of using the latest and greatest of these applications. We are using V2 of this task, which is in Preview and thus bound to change. In many cases these changes are adding or simplifying features for us developers, but in this case something broke.

In our release pipeline we are using a task called Azure File Copy V2. This task is using azcopy to copy some deployment related stuff into a blob container, in this case a linked ARM template.

The main template, let’s call it azuredeploy.json, is using a path to a linked ARM template. This path is created on the fly using an output parameter of the Azure File Copy task, the outputStorageURI. To this location, a subfolder is added for our linked temlate:

"templateLink": {
      "uri": "[concat(parameters('storageURI'),'/Microsoft.Storage/Project.StorageAccount.json', parameters('storageURISasToken'))]"
}

On October 4th a change was done in this task: a trailing slash was added for compatibility with uri function (link to github)

A slash was added to the path returned by the task, breaking releases later in the pipeline
A slash was added to the path returned by the task, breaking releases later in the pipeline Breaking change in AzureFileCopyV2 task?

Now, since the release pipeline in Azure DevOps is not as insensitive to duplicate slashes as an OS like Windows, problems rise when this output parameter  is combined with our own second part of the template path. The leading slash, which was previously required for the template to work, was now causing a problem…

… and a solution

Luckily I found a workaround quickly because of the open source nature of these Azure pipeline tasks. I introduced a new variable that checks the existence of the trailing slash and adjusts the parameter to get something working again. After that I replaced parameters(‘storageURI) with variables(‘newStorageURI’) in the template. Linked templates don’t have to be updated, they will get the correct URI passed to them by azuredeploy.json.

"variables": {
     "newStoragrURI": "[if(endsWith(parameters('storageURI'), '/'), take(parameters('storageURI'),add(length(parameters('storageUr')),-1)),parameters('_artifactsLocation'))]"
}

Another solution would of course have been to remove our own ‘extra’ leading slash from our templates, but I considered this solution more backwards- and forwards compatible:)