Featured Image: Ansible Tower inventory plugin

Packaging Ansible Playbooks within a collection is the best way to distribute reusable automation content. To avoid naming conflicts, developers organize collections inside namespaces. Sometimes situations arise where you need to migrate a collection from one namespace to another, such as a personal or community collection graduating to a more well known or certified namespace.

Altering the namespace can be a tedious task. However, the Fully Qualified Collection Name (FQCN) migration tool simplifies this process by utilizing the fqcn_migration command. Employing a straightforward configuration file transforms an entire collection from one namespace to another. This article introduces the tool and demonstrates how to use it.

Case story

Let’s assume we have a collection called useful_stuff living in a community namespace. It has proven valuable to the Ansible community for several years, so there was a decision to move its content from the community namespace to the ansible namespace. The migration also presents the opportunity to rename the collection, as its current one was deemed not applicable in the destination namespace.

The content of useful_stuff adheres to the best practices and conventions associated with Ansible collections, which means that all the roles it contains are prefixed by the collection name (useful_stuff_role_name) and all variables inside the role are also prefixed with the role name (useful_stuff_varname).

On top of the runnable Ansible content, the name of the collection and its namespace appears in other files, such as the galaxy.yml metadata file as well as within the included documentation resource. Also, as a result of the namespace change, a few URLs will need to be updated.

Using FQCN migration to alter the collection content

To ease the migration from community.useful_stuff to ansible.helpful_things, we are going to use the FQCN migration tool. First, we’ll need to install it. The tool is packaged as a collection and requires to be available on the system that we will utilize to perform the migration:

$ ansible-galaxy collection install community.fqcn_migration

Once the collection is installed on the system, use the included playbook from within the collection and set several variables properly. Let’s create a playbook called playbook.yml with the following content:

---
- ansible.builtin.import_playbook: community.fqcn_migration.fqcn_migration
  vars:
    upstream_name: useful_stuff
    downstream_name: helpful_things
    upstream_namespace: 'community'
    downstream_namespace: 'ansible'
    project_git_url: https://github.com/ansible-collections/useful_stuff.git
    project_git_version: main
    galaxy:
      documentation:  https://docs.ansible.com/ansible/latest/collections/ansible/helpfull_things/index.html
      homepage: https://docs.ansible.com/ansible/latest/collections/ansible/helpfull_things/index.html

This playbook can then be run like any other one:

$ ansible-playbook playbook.yml

The playbook will first perform a Git clone of the project’s repository of the collection to migrate and alter its content to match the new naming convention required. All that remains is to use git diff to review the modifications, test that the collection still works as expected, and then commit the changes back to the existing repository (or import the resulting content into another repository).

Note that because fqcn_migration is a development tool, the provided playbook is designed to target the local instance (Ansible controller) rather than on a target (remote) system. As a result, no inventory file is required.

Generating a downstream collection

As demonstrated, fqcn_migration is already quite helpful for migrating collections from one namespace to another. However, the tool was also developed to support creating downstream collections. Before explaining how to use the tool for such a purpose, let’s briefly clarify what we mean by downstream content. This is a topic that is somewhat specific for providing commercial support over an open source solution.

Most Red Hat Ansible Automation Platform users are familiar with the Red Hat Enterprise Linux distribution, as a supported and certified version based on the community project Fedora. The same logic applies with JBoss Enterprise Platform being the supported and certified version of the community supported Java/JEE application WildFly. In this context, the community project is often referred to as upstream, while the code base of the Red Hat products is the downstream. Naturally, downstream source derives from the upstream. But, for many reasons, it is frequently transformed (to add files specific content related to the certified product) and then resides in its separate source code repository. Fixes and enhancements in the upstream project are selected afterward and back-ported to the downstream.

The Ansible Middleware collections are a set of collections designed to help manage Red Hat Runtimes solutions (RH JBoss EAP, RH SSO, RH JBoss Web Server, RH Data Grid, RH AMQ and RH AMQ Streams). Therefore, the upstream collections target the community project (upstream) of each of those projects and each has a downstream version targeting the products provided by Red Hat.

However, functionally, those collections are the same. The only technical difference is the naming convention and the supportability options. Consequently, to generate the downstream collection of one of those collections, for release purposes, fqcn_migration is also used. Naturally, the transformation performed on the collection is a bit more extensive, as there are extra requirements for documentation along with those that become Ansible certified content published on Ansible automation hub.

All of these considerations are handled within the fqcn_migration logic so that no manual change is required during a release of the downstream collection. For example, the following is the transformation rule used to convert the middleware_automation.wildfly collection into the redhat.eap collection:

---
- ansible.builtin.import_playbook: community.fqcn_migration.fqcn_migration
  vars:
	upstream_name: wildfly
	downstream_name: eap
	downstream_namespace: 'redhat'
	upstream_namespace: 'middleware_automation'
	project_git_url: https://github.com/ansible-middleware/wildfly.git

	upstream_downstream_collections_map:
  	- { upstream_name: 'middleware_automation.common', downstream_name: 'redhat.runtimes_common' }
  	- { upstream_name: 'middleware_automation.wildfly', downstream_name: 'redhat.eap' }

	post_processors_replacements:
 	- match: "eap_install_workdir: /opt/eap"
   	replace: "eap_install_workdir: /opt"
 	- match: "eap[.]statistics-enabled"
   	replace: "wildfly.statistics-enabled"
 	- match: "eap-configuration:"
   	replace: "wildfly-configuration:"
 	- match: "repo1.maven.org/maven2/org/eap/prospero"
   	replace: "repo1.maven.org/maven2/org/wildfly/prospero"

	galaxy:
  	documentation: https://access.redhat.com/documentation/en-us/red_hat_jboss_enterprise_application_platform
  	homepage: https://access.redhat.com/products/red-hat-jboss-enterprise-application-platform
	# anything inside <!--start {{ <downstream_placeholder>_delete }} --> and <!--end {{ <downstream_placeholder>_delete }} --> will be removed
	excluded_files_from_collections:
  	- roles/wildfly_subs
	downstream_placeholder_delete:
  	- build_status
	# anything inside <!--start {{ <downstream_placeholder>_content }} --> and <!--end {{ <downstream_placeholder>_content }} --> will be replaced with content
	downstream_placeholder_content:
  	- placeholder: galaxy_download
    	content: |
      	### Installing the Collection from Automation Hub

      	Before using the collection, you need to setup Ansible Automation Hub as galaxy server; then install it via the CLI:

          	ansible-galaxy collection install redhat.eap
  	- placeholder: support
    	content: |
      	## Support

      	redhat.eap collection v{{ galaxy_version | default('0.0.0-dev') }} is for [Technical Preview](https://access.redhat.com/support/offerings/techpreview).
      	If you have any issues or questions related to collection, please don't hesitate to contact us on <Ansible-middleware-core@redhat.com> or open an issue on
      	<https://github.com/ansible-middleware/wildfly/issues>
  	- placeholder: rhn_credentials
    	content: |
      	## Downloading products from the Customer Portal

      	The `redhat.eap.eap_install` role supports downloading and installing from the Red Hat Customer Portal using credentials associated to a service account. After
      	login in the customer portal and navigating to the hybrid cloud console, select the [services account tab](https://console.redhat.com/application-services/service-accounts)
      	to create one, if needed. Client ID and Client secret associated to the service account needs to be provided with the following variables are defined:
      	```
      	rhn_username{{':'}} '<client_id>'
      	rhn_password{{':'}} '<client_secret>'
      	```

      	The downloaded product archive will be stored in the controller working directory, and then distributed to target nodes.

      	When patching is requested, via the `eap_apply_cp` variable, the most recently published cumulative patch will be installed; to use a specific patch version instead,
      	set it with the `eap_patch_version` variable.

      	NOTE: downgrading patches is not supported.

This configuration of fqcn_migration is richer than the previous one. We leverage some advanced features that allow us to add or replace content to the collection. Based on a simple placeholder, this capacity allows the user to change the documentation of the downstream collection, so that it matches the documentation requirements of Ansible certified content.

Once we have generated the downstream collection, we can validate that the result is functional simply by running its transformed molecule test suite:

$ cd downstream/eap/
$ molecule test
…

Summary

In summary, altering a namespace requires a lot of changes because Ansible collections live inside namespaces, and it is best to use it in variables and role names. However, thanks to the fqcn_migration tool, we can easily migrate a collection’s content from one namespace to another, but also transform its roles and playbooks to generate a fully functional downstream version of the Ansible extension.