Abstract
| Goal |
Write your own Ansible Content Collections, publish them, embed them in a custom automation execution environment, and run them in playbooks by using automation controller. |
| Objectives |
|
| Sections |
|
| Lab |
|
Red Hat, its partners, and the Ansible community provide Ansible Content Collections for many software products and technologies. However, customers often have automation needs that no existing collection covers. For example, you might have to pilot an application for which there is no available collection, or your company might develop internal tools that you need to automate. In all those situations, you should consider developing collections.
Ansible 2.8 and earlier do not support collections. With those versions, you develop and distribute individual roles and provide modules and plug-ins inside those roles or alongside your playbooks.
Red Hat still supports that architecture but recommends moving your roles, modules, plug-ins, and filters inside collections. Automation hub and private automation hub do not support individual roles.
Remember that Ansible organizes collections in namespaces.
The namespace is the first part of a collection name.
For example, the namespace of the amazon.aws collection is amazon.
Carefully choose a namespace for grouping your collections:
If you plan to publish your collections to Ansible Galaxy, then use your Ansible Galaxy username as the namespace.
If you publish your collections to private automation hub, then ask the platform administrators to create a namespace for you. Note that you might be able to create a namespace yourself if your user account has the required permissions.
If you are a Red Hat partner and publish your collections to automation hub, then use the namespace that Red Hat has assigned for your company.
Use the ansible-galaxy collection init command to create the directory structure for your new collection.
Specify the name of the collection, including the namespace, as the argument to the command:
[user@host ~]$ ansible-galaxy collection init mynamespace.mycollection
- Collection mynamespace.mycollection was created successfullyThis command creates the collection and organizes content in the following directory and file structure:
[user@host ~]$tree mynamespace/mynamespace/ └── mycollection ├── docs├── galaxy.yml
├── plugins
│ └── README.md ├── README.md
└── roles
4 directories, 3 files
The | |
The | |
The | |
The | |
The |
You can remove the files and directories that you are not using.
For example, if there are no roles in your collection, then you can remove the roles/ directory.
Organize the modules, plug-ins, and filters that you develop in subdirectories under the plugins/ directory.
For modules, create the plugins/modules/ subdirectory and then copy the Python scripts for your modules into that subdirectory.
For inventory plug-ins, create and then use the plugins/inventory/ subdirectory.
Similarly, the other plug-in types have dedicated subdirectories.
Developing modules, plug-ins, and filters is beyond the scope of this course.
If you have existing roles, then you can move their directory structure under the roles/ directory.
To create a role for the collection, use the ansible-galaxy role init command from inside the roles/ directory:
[user@host ~]$cd mynamespace/mycollection/roles/[user@host roles]$ansible-galaxy role init myrole- Role myrole was created successfully [user@host roles]$ls myrole/defaults files handlers meta README.md tasks templates tests vars
The galaxy.yml YAML file at the root of the collection directory provides information for Ansible to build and publish the collection.
The file includes comments that describe each parameter.
The following galaxy.yml file is a complete example:
--- namespace: mynamespace name: mycollection version: 1.0.0 readme: README.md authors: - your name <example@domain.com> description: Ansible modules to manage my company's custom software license: - GPL-3.0-or-later repository: https://git.example.com/training/my-collection # The URL to any online docs documentation: https://git.example.com/training/my-collection/tree/main/docs # The URL to the homepage of the collection/project homepage: https://git.example.com/training/my-collection # The URL to the collection issue tracker issues: https://git.example.com/training/my-collection/issues dependencies: community.general: '>=1.0.0' ansible.posix: '>=1.0.0'
Some collections depend on other collections to work correctly.
For example, a role in your new collection might call modules from other collections.
Declare all those required collections by using the dependencies parameter in your galaxy.yml file.
That parameter is a dictionary of collections.
For each entry, the key is the collection FQCN, and the value is the collection version (use >=1.0.0 when you do not need a specific version).
The following example lists the community.general and ansible.posix collections as requirements:
...output omitted... dependencies: community.general: '>=1.0.0' ansible.posix: '>=1.0.0' ...output omitted...
You do not need to declare the ansible.builtin collection.
More complex collections might provide modules, plug-ins, and filters that depend on additional Python libraries.
Users must install the corresponding Python packages in the execution environment before they can use the collection.
For example, the amazon.aws collection uses the Amazon Web Services Software Development Kit (SDK) that the boto Python package provides.
If you are using the ansible-playbook command, or the ansible-navigator command with the --ee false option, the execution environment is the same as the control node and these Python components need to be installed on the control node.
Otherwise, these resources need to be installed in the execution environment that you are using with that collection.
The supported execution environments provide all the Python dependencies and other tools needed for the content collections that they include by default.
For those Python dependencies, create a requirements.txt file at the root of your collection.
Each line of the file declares a Python package.
The following example shows the content of the requirements.txt file for the amazon.aws collection.
At the end of the package name, the version part is optional if you do not require a specific version.
botocore>=1.18.0 boto3>=1.15.0 boto>=2.49.0
Some collections also require system-level packages in the execution environment.
For example, the ansible.posix collection requires the rsync RPM package.
At the root of your collection, create the bindep.txt file and list the RPM packages, one per line.
The following example shows the content of the bindep.txt file for the ansible.posix collection.
rsync [platform:centos-8 platform:rhel-8]
The bindep tool, which processes the bindep.txt file, can manage packages for several Linux distributions.
Different distributions might have other package names for the same software.
In the preceding file, the [platform:centos-8 platform:rhel-8] directive provides the name of the Linux distributions.
Another standard directive is [platform:rpm], which targets all the Linux distributions that use the RPM packaging system.
When a user or the automation controller runs the ansible-galaxy collection install command to install your collection, the command automatically installs the additional collections that you have declared in the galaxy.yml file.
However, the command does not process the requirements.txt file for Python packages or the bindep.txt file for system packages.
On the other hand, the ansible-builder command that you run to create automation execution environments uses all those files.
Another section of this course discusses the execution environment builder in more detail.
You can define additional metadata for the collection in the meta/runtime.yml file.
If your collection requires a specific version of Ansible, then add the requires_ansible parameter to the file.
The following example specifies that the collection works with Ansible 2.10 or later.
--- requires_ansible: ">=2.10"
Because the ansible-galaxy collection init command does not create the meta/ directory, you must create it yourself, as well as the runtime.yml file.
The meta/runtime.yml file and the requires_ansible parameter are mandatory if you plan to publish your collection to Ansible Galaxy, automation hub, or private automation hub.
Otherwise, the validation process that those platforms run rejects the collection.
From inside the collection directory, run the ansible-galaxy collection build command to prepare the collection:
[user@host mycollection]$ ansible-galaxy collection build
Created collection for mynamespace.mycollection at /home/user/mynamespace/mycollection/mynamespace-mycollection-1.0.0.tar.gzYou can use the resulting .tar.gz file to install and test the collection locally, to share the collection with team members, or to publish it to a distribution platform such as Ansible Galaxy or private automation hub.
When you publish your collection to Ansible Galaxy, automation hub, or private automation hub, the platforms automatically run some tests.
For example, private automation hub uses the ansible-lint tool to verify that your collection conforms to the standards and good practices that the Ansible team establishes.
The distribution platform publishes the resulting report alongside the collection.
The following output shows an import log for the mynamespace.mycollection collection.
Importing with galaxy-importer 0.4.4 Getting doc strings via ansible-doc Finding content inside collection Loading role myrole Linting role myrole via ansible-lint... roles/myrole/tasks/main.yml:3: fqcn-builtins Use FQCN for builtin actions. roles/myrole/tasks/main.yml:3: risky-file-permissions File permissions unset or incorrect. CHANGELOG.rst file not found at top level of collection. Collection loading complete Done
If the import log displays the messages Collection loading complete and Done, then the collection uploaded successfully.
Notice that the log produces warnings about fqcn-builtins and risky-file-permissions.
Although not required, you might update the collection to fix any reported problems.
If your collection does not include a CHANGELOG.rst file, then the import log displays the message: CHANGELOG.rst file not found at top level of collection.
Because this file is not required, you can safely ignore this message.
You can find information about generating change logs in the References section.
For collections that Red Hat partners develop, automation hub tests more thoroughly using the ansible-test tool.
The Ansible team recommends that you install and then use those tools before publishing your collections. In addition, some community projects also run those tools and reject contributions that do not pass the tests.
At a minimum, install your collection on a test system from the .tar.gz file, and then develop a playbook that uses the collection and demonstrates that it works as expected.
To test your collection in playbooks, you cannot directly use the collection from your development directory by pointing the collections_paths directive in the ansible.cfg configuration file to that working directory.
You first need to build and then install the collection from the .tar.gz file.
Use the distribution platform web UI to publish your collection from the .tar.gz file.
For private automation hub, navigate to → , select your namespace, click , and then provide the .tar.gz file.
Before users can use your collection, an administrator must review and approve it.
If your user account has that permission, then navigate to → .
You can view the import log, which displays the result of the ansible-lint validation, and then approve or reject the collection.
Whenever you modify your collection, edit the galaxy.yml file and update the version parameter.
The distribution platform rejects your collection otherwise.
Create a .tar.gz archive and then publish the new version.
[user@host mycollection]$cat galaxy.yml--- namespace: mynamespace name: mycollectionversion: 2.0.0readme: README.md authors: - your name <example@domain.com> ...output omitted... [user@host mycollection]$ansible-galaxy collection buildCreated collection for mynamespace.mycollection at /home/user/mynamespace/mycollection/mynamespace-mycollection-2.0.0.tar.gz
As an alternative to uploading a collection archive file using the private automation hub web UI, the ansible-galaxy command also supports publishing collections.
Update your Ansible configuration file to contain settings similar to the following.
Your server_list line might contain additional servers.
[galaxy] server_list = inbound_mynamespace [galaxy_server.inbound_mynamespace] url=https://hub.lab.example.com/api/galaxy/content/inbound-mynamespace/ token=<put your token here>
The private automation hub web UI displays the inbound URL for your namespace.
Navigate to → , click the link for the desired namespace, and then click the tab.
Retrieve your API token from the private automation hub web UI.
Navigate to → and click .
Update the token line with your authentication token.
Run the ansible-galaxy collection publish command to publish your collection to Ansible Galaxy or private automation hub.
Notice that the command output displays the same messages as the private automation hub web UI import log.
[user@host mycollection]$ansible-galaxy collection \>publish mynamespace-mycollection-2.0.0.tar.gz...output omitted... [WARNING]: Galaxy import warning message: roles/myrole/tasks/main.yml:3: fqcn-builtins Use FQCN for builtin actions. [WARNING]: Galaxy import warning message: roles/myrole/tasks/main.yml:3: risky-file-permissions File permissions unset or incorrect. [ERROR]: Galaxy import error message: CHANGELOG.rst file not found at top level of collection. Collection has been successfully published and imported to the Galaxy server inbound_mynamespace https://hub.lab.example.com/api/galaxy/content/inbound-mynamespace/