Ansible GCP module bootstrap

Artem Yakimenko
2 min readJun 11, 2018

--

The official docs on Ansible GCP module are a bit confusing, so I’ve decided to publish some steps to quickly bootstrap a working environment.

Main concept is that Ansible can not only use static files as a source of inventory but also execute a script and use it’s output as an in-memory representation of it. This allows us to make dynamic inventories to load up hosts from your cloud provider, for example. And, conveniently, there’s such a script in the Ansible’s contrib directory named gce.py.

This assumes you already have:

  • Ansible installed
  • A working python installation
  • Have a service account with Compute Engine API access
  • Exported a JSON key in Credentials subsection of your console

Here are quick bootstrap instructions on how to get it working:

Install libcloud and libcrypto:

λ pip install apache-libcloud pycrypto

Create a working dir:

λ mkdir -p ansible/inventory && cd ansible

Clone ansible repo:

λ git clone https://github.com/ansible/ansible

Copy the gcp.py inventory script and the gcp.ini template from contrib folder:

λ cp ansible/contrib/inventory/gce.* inventory

Populate the .ini file (this is where gce.py will read its’ settings from):

λ cat ~/.ansible/gce.ini[gce]
gce_service_account_email_address = my-account@my-project.iam.gserviceaccount.com
gce_service_account_pem_file_path = /full/path/to/my_key.json
gce_project_id = my-project
[inventory]
# Use external IP addresses to connect
inventory_ip_type = external
[cache]
cache_path = ~/.ansible/tmp
cache_max_age = 300

You can move it into your home directory and exporting the variable in your .zshrc for future ease-of-use:

λ cat ~/.zshrc | grep gce.ini# Export ansible gce.ini[[ -s "$HOME/.ansible/gce.ini" ]] && export GCE_INI_PATH="$HOME/.ansible/gce.ini"

Reload your shell and check if it’s working:

λ source ~/.zshrcλ ./inventory/gce.py --list

If you’ve received a large set of output with your instance data — it’s now set up correctly.

Boom, now you can access your instances by zone:

λ ansible -i inventory australia-southeast1-c -m pingweb-worker-3 | SUCCESS => {
"changed": false,
"ping": "pong"
}
web-worker-1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
web-worker-2 | SUCCESS => {
"changed": false,
"ping": "pong"
}
master | SUCCESS => {
"changed": false,
"ping": "pong"
}

, or tag. For that just prepend the network tag name with tag_, i.e. for web-worker tag:

λ ansible -i inventory tag_web-worker -m pingweb-worker-3 | SUCCESS => {
"changed": false,
"ping": "pong"
}
web-worker-1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
web-worker-2 | SUCCESS => {
"changed": false,
"ping": "pong"
}

For more options and further reading, check out the official module docs.

Hope it’s helpful!

Materials used:

--

--

Artem Yakimenko

Solutions engineer with a focus on modern Operations. Open source contributor. Sharing my knowledge, thoughts and general insanity in slightly longer bursts.