Small big WTF in dynamic inventory for GCP
GCP stands for Google Cloud Platform.
They provides their own dynamic inventory source, which allows to query GCP for existing VMs and to put them into groups based on filters. The inventory plugin for this is called ‘gcp_compute
'.
It allows to set host variables based on available instance data (labels, name).
The most common is this:
compose:
ansible_host: networkInterfaces[0].accessConfigs[0].natIP
Boring and simple. I decided to add their something more. For example, a username.
compose:
ansible_host: networkInterfaces[0].accessConfigs[0].natIP
ansible_user: bot
It looked innocent and it almost worked. GCP wants here not a string, but a Jinja expression.
The problem is that bot
variable is not defined. And gcp_compute
is really nasty here. Instead of reporting the issue and rejecting to proceed, it just ignores the line. So, no bot
variable, no ansible_user
defined. In my case the problem was that ansible_user
is defined in different source, but I expected it to be redefined, and it wasn’t. What a mess I got myself into.
Anyway, the proper way to fix this is to use jinja expression (without mustaches):
compose:
ansible_host: networkInterfaces[0].accessConfigs[0].natIP
ansible_user: "'bot'"
Note, there are nested quotes, because first layer is stripped by yaml parser (Both ansible_user: bot
and ansible_user: "bot"
are the same), and only by adding second layer of quotes I get “a string” for Jinja.
If I wasn’t that much deep into Ansible machinery, that would have been a big fat WTF. At my current understanding it’s a minor quirk of google modules (which are unexpectedly lax toward Ansible best practices), and some eye rolling.