Small big WTF in dynamic inventory for GCP

George Shuklin
OpsOps
Published in
1 min readJun 27, 2021

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.

--

--

George Shuklin
OpsOps

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux. My hobby is Rust.