Skip to content

Instantly share code, notes, and snippets.

@b0bu
Last active May 9, 2021 17:33
Show Gist options
  • Save b0bu/3a1a01693623bd66cb45123b597b66f1 to your computer and use it in GitHub Desktop.
Save b0bu/3a1a01693623bd66cb45123b597b66f1 to your computer and use it in GitHub Desktop.
using import_playbook with ansible collections

getting set up

As of this writing

# requirements.txt
ansible==3.3.0

Install ansible (personally I use pyenv virtual envs to create a clean environment but you can do what you like)

pip install -r requirements.txt

This will install ansible-base however we need ansible-core

pip uninstall ansible-base
pip install ansible-core

Packages:

pip freeze | grep ansible
ansible==3.3.0
ansible-core==2.11.0

The name matter (at least in 2.11)

In a collection the name you use for your playbooks matters. As of ansible-core 2.11, line 792 of _collection_finder.py if not AnsibleCollectionRef.is_valid_fqcr(ref, ref_type):

is_valid_fqcr() returns a bool() and is True if the passed in ref matches a regex. This ref is your fqcn and is read in from the - import_playbook statement in your playbook.

from is_valid_fqcr() we can see return bool(re.match(AnsibleCollectionRef.VALID_FQCR_RE, ref)) this VALID_FQCR_RE is shown below where "match" would be the returned obj of the function.

>>> match = bool(re.match(re.compile('^\\w+(\\.\\w+){2,}$'), 'mycompany.base_roles.on-prem'))
>>> match
False
>>> # underscore and dashes fail the match
>>> match = bool(re.match(re.compile('^\\w+(\\.\\w+){2,}$'), 'mycompany.base.onprem'))
>>> match
True
>>> # valid name

Note that the name of my collection in this case "base" and the playbook name in this case "on_prem" are valid if it has underscore but not dashes. Also note that the collection name can be further nested

>>> match = bool(re.match( re.compile('^\\w+(\\.\\w+){2,}$'), 'mycompany.base_base.onprem'))
>>> match
True
>>> match = bool(re.match( re.compile('^\\w+(\\.\\w+){2,}$'), 'mycompany.on_prem_nested_1.on_prem_nested_2.onprem'))
>>> match
True

If there's a dash, it'll break and the bool() will return False.

>>> match = bool(re.match( re.compile('^\\w+(\\.\\w+){2,}$'), 'mycompany.base-base.on_prem.onprem'))
>>> match
False
>>> match = bool(re.match( re.compile('^\\w+(\\.\\w+){2,}$'), 'mycompany.base_base.on_prem.on-prem'))
>>> match
False

Collection layout

.
├── galaxy.yml
├── meta
│   └── runtime.yml
├── playbooks
│   └── onprem.yml
├── README.md
└── roles
    ├── role2
    └── role1

Within this collection, onprem.yml can be used in CI to test our changes to the collection. But can also be used as an importable resource. Creating a github release for your collection in this case 0.0.3.alpha.1 and corresponding collections.yml file so that it can be easily consumed by other ansible repos. In another repo with a playbook named playbook.yml I have the following requirements file:

---
collections:
  - name: git@github.com:mycompany/base.git
    type: git
    version: 0.0.3.alpha.1

I can install this collection with

ansible-galaxy collection install -r collections.yml

The galaxy.yml is typical and how you'd expect it to be.

namespace: "mycompany"
name: "base"
version: "0.0.3"
readme: "README.md"
authors:
    - "b0bu"
license:
    - "MIT"
tags:
    - demo
    - collection
repository: "git@github.com:mycompany/base.git"

For a quick feedback loop we can test our changes and build this collection locally then install it. From the root of the tree where galaxy.yml is located run:

ansible-galaxy collection build

This will produce a tar.gz file you can install with

ansible-galaxy collection install mycompany-0.0.3.tar.gz

Based on the galaxy.yml above we can import our playbook like so:

---
# playbook.yml
- import_playbook: mycompany.base.onprem

Test playbook locally

ansible-playbook playbook.yml --connection=local --inventory 127.0.0.1, -CD --ask-pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment