In the previous chapter of this blog post series, we discussed how Würth Phoenix has recently adopted Pulp as its main repository management platform.
To briefly recap, Pulp is a free and open-source platform for managing repositories of software packages and artifacts and making them available to a larger audience. The types of packages and artifacts supported by Pulp range from RPM packages to simple text files, and all of them can be managed, categorized, and published. Pulp can mirror remote repositories and offers a REST API for carrying out management activities.
In that last post, we described the preliminary steps we followed for introducing Pulp into our automation processes, from its installation to the basic operations needed to create, manage, and sync repositories. Several months after its introduction, we can now say that the tool is very well integrated into our infrastructure.
Let’s take a look together at an example of an activity that can be fully automated with the help of Pulp, Jenkins, and Ansible.
In our R&D team, our daily activities are mostly devoted to the implementation of new NetEye 4 features and bug fixes. As you can imagine, it means that at some point during the day, at least one person on the team needs to interact with Pulp to release new content that must be deployed, managed, and then published to the general public.
Let’s imagine the following scenario: the team has just integrated a new version of the Elastic Stack in NetEye 4 and, after several hours of testing, we’re finally ready to release it to end users. The new RPM packages are hosted in our beta repositories, a new project version has been created in Jira, and a team member clicks on the release button.
That click triggers a pipeline in Jenkins that executes an Ansible playbook, resulting in the moving of the beta version of the new Elastic Stack packages from our beta repositories to the stable ones, which are accessible by our customers.
First, Ansible retrieves all those packages that belong to a specific software project (the Elastic Stack project in our scenario) from a database and determines which stable repository each package must be moved to. We have, in fact, different stable repositories we use to classify software.
In the case of the Elastic Stack, for example, all packages are published within the same stable repository, so Ansible creates a dictionary with all the project’s packages and stores it in JSON format, as can be seen in the following code snippet.
{
"ELASTIC": [
"elasticsearch",
"elasticsearch-autosetup",
"kibana",
"kibana-autosetup",
"logstash",
"filebeat",
...
]
}
With this information, Ansible can now query Pulp to retrieve those packages and to move them to the stable repositories.
As shown in the previous blog post, Pulp offers the very user friendly pulp-admin
client to interact with the system. The same result, however, can be achieved by interacting directly with the Pulp API.
In our scenario, Ansible crafts a query to retrieve the repository membership of the Elastic Stack packages from Pulp in order to identify their beta repository, and to move them to the stable one.
Let’s try to find the elasticsearch-7.9.1_neteye3.12.3-1
package. The query is very similar to this one:
$ curl -XPOST <my_pulp_server>/pulp/api/v2/content/units/rpm/search/ -d '{"criteria":{"filters": {"filename": { "$regex": "elasticsearch-7.9.1_neteye3.12.3-1"}},"fields": ["filename", "version", "release"]}, "include_repos": true}'
In fact, we ask Pulp to retrieve all those packages whose filename contains elasticsearch-7.9.1_neteye3.12.3-
1, and to print out the filename itself, the package and the release version, and the repositories in which the packages are published.
The response looks like this:
[
{
"repository_memberships": [
"neteye-4.1x-beta"
],
"version": "7.9.1_neteye3.12.3",
"release": "1",
"filename": "elasticsearch-7.9.1_neteye3.12.3-1.x86_64.rpm"
},
{
"repository_memberships": [
"neteye-4.1y-beta"
],
"version": "7.9.1_neteye3.12.3",
"release": "1",
"filename": "elasticsearch-7.9.1_neteye3.12.3-1.x86_64.rpm"
}
]
We can see that the package we want to release is a member of the neteye-4.1x-beta
and neteye-4.1y-beta
repositories.
Now what we need to do is move the package to its final destination, the stable repo. For simplicity, I’ll show the corresponding pulp-admin
client commands from now on (our Ansible setup will still query Pulp via API).
The first thing we need to do is copy the package from the beta repository, to the stable one, as follows:
$ pulp-admin rpm repo copy rpm --match filename=elasticsearch-7.9.1_neteye3.12.3-1.x86_64.rpm --from-repo-id=neteye-4.1x-beta --to-repo-id=neteye-4.1x
Note that this operation must be done for each of the beta repositories in which the package is hosted. The syntax of the command is pretty self-explanatory.
Once the package has been copied, we can then remove it from the NetEye 4.x beta repo and then republish both the modified ones (beta and stable) to propagate the changes and to generate a new version of the repos. The commands are:
$ pulp-admin rpm repo remove rpm --repo-id=neteye-4.1x-beta --match filename=elasticsearch-7.9.1_neteye3.12.3-1.x86_64.rpm
$ pulp-admin rpm repo publish run --repo-id=neteye-4.1x-beta
$ pulp-admin rpm repo publish run --repo-id=neteye-4.1x
If everything goes well, we will have now released our new Elastic Stack version to our stable repository.
In this blog post, I’ve shown you one example of the automated pipeline that we use in our infrastructure, but the possibilities with Pulp are enormous. Think about automating the creation of the repositories for the new NetEye versions, or handling the variety of artifacts (ISOs, DEB or RPM packages, Python libraries) a complex product like NetEye has. It’s a very flexible, versatile and powerful tool that has everything we need to satisfy our daily and long term goals.