Yum repository bootstrapping in Ansible
December 3, 2013•595 words
I don't do cloud-scale work, but I do provision systems a lot, since I develop and maintain a custom Linux distribution that we sell on a box at Code Blue. With that in mind, and after hearing more about some of the options available at the inaugural meeting of DevOps West Michigan, I decided some weeks ago to investigate the current state-of-the-art in that field.
My short time with Puppet was marked with initial intrigue but eventually deep frustration over a specific thing I really wanted to do while provisioning new systems: add third-party yum respositories. A few of them, in fact. Trying to do this with the built-in yumrepo type ran me headlong into a really old bug (which I helped reproduce), which was partly responsible for me opting to check out Ansible.
I discovered that I really liked Ansible, but I was still stuck with a weird chicken-and-egg problem getting the repositories up and running on my systems. If I wanted to add, say, EPEL from the shell, I'd head to the epel-release download page (linked from the Fedora wiki), grab the latest RPM, and rpm -Uvh
it. Tedious, manual, and not very automatable. Most users get around this (and the problem of the release package filename's changing) by creating their own .repo
files in /etc/yum.repos.d
from scratch, but this creates an interesting situation if a wanted package ever depends on its repository's release package—which is exactly the case for packages in the AsteriskNOW repo, since you've now got your little custom repo and the official repos from the release package both hanging around.
But then I stumbled across a really neat little trick. Stack Overflow user ravello posted about using a .repo file to bootstrap installing a release package, without knowing its version number—only requiring a stable repository URL and release package name. From that inspiration, I created a few tasks in my Ansible playbook to bootstrap the repositories using exclusively declarative tasks:
- name: bootstrap epel-release install
copy: src=ansible-bootstrap-epel.repo
dest=/etc/yum.repos.d/
owner=root group=root mode=0644
- name: epel-release install
yum: name=epel-release
enablerepo=ansible-bootstrap-epel
state=present
- name: epel repository enable
ini_file: dest=/etc/yum.repos.d/epel.repo
section=epel
option=enabled
value=1
The above does three things. First, it copies a bootstrap .repo
file to /etc/yum.repos.d
. The repository uses the official URL, has a unique name so as not to clash with the release package's .repo
files, and—critically—is disabled. For EPEL, it looks like this:
[ansible-bootstrap-epel]
name = Ansible bootstrap for epel
mirrorlist = http://mirrors.fedoraproject.org/mirrorlist?repo=epel-$releasever&arch=$basearch
failovermethod = priority
enabled = 0
gpgcheck = 0
From there, the enablerepo
option on the yum
task is used to temporarily enable the bootstrap repository long enough to install epel-release
. Finally, the last task edits the new epel.repo
from epel-release
to enable it, since it ships disabled.
For AsteriskNOW, a similar set of tasks:
- name: bootstrap asterisknow-version install
copy: src=ansible-bootstrap-asterisk-current.repo
dest=/etc/yum.repos.d/
owner=root group=root mode=0644
- name: asterisknow-version install
yum: name=asterisknow-version
enablerepo=ansible-bootstrap-asterisk-current
state=present
- name: asterisk-11 repository enable
ini_file: dest=/etc/yum.repos.d/centos-asterisk-11.repo
section=asterisk-11
option=enabled
value=1
and a bootstrap .repo
file:
[ansible-bootstrap-asterisk-current]
name = Ansible bootstrap for asterisk-current
baseurl = http://packages.asterisk.org/centos/$releasever/current/$basearch/
enabled = 0
gpgcheck = 0
get the same job done.
I'm pretty sure this is the most robust way to get third-party yum repositories up and running on Ansible-managed systems. I'm pretty thrilled with it, in any event. I've used it, with slight modification, in the Vagrant hacking setup for octothorpe.