This post was most recently updated on July 27th, 2022.
3 min read.So some time ago, I needed to configure my first Azure DevOps pipeline for an Azure IoT Edge project. I needed to figure out which tasks to use, how to handle variables – all that good stuff. And let’s call it a learning experience.
Pro tip: AzureIoTEdge task is not the way to go :)
This article has actually been more than a year in the making, but as usual, it takes me a while to get around to polishing things into a publishable form. This time, it took until I went on 6-week paternity leave.
Background
Azure IoT Edge has dedicated tasks for the most typical things you might need to accomplish in your Azure DevOps pipelines – building, pushing, and deploying modules. As a novice Azure IoT Edge developer, I opted to use these.
This turned out to be a bit more complicated than I expected, and I needed to find some workarounds.
Problem
So, using Azure IoT Edge Azure DevOps tasks, you should theoretically be building the pipeline using the built-in task called AzureIoTEdge. This would look somewhat like this (don’t use the YAML for anything, that’s just a sample to show you an idea):
trigger:
- main
variables:
azureSubscriptionEndpoint: Contoso
azureContainerRegistry: contoso.azurecr.io
steps:
- task: AzureIoTEdge@2
displayName: AzureIoTEdge - Build module images
inputs:
action: Build module images
templateFilePath: deployment.template.json
defaultPlatform: amd64
- task: AzureIoTEdge@2
displayName: AzureIoTEdge - Push module images
inputs:
action: Push module images
containerregistrytype: Azure Container Registry
azureSubscriptionEndpoint: $(azureSubscriptionEndpoint)
azureContainerRegistry: {"loginServer":"$(azureContainerRegistry)"}
templateFilePath: deployment.template.json
defaultPlatform: amd64
fillRegistryCredential: true
- task: AzureIoTEdge@2
displayName: AzureIoTEdge - Generate deployment manifest
inputs:
action: Generate deployment manifest
templateFilePath: deployment.template.json
defaultPlatform: amd64
deploymentManifestOutputPath: $(System.DefaultWorkingDirectory)/config/deployment.json
validateGeneratedDeploymentManifest: false
- task: AzureIoTEdge@2
displayName: 'Azure IoT Edge - Deploy to IoT Edge devices'
inputs:
action: 'Deploy to IoT Edge devices'
deploymentFilePath: $(System.DefaultWorkingDirectory)/config/deployment.json
azureSubscription: $(azureSubscriptionEndpoint)
iothubname: iothubname
deploymentid: '$(System.TeamProject)-devops-deployment'
priority: '0'
deviceOption: 'Single Device'
deviceId: deviceId
But with the AzureIoTEdge tasks, you’ll probably run into problems with authentication, building complicated images, pushing to ACR, deploying layered deployments, or actually doing anything at all.
Fear not, though! There are great replacements available 😅
Solution
So, let’s go through which steps you’ll (probably need)!
Time needed: 4 days, 5 hours and 30 minutes
How to replace AzureIoTEdge tasks in Azure DevOps with functional tasks?
- Instead of “AzureIoTEdge – Build module images” use Docker
Using docker build instead the equivalent AzureIoTEdge task is going to do the same thing but save you a few grey hairs!
The YAML will look somewhat like this:- task: Docker@2
displayName: Build an image
inputs:
repository: $(imageName)
command: build
Dockerfile: app/Dockerfile - Instead of “AzureIoTEdge – Push module images” use Docker
Just like before – the AzureIoTEdge task is just going to be a less reliable and not-as-configurable version of the Docker task.
Instead, you might want to use docker push – somewhat like below:- task: Docker@2
displayName: Push image
inputs:
containerRegistry: |
$(dockerHub)
repository: $(imageName)
command: push
tags: |
test1
test2 - Instead of “AzureIoTEdge – Generate deployment manifest” have the manifest in version control
You shouldn’t need to generate a deployment manifest in normal cases, so you shouldn’t need AzureIoTEdge – Generate deployment manifest task anyway – deployment manifests should probably be in your version control.
If you need to have some secrets in them, you can replace them with tokens in the template and replace the tokens using this task:
https://marketplace.visualstudio.com/items?itemName=qetza.replacetokens
Alternatively, you could build a nifty PowerShell script to replace contents in your JSON file, if the task above is unavailable to you. - Instead of “AzureIoTEdge – Deploy to IoT Edge devices” use the Azure CLI task
Azure CLI task is far more configurable than the AzureIoTEdge task. So, let’s see what we do with it to replace the “Deploy to IoT Edge devices” task!
How does this look, then? Well, it’s a bit more verbose than the AzureIoTEdge task, but the good thing is you can experiment right in Azure CLI to see what works for you, and just copy-paste that to Azure DevOps.
A sample of something that works would look like this:
– task: AzureCLI@2
displayName: Create Edge Deployment using AZ CLI
inputs:
azureSubscription: $(serviceConnection)
scriptType: ‘pscore’
scriptLocation: ‘inlineScript’
inlineScript: |
az config set extension.use_dynamic_install=yes_without_prompt
az account set –subscription “subName” $TargetCondition = “(tags.environment=’dev’ AND tags.location=’stockholm’)”
az iot edge deployment create -d ‘unique-deployment-name’ -n ‘iot-hub-name’ –content ‘path-to-your-layered-deployment-manifest-file.json’ –layered –target-condition “$TargetCondition” –priority 10
(Source: Sample of a layered deployment using az CLI in Azure DevOps pipeline YAML file)
I know – it’s a lot! But you don’t actually need target conditions and –layered if you don’t do layered deployments, and instead just do a “full deployment” each time.
And here we are! Hope this was as useful as it would’ve been for me before embarking on my first major Azure DevOps pipeline configuration task for an Azure IoT Edge project.
References
- https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/build/azure-iot-edge?view=azure-devops
- Refreshing DefaultAzureCredential in Visual Studio - November 26, 2024
- M365 Copilot claiming “You have turned off web search in the work mode”? Easy fix! - November 19, 2024
- “Performing cleanup” – Excel is stuck with an old, conflicted file and will never recover. - November 12, 2024