I’m working towards deploying azure DevOps build agents on azure container apps jobs and when deploying using an ARM templating I’m getting the below generic error message:
WARNING: Default enabled including preview versions for extension installation now. Disabled in future release. Use '--allow-preview true' to enable it specifically if needed. Use '--allow-preview false' to install stable version only.
WARNING: The installed extension 'containerapp' is in preview.
ERROR: {"code": "InvalidTemplateDeployment", "message": "The template deployment 'containerapp' is not valid according to the validation procedure. The tracking id is '372358fe-1076-4b96-ae3c-b4b6abbd987e'. See inner errors for details."}
Inner Errors:
{"code": "ValidationForResourceFailed", "message": "Validation failed for a resource. Check 'Error.Details[0]' for more information."}
Inner Errors:
{"code": "ContainerAppsJobInvalidSchema", "message": "Invalid request body for container apps job. Does not conform to Container Apps Job schema, please visit for more information https://docs.microsoft.com/azure/container-apps/azure-resource-manager-api-spec?tabs=arm-template#container-app"}
I’ve reviewed the documentation, and I can’t find a difference between what I’m building and their documentation.
Template:
{
"$schema": "https://schema.management.azure.com/schemas/2019-08-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"environment_name": {
"type": "string"
},
"location": {
"type": "string"
},
"azp_url": {
"type": "securestring"
},
"azp_token": {
"type": "securestring"
},
"azp_pool": {
"type": "string"
},
"azp_poolId": {
"type": "int"
},
"REGISTRY_LOGIN_SERVER": {
"type": "string"
},
"REGISTRY_USERNAME": {
"type": "string"
},
"REGISTRY_PASSWORD": {
"type": "securestring"
},
"IMAGE": {
"type": "string"
},
"SCALE_ON": {
"type": "int"
},
"MIN_REPLICAS": {
"type": "int"
},
"MAX_REPLICAS": {
"type": "int"
},
"CPU": {
"type": "string"
},
"MEMORY": {
"type": "string"
},
"CONTAINER_APP_NAME": {
"type": "string"
}
},
"resources": [
{
"apiVersion": "2023-05-01",
"type": "Microsoft.App/jobs",
"name": "[parameters('CONTAINER_APP_NAME')]",
"location": "[parameters('location')]",
"identity": {
"type": "None"
},
"properties": {
"environmentId": "[resourceId('Microsoft.App/managedEnvironments', parameters('environment_name'))]",
"configuration": {
"triggerType": "Event",
"replicaTimeout": 1800,
"replicaRetryLimit": 1,
"secrets": [
{
"name": "azp-url",
"value": "[parameters('azp_url')]"
},
{
"name": "azp-token",
"value": "[parameters('azp_token')]"
},
{
"name": "registry-password",
"value": "[parameters('REGISTRY_PASSWORD')]"
}
],
"registries": [
{
"server": "[parameters('REGISTRY_LOGIN_SERVER')]",
"username": "[parameters('REGISTRY_USERNAME')]",
"passwordSecretRef": "registry-password"
}
],
"eventTriggerConfig": {
"parallelism": 1,
"replicaCompletionCount": 1,
"scale": {
"minExecutions": "[parameters('MIN_REPLICAS')]",
"maxExecutions": "[parameters('MAX_REPLICAS')]",
"pollingInterval": 10,
"rules": [
{
"name": "azure-pipelines-scale-rule",
"auth": [
{
"secretRef": "azp-token",
"triggerParameter": "personalAccessToken"
},
{
"secretRef": "azp-url",
"triggerParameter": "organizationURL"
}
],
"type": "azure-pipelines",
"metadata": {
"organizationURL": "[parameters('azp_url')]",
"poolID": "[string(parameters('azp_poolId'))]",
"targetPipelinesQueueLength": "[string(parameters('SCALE_ON'))]"
}
}
]
}
}
},
"template": {
"containers": [
{
"image": "[parameters('IMAGE')]",
"imageType": "ContainerImage",
"name": "azure-pipelines-agent",
"volumeMounts": [
{
"volumeName": "data-volume",
"mountPath": "/data"
}
],
"env": [
{
"name": "AZP_URL",
"secretRef": "azp-url"
},
{
"name": "AZP_TOKEN",
"secretRef": "azp-token"
},
{
"name": "AZP_POOL",
"value": "[parameters('azp_pool')]"
},
{
"name": "AZP_POOLID",
"value": "[parameters('azp_poolId')]"
},
{
"name": "AZP_WORK",
"value": "/data/azp_work"
}
],
"resources": {
"cpu": "[parameters('CPU')]",
"memory": "[parameters('MEMORY')]"
}
}
],
"volumes": [
{
"name": "data-volume",
"storageType": "AzureDisk",
"diskSizeGB": 50
}
]
},
"workloadProfileName": "Consumption"
}
}
]
}
Here is the code I’m using to execute the above Arm Deployment:
#!/bin/bash
# Set POOLID based on deploymentPurpose
if [[ "${{ parameters.deploymentPurpose }}" == "DEV" ]]; then
POOLID=17
elif [[ "${{ parameters.deploymentPurpose }}" == "Test" ]]; then
POOLID=16
elif [[ "${{ parameters.deploymentPurpose }}" == "PROD" ]]; then
POOLID=14
else
POOLID=15
fi
echo "POOLID is set to $POOLID"
az extension add --name containerapp --yes
az provider register --namespace Microsoft.App
# Wait until the namespace registration is completed
while ! az provider show -n Microsoft.App --query "registrationState" -o tsv | grep -q "Registered"; do
echo "Waiting for Microsoft.App namespace registration to complete..."
sleep 10
done
AZP_URL="URL"
AZP_TOKEN=$(pattoken)
AZP_AGENT_NAME=${{ parameters.deploymentPurpose }}
AZP_POOL=${{ parameters.deploymentPurpose }}
REGISTRY_USERNAME=USERNAME
REGISTRY_PASSWORD=$(acrpassword)
REGISTRY_LOGIN_SERVER=ACRURL
IMAGE=IMAGEURL
CONTAINER_APP_NAME="devops-agent-$(echo "${{ parameters.deploymentPurpose }}" | tr '[:upper:]' '[:lower:]')"
MIN_REPLICAS="${{ parameters.minReplicas }}"
MAX_REPLICAS="${{ parameters.maxReplicas }}"
CPU="${{ parameters.cpu }}"
MEMORY="${{ parameters.memory }}Gi"
SCALE_ON="${{ parameters.scalePoint }}"
az deployment group create
--resource-group $RESOURCE_GROUP
--template-file "$(Build.SourcesDirectory)/src/DevOps/DevopsAgent/ContainerApp/containerapp.json"
--parameters
environment_name="$CONTAINERAPPS_ENVIRONMENT"
location="$REGION"
azp_url="$AZP_URL"
azp_token="$AZP_TOKEN"
azp_pool="$AZP_POOL"
azp_poolId="$POOLID"
REGISTRY_LOGIN_SERVER=$REGISTRY_LOGIN_SERVER
REGISTRY_USERNAME=$REGISTRY_USERNAME
REGISTRY_PASSWORD=$REGISTRY_PASSWORD
IMAGE=$IMAGE
SCALE_ON=$SCALE_ON
MIN_REPLICAS=$MIN_REPLICAS
MAX_REPLICAS=$MAX_REPLICAS
CPU=$CPU
MEMORY=$MEMORY
CONTAINER_APP_NAME=$CONTAINER_APP_NAME
I would appreciate it more than anything if someone could point out what is wrong with my template.
I did a deployment with the below commmand:
az containerapp job create
--name "$CONTAINER_APP_NAME"
--resource-group "$RESOURCE_GROUP"
--environment "$CONTAINERAPPS_ENVIRONMENT"
--trigger-type "Event"
--replica-timeout 1800
--replica-retry-limit 1
--registry-server "$REGISTRY_LOGIN_SERVER"
--registry-username "$REGISTRY_USERNAME"
--registry-password "$REGISTRY_PASSWORD"
--image "$IMAGE"
--cpu "$CPU"
--memory "$MEMORY"
--min-executions "$MIN_REPLICAS"
--max-executions "$MAX_REPLICAS"
--scale-rule-name "azure-pipelines-scale-rule"
--scale-rule-type "azure-pipelines"
--scale-rule-metadata "poolID=$POOLID" "targetPipelinesQueueLength=$SCALE_ON"
--scale-rule-auth "personalAccessToken=secretref:azp-token" "organizationURL=secretref:azp-url"
--secrets "azp-url=$AZP_URL" "azp-token=$AZP_TOKEN"
--env-vars "AZP_URL=secretref:azp-url" "AZP_TOKEN=secretref:azp-token" "AZP_POOL=$AZP_POOL" "AZP_POOLID=$POOLID" "AZP_AGENT_NAME=$AZP_AGENT_NAME"
This worked and I matched the output to my template and didn’t see any differences in the Schema.