I have an Azure template that, among other things, defines a Public IP Address. I want to list that IP address in the template's output, but after the first deployment, I get an error message:
Message: Unable to evaluate template outputs: 'builderConnectionInformation'. Please see error details and deployment operations. Please see https://aka.ms/arm-debug for usage details.
Exception Details:
Error Code: DeploymentOutputEvaluationFailed
Message: The template output 'builderConnectionInformation' is not valid: The language expression property 'ipAddress' doesn't exist, available properties are 'provisioningState, resourceGuid, publicIPAllocationMethod, idleTimeoutInMinutes'..
Target: builderConnectionInformation
However, if I redeploy, it shows the output I wanted just fine:
Deployment completed. Outputs:
- builderConnectionInformation = {'Username': 'ExampleAdministrator', 'Password': '<PASSWORD>', 'Public IP Address': '1.2.3.4'}
Deployment details
I'm using a Python script and calling the Azure Python SDK to deploy. The whole script is here; the relevant bits are:
result = resource.resource_groups.create_or_update(
parsed.group_name, {'location': parsed.group_location})
template_params = {
'storageAccountName': parsed.storage_account_name,
'builderVmAdminPassword': parsed.builder_vm_admin_password,
'builderVmSize': parsed.builder_vm_size}
template_params = {k: {'value': v} for k, v in template_params.items()}
deploy_params = {
'mode': 'incremental',
'template': template,
'parameters': template_params}
async_operation = resource.deployments.create_or_update(
parsed.group_name, parsed.deployment_name, deploy_params)
result = async_operation.result()
msg = "Deployment completed. Outputs:"
for k, v in result.properties.outputs.items():
msg += f"\n- {k} = {str(v['value'])}"
print(msg)
A representation of my template can be found here. (Note: I actually am using a YAML template, but it's converted to a Python object before being used the same way that JSON is, and it works otherwise, so I don't think that's the problem.) The relevant parts (of the converted JSON template, since that's what everyone will be familiar with) are:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
...
"parameters": {
"builderVmAdminPassword": {
"type": "securestring"
},
...
},
"variables": {
"apiVersion": "2015-06-15",
"builderVmAdminUsername": "WinTrialAdmin",
"pubIpAddrName": "builderPubIp",
"pubIpAddrType": "Dynamic",
...
},
"resources": [
...
{
"type": "Microsoft.Network/publicIPAddresses",
"name": "[variables('pubIpAddrName')]",
"apiVersion": "[variables('apiVersion')]",
"location": "[resourceGroup().location]",
"properties": {
"publicIPAllocationMethod": "[variables('pubIpAddrType')]"
}
},
....
],
"outputs": {
"builderConnectionInformation": {
"type": "object",
"value": {
"Username": "[variables('builderVmAdminUsername')]",
"Password": "[parameters('builderVmAdminPassword')]",
"Public IP Address": "[reference(variables('pubIpAddrName')).ipAddress]"
}
}
}
What I've tried
I wondered if perhaps the public IP wasn't finished being allocated at the time the template deployment returns, but I didn't see a way to deal with that problem if that's what's happening - the only thing that occurred to me was to use a dependsOn
property of the output, but outputs do not support a dependsOn
property.
I have also found some information saying that instead of
"[reference(variables('pubIpAddrName')).ipAddress]"
I should use:
"[reference(variables('pubIpAddrName')).properties.ipAddress]"
However, that gives a similar result whether its the first time I have deployed, or any subsequent time. Here's the exact message for an initial deployment - note that it does not list ipAddress
as an available property:
Message: Unable to evaluate template outputs: 'builderConnectionInformation'. Please see error details and deployment operations. Please see https://aka.ms/arm-debug for usage details.
Exception Details:
Error Code: DeploymentOutputEvaluationFailed
Message: The template output 'builderConnectionInformation' is not valid: The language expression property 'properties' doesn't exist, available properties are 'provisioningState, resourceGuid, publicIPAllocationMethod, idleTimeoutInMinutes'..
Target: builderConnectionInformation
And here's the exact message from subsequent deployments - note that it does list an ipAddress
property:
Message: Unable to evaluate template outputs: 'builderConnectionInformation'. Please see error details and deployment operations. Please see https://aka.ms/arm-debug for usage details.
Exception Details:
Error Code: DeploymentOutputEvaluationFailed
Message: The template output 'builderConnectionInformation' is not valid: The language expression property 'properties' doesn't exist, available properties are 'provisioningState, resourceGuid, ipAddress, publicIPAllocationMethod, idleTimeoutInMinutes, ipConfiguration'..
Target: builderConnectionInformation
Summary
How can I make sure that the public IP address is always returned, even on the first deployment?
I tested in my lab and I get the same result as you. According to this link and this link on GitHub. This is a known limitation in the platform where a dynamic public IP address doesn't resolve itself until the VM is up and running. There are two options to workaround:
Create the Public IP Address in static mode. That will ensure that Public IP address is immediately allocated. However, note that you might incur additional charges.
Change the dependency from Public IP address to the Virtual Machine that the IP address is attached to. This will ensure that the public IP address is always available.
I suggest you use a static Public IP, I tested in my lab, and it works for me.
Change the vaule from
Dynamic
toStatic
.