azure_rm_virtualmachine tags weirdness

Hi,

Not sure yet if what I have here is a bug or not, so thought I’d ask first. I’m seeing a strange failure out of azure_rm_virtualmachine in the latest ansible devel. The working playbook looks as follows:

  • name: Create VM and attach NIC
    azure_rm_virtualmachine:
    resource_group: ‘{{ rg }}’
    name: ‘{{service_name}}-vm-{{item}}’
    network_interface_names: ‘{{service_name}}-vm-{{item}}-nic’
    storage_account: ‘{{ env_name }}’
    vm_size: Standard_DS1_v2
    admin_username: hoylu
    ssh_password_enabled: False
    ssh_public_keys: ‘{{ssh_keys}}’
    image:
    offer: UbuntuServer
    publisher: Canonical
    sku: ‘16.04-LTS’
    version: latest
    tags:
    env: ‘{{env}}’
    service: ‘{{service}}’
    with_sequence:
    start=1
    end=‘{{count}}’
    stride=1
    format=%02d

This code runs. When I then change the tags: section of the playbook task to a dictionary that looks like the following:
tags: ‘{{ { “env”: env, service: env } }}’

I get an error that looks like this:

“module_stderr”: “Traceback (most recent call last):\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_GI_w3r/ansible_module_azure_rm_virtualmachine.py", line 1311, in \n main()\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_GI_w3r/ansible_module_azure_rm_virtualmachine.py", line 1308, in main\n AzureRMVirtualMachine()\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_GI_w3r/ansible_module_azure_rm_virtualmachine.py", line 554, in init\n supports_check_mode=True)\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_GI_w3r/ansible_modlib.zip/ansible/module_utils/azure_rm_common.py", line 197, in init\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_GI_w3r/ansible_module_azure_rm_virtualmachine.py", line 797, in exec_module\n vm_id=vm_dict[‘properties’][‘vmId’],\nKeyError: ‘vmId’\n”,

This error only happens with the azure_rm_virtualmachine module. The azure_rm_publicipaddress and azure_rm_networkinterface modules are both fine with that change. Is there some vagary of azure I’m not aware of that’s biting me here, or does this look like a bug to folks?

Thanks,

Marcin

I’d suggest double checking that you have the same versions of the azure pip module that the documents say is required.

I’m guessing the error

vm_id=vm_dict[‘properties’][‘vmId’],\nKeyError: ‘vmId’\n"

means its looking for something called vmId and not finding it.

I’m not familiar with the azure stuff unfortunately.

Hope this helps,

Jon

Hrm, kinda looks like a templating bug (or a bad template value)- pretty sure it’s not a module bug since it’s working with the discrete dict.

Can you run that both ways in check_mode with -vv and look at the tags element in the invocation value from the result to see if it looks the same in both cases? If it works with the discrete dict and fails with the templated one, I’m guessing that the templated arg isn’t getting rendered in the right shape to the module.

-Matt

Hi Matt,

Tried what you suggested. Here’s what I get for azure_rm_publicipaddress, which works in both instances. Both tasks are in the same playbook, so they’re executed one right after the other with the same args.

  1. discrete tags dict: “tags”: {“env”: “dev”, “service”: “foo”}
  2. templated tags: “tags”: {“env”: “dev”, “foo”: “dev”}

For azure_rm_virtualmachine, which breaks with templated:

  1. discrete tags dict: “tags”: {“env”: “dev”, “service”: “foo”}
  2. templated tags: blew up, -vv does not show what it tried to send

Running with -vvv, I get the following:

ASK [Create VM and attach NIC] ***************************************************************************************************************************************************************************************************************
task path: /Users/mkporwit/work/infra/ansible/azure/create_vm.yml:46
Using module file /usr/local/lib/python2.7/site-packages/ansible-2.4.0-py2.7.egg/ansible/modules/cloud/azure/azure_rm_virtualmachine.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: mkporwit
<127.0.0.1> EXEC /bin/sh -c ‘echo ~ && sleep 0’
<127.0.0.1> EXEC /bin/sh -c ‘( umask 77 && mkdir -p “echo /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610965.68-33490890086942” && echo ansible-tmp-1491610965.68-33490890086942=“echo /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610965.68-33490890086942” ) && sleep 0’
<127.0.0.1> PUT /var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/tmpnQtd7v TO /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610965.68-33490890086942/azure_rm_virtualmachine.py
<127.0.0.1> EXEC /bin/sh -c ‘chmod u+x /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610965.68-33490890086942/ /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610965.68-33490890086942/azure_rm_virtualmachine.py && sleep 0’
<127.0.0.1> EXEC /bin/sh -c ‘/usr/local/opt/python/bin/python2.7 /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610965.68-33490890086942/azure_rm_virtualmachine.py; rm -rf “/Users/mkporwit/.ansible/tmp/ansible-tmp-1491610965.68-33490890086942/” > /dev/null 2>&1 && sleep 0’
The full traceback is:
Traceback (most recent call last):
File “/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_module_azure_rm_virtualmachine.py”, line 1310, in
main()
File “/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_module_azure_rm_virtualmachine.py”, line 1307, in main
AzureRMVirtualMachine()
File “/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_module_azure_rm_virtualmachine.py”, line 554, in init
supports_check_mode=True)
File “/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_modlib.zip/ansible/module_utils/azure_rm_common.py”, line 197, in init
File “/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_module_azure_rm_virtualmachine.py”, line 796, in exec_module
vm_id=vm_dict[‘properties’][‘vmId’],
KeyError: ‘vmId’
failed: [localhost] (item=01) => {
“failed”: true,
“item”: “01”,
“module_stderr”: “Traceback (most recent call last):\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_module_azure_rm_virtualmachine.py", line 1310, in \n main()\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_module_azure_rm_virtualmachine.py", line 1307, in main\n AzureRMVirtualMachine()\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_module_azure_rm_virtualmachine.py", line 554, in init\n supports_check_mode=True)\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_modlib.zip/ansible/module_utils/azure_rm_common.py", line 197, in init\n File "/var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/ansible_24PReY/ansible_module_azure_rm_virtualmachine.py", line 796, in exec_module\n vm_id=vm_dict[‘properties’][‘vmId’],\nKeyError: ‘vmId’\n”,
“module_stdout”: “”,
“msg”: “MODULE FAILURE”,
“rc”: 0
}
to retry, use: --limit @/Users/mkporwit/work/infra/ansible/azure/create_vm.retry

I don’t think this show any more additional information. What stumps me is why this same templating would be OK for other resources, but not azure_rm_virtualmachine. That’s what makes me think this might be a bug. I can create such a tag manually in the azure portal, so I’m pretty sure the key=value pair I’m trying to set is acceptable to azure.

Here’s the -vvv output for a working templated invocation of azure_rm_publicipaddress. You’ll see the invocation params happily take the templated tags, and see in the state block that they were applied correctly.

TASK [Create public ip for vm] ****************************************************************************************************************************************************************************************************************
task path: /Users/mkporwit/work/infra/ansible/azure/create_vm.yml:14
Using module file /usr/local/lib/python2.7/site-packages/ansible-2.4.0-py2.7.egg/ansible/modules/cloud/azure/azure_rm_publicipaddress.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: mkporwit
<127.0.0.1> EXEC /bin/sh -c ‘echo ~ && sleep 0’
<127.0.0.1> EXEC /bin/sh -c ‘( umask 77 && mkdir -p “echo /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610957.8-260047672053181” && echo ansible-tmp-1491610957.8-260047672053181=“echo /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610957.8-260047672053181” ) && sleep 0’
<127.0.0.1> PUT /var/folders/06/zm5r71tj60b4_19wlz7h822m0000gn/T/tmpMIvukr TO /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610957.8-260047672053181/azure_rm_publicipaddress.py
<127.0.0.1> EXEC /bin/sh -c ‘chmod u+x /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610957.8-260047672053181/ /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610957.8-260047672053181/azure_rm_publicipaddress.py && sleep 0’
<127.0.0.1> EXEC /bin/sh -c ‘/usr/local/opt/python/bin/python2.7 /Users/mkporwit/.ansible/tmp/ansible-tmp-1491610957.8-260047672053181/azure_rm_publicipaddress.py; rm -rf “/Users/mkporwit/.ansible/tmp/ansible-tmp-1491610957.8-260047672053181/” > /dev/null 2>&1 && sleep 0’
ok: [localhost] => (item=01) => {
“changed”: false,
“invocation”: {
“module_args”: {
“ad_user”: null,
“allocation_method”: “Static”,
“append_tags”: true,
“client_id”: null,
“domain_name”: “hoyludevmkp-foo-vm-01”,
“domain_name_label”: “hoyludevmkp-foo-vm-01”,
“location”: null,
“name”: “hoyludevmkp-foo-vm-01-ip”,
“password”: null,
“profile”: null,
“resource_group”: “hoylu-dev-mkp”,
“secret”: null,
“state”: “present”,
“subscription_id”: null,
“tags”: {
“env”: “dev”,
“foo”: “dev”
},
“tenant”: null
}
},
“item”: “01”,
“state”: {
“dns_settings”: {
“domain_name_label”: “hoyludevmkp-foo-vm-01”,
“fqdn”: “hoyludevmkp-foo-vm-01.westus2.cloudapp.azure.com”,
“reverse_fqdn”: null
},
“etag”: “W/"7c3db6aa-7057-49c2-8cf4-7c5b0b03e88e"”,
“idle_timeout_in_minutes”: 4,
“ip_address”: “52.183.90.100”,
“location”: “westus2”,
“name”: “hoyludevmkp-foo-vm-01-ip”,
“provisioning_state”: “Succeeded”,
“public_ip_allocation_method”: “Static”,
“tags”: {
“env”: “dev”,
“foo”: “dev”
},
“type”: “Microsoft.Network/publicIPAddresses”
}
}

So, here’s the kicker…

Switched from devel to stable-2.3, and I’m able to provision using the templated tags. Switch back to devel, and I’m still able to use the templated mechanism.

So, probably not a bug. Rather, some edge case interplay between the various python dependencies?

Possibly- if you’re running from source, make sure you’re running the hacking/env-setup script each and every time you pull new changes in. Otherwise there can be stale .pyc files and other things laying around that can wreak all sorts of havoc (the script cleans all that up).

As it turns out, this seems to have more to do with the fact that VM updates don’t seem to work. I was able to repro this with a simpler playbook that had nothing to do with the templating:

https://github.com/ansible/ansible/issues/23765

and found a similar issue(https://github.com/ansible/ansible/issues/20444), which actually already has a fix (https://github.com/ansible/ansible/pull/22974), it just hasn’t been merged yet. Applying that fix makes the tag issue go away as well. It’s a very simple fix, so it would be nice if it could get merged.

thanks,
Bjørn

The same vmId error came back when we tried some more tags-related things. Not sure why tags tickle it, but it seems there’s an issue with how ansible calls the azure SDK (https://github.com/ansible/ansible/pull/22974). We can confirm that merging this fix resolves the issues we’re having in devel and stable-2.3, and does not appear to introduce any new issues. Hope it gets picked up for a merge into 2.3 final…