Ansible 3.0 and beyond, a collections primer
The new project organization for Ansible can be somewhat confusing, here's a guide!
Background
Ansible is a configuration management (CM) tool used to make changes to remote hosts in an idempotent manner. It's a tool that I use on a daily basis and quite frankly is one of my favorite pieces of software. Ansible is extensible, has a fantastic community and is quite easy to get acquainted with for new users.
This article is aimed at those who may be using Ansible but don't follow the in's and out's of the project at-large.
Recently, there has been a shift in the way Ansible was released. Originally Ansible would ship with all modules to perform tasks in its installation package. That presented a whole host (๐) of issues for the Ansible team. These challenges (maintainability, size of the package, scalability, etc.) for the Ansible Team are being addressed by the changes. If you are curious about the underlying reasons, and wish to get a better understanding of what is happening, the team has outlined their methodology in a blog post.
The change will cause some confusion and mild heartburn (mostly around changing to the FQCN, Fully-Qualified Collection Name format in playbooks or commands). One might upgrade to a version that moved to this format and suddenly playbooks no longer function (see the Troubleshooting section for what I mean).
So this post is meant to be a guide on what is changing for those of us who work day-to-day in the tool. Let's get started!
Updating to the new version, along with installation changes
To move to the new version, and you are currently running Ansible 2.9, you will need to uninstall Ansible first.
As of this writing, on CentOS 8 yum
(or now dnf
) will install 2.9.18-2 from the epel
repository. This also goes for the Ubuntu PPA. As a result, I would recommend sticking to the pip
installation rather than via a package manager:
$ pip3 install ansible=3.0.0
If you need to use multiple versions of Ansible on the same machine, please use python virtual environments or use a docker container.
Ansible-base versus Ansible-core?
As of today, the package is ansible-base
. However, please note this is changing to ansible-core
in the very short term (with the upcoming release of version 2.11). As the changes march on, expect to use ansible-core
and think of the the package as containing only the 'core' modules in Ansible either way.
Personally, I find it "easier" (though it will not be technically correct) to just think of this as a rename operation for the package as part of the migration.
Collections
Collections are a new type of categorization for modules utilizing namespaces. As alluded to above, Ansible used to include all of its modules in the package. This is no longer going to be the case using the ansible-core
/ansible-base
packages. If you install the ansible
pip3 package, there are some modules included from the Community (more on that later).
Before
Let's take a look at the format of using a module in a playbook before upgrading to the new FQCN system:
- name: Print hostname of remote system
hostname:
name: "{{ inventory_hostname }}"
The above code will use the hostname
module. It will print the Ansible fact (a variable), inventory_hostname
.
After
The new method will change to:
- name: Print hostname of remote system
ansible.builtin.hostname:
name: "{{ inventory_hostname }}"
Notice the new format? We've added ansible.builtin.
to the hostname module. The change corresponds to the new builtin modules that will ship with ansible-core
(or ansible-base
for the time being).
Optionally, with builtin modules, you do not need to specify the FQCN value (the ansible.builtin.
portion) either on the command-line, in a play or in a playbook.
However, I highly recommended that you do so anyway to maintain clean code for others as they may not be familiar with this slight difference - especially beginners. You will see that these are referenced in official documentation with the FQCN, so the Ansible team recognizes this fact.
Package / Module Installation locations
If you've installed Ansible 2.9 via a package manager (e.g., yum) or via the Python Package Manager (pip3), module locations for the package manager and pip3 are found in
/usr/lib/python3.6/site-packages/ansible/modules/
With the new installation of 3.0, via the pip3 installation, are located in
/usr/local/lib/python3.6/site-packages/ansible
TIP: ansible --version
will always show you the location of these directories.
Why does ansible --version
display 2.10+?
ansible --version
will return the version of ansible-core
/ansible-base
, not the version of the Ansible package.
You can see this in action by running the command pip3 list ansible
:
# ansible-base
$ pip3 list ansible
Package Version
------------ -------
ansible-base 2.10.7
or
# ansible-core
$ pip3 list ansible
Package Version
------------ --------
ansible-core 2.11.0b4
What is now built-in?
A list of built-in modules can be found here.
If you've only installed the ansible-base
/ansible-core
package via pip3, you will need to install additional collections using the new command:
ansible-galaxy collection install my_namespace.my_collection
So, to install the Chocolatey namespace and collection, one would use the following command:
ansible-galaxy collection install chocolatey.chocolatey
The default installed directory for collections installed via the command above are located at ~/.ansible/collections
or /usr/share/ansible/collections
.
What about the ansible
package?
If you've installed the ansible
package via pip3, there are a quite a few community modules included! This is supposed to be the "new" semi-inclusive Ansible package but still allows the Ansible Team the ability to break modules up into more manageable pieces for maintainability (instead of say, one big git repository with 1000s of issues).
If you have the ansible
pip3 package, you will see the following:
# ansible with community packages as well as the base package
$ pip3 list ansible
Package Version
------------ -------
ansible 3.2.0
ansible-base 2.10.7
There are a list of redirections that Ansible performs for several modules here.
For more information see here for how module utilities are developed.
Again -- if you ever have doubts about the installed modules included on your installation, I advise looking to the paths above in the package location heading.
Of course if you have a custom-developed collection, you would use the ansible-galaxy
command above to install this collection via a URL or tarball. As a reminder this command is my_namespace.my_collection
, substituting as appropriate.
ansible-galaxy collection install my_namespace.my_collection
Keeping up with Ansible
Ansible is moving with a fast cadence. I highly recommend subscribing to the Bullhorn. You can do so here. This newsletter is fantastic.
Feel free to keep up to date via other methods (such as mailing lists or IRC) here.
Troubleshooting
If you have already upgraded but now run into an error like ImportError: cannot import name 'AnsibleCollectionLoader'
This is because your play or playbook is more than likely referencing the old 'short-name' format and not using the FQCN in your playbook or play.
Closing
This entire process is a shift. But it is a necessary one. I hope this has helped you understand the underlying changes!
Thank you for reading! ๐