I’ve been on an Ansible kick recently at work (domo). While working on a project, I started creating a simple workstation setup playbook. I got to thinking that someone must have done this already. I remembered boxen by github.
What follows is my journey to the creation of a tool called battleschool.
A few things that aren’t necessarily bad about boxen, but rub me the wrong way: 1) Puppet, 2) installation.
Every time I have tried a puppet tutorial (or chef, more on that later), I’ve never found them simple or easy to follow. When I found ansible, its first goal is to be simple, simple to install, configure, execute (it’s only requirement on the machine it’s going to provision is ssh and python). Ansible’s syntax is yaml, as simple a markup language as I’ve seen. You can write modules in any language you want, but library of modules is written in python.
The installation of boxen seems awkward to me. I was looking for a simple install and then point to a company setup, rather than customize a boxen fork.
I searched for an alternative to boxen and came upon kitchenplan. It’s similar to boxen, but based on chef. I have had similar issues with chef as I’ve had with puppet. Kitchenplan still involves forking, but is a little more sane.
So, I did what a good developer does and created my own: battleschool. It uses the ansible API to setup, configure and run ansible playbooks. It’s still got some rough edges, so bear with me. I use it regularly. In fact, since I started writing this post, I had to wipe my machine because of some bad partitions I created. When I tried to install OS X Mavericks, I ended up having to delete the partitions and start over. I was back up and running in 2 hours and most of that time was downloading packages to install.
In short, battleschool downloads and executes ansible playbooks against your local machine in a manner that is simple to configure and repeatable in cases of disaster (bad) or new machines (good).
I wanted a no forking install for battleschool.
#if needed $ sudo easy_install pip $ sudo pip install battleschool
That’s it. Battleschool depends on ansible, so that will be installed via pip as well. I haven’t done any work to deal with alternative installs of ansible via homebrew, macports or apt (yes, this will work on linux/bsd as well).
Private Playbook Repos
Battleschool uses the git and get_url ansible modules to download remote playbooks. That means you can use private, self-hosted git repositories, private or public github or bitbucket repositories, or dropbox to host your playbooks! Extreme flexibility without forking battleschool. Other version control systems (VCS) such as svn or mercurial should be simple to add because of ansible’s support for them.
Built On Ansible
I use ansible’s python api, so most of ansible-playbooks options are available to battleschool. All of ansible’s modules are available. I have been using ansible 1.3 to develop and plan on upgrading to 1.4 shortly. Ansible, IMHO, is the most straightforward provisioner I have tried. It’s written in python, which I have enjoyed.
Some of this comes from the README.md
About the Name
I learned about the term ansible from Ender’s Game. Taking a cue from Kitchenplan, I wanted to name my project with something from the enderverse. I settled on battleschool as the project name and battle as the command.
battle --ask-sudo-pass #if you have setup nopasswd in sudo then omit --ask-sudo-pass
battle --ask-sudo-pass. This will fail with a
file not found: /Users/username/.battleschool/config.yml (A better error would be nice :-). You need to create a
config file first. I plan on creating a default one if battleschool doesn’t find one. If you are following along:
mkdir ~/.battleschool cd .battleschool curl -L https://db.tt/aG2uyydU > config.yml #this downloads my config as a starting point
--- sources: local: #- playbook.yml url: #- name: playbook.yml # url: https://db.tt/VcyI9dvr git: - name: 'osx' repo: 'https://github.com/spencergibb/ansible-osx' playbooks: #- adium.yml
explanation of ~/.battleschool/config.yml
sources: local: - playbook.yml
Any ansible playbooks located in ~/.battleschool/playbooks can be listed under local. Each playbook will be executed in order. This can useful for custom configuration per workstation. (You could install apps with homebrew or macports if those are installed, for example). After adding url sources (see below), this should probably be used sparingly.
url: - name: playbook.yml url: https://db.tt/VcyI9dvr
Playbooks located at a url. Each playbook will be executed in order. Helpful for bootstrapping (ie, the first time you run battleschool). For example, if you are restoring a machine, you might run:
or more realistically
sudo pip install battleschool && battle --ask-sudo-pass --config-file=https://db.tt/aG2uyydU
As long as there are no local sources, everything will be downloaded and run.
NOTE: playbooks under the
url sections, cannot reference anything outside of their own contents (e.g.
files, templates, roles, etc…). See git sources below for more advanced playbooks.
git: - name: 'osx' repo: 'https://github.com/spencergibb/ansible-osx' playbooks: - adium.yml
Any git repo that hosts ansible playbooks (specific to battleschool or not) will work here. Each item under playsbooks is the relative location to a playbook in the specified git repository. In the example above, adium.yml is in the root of the ansible-osx repository.
git repo sources
The top level of the directory would contain files and directories like so:
local.yml # optional master playbook, automatically run, no need to list under playbooks dev.yml # example playbook for dev ux.yml # example playbook for ux chrome.yml # example playbook for the chrome browser dir/myapp.yml # example playbook, supports nesting one level deep roles/ # optional standard ansible role hierarchy library/ # optional remote module definitions
See the roles docs for information about ansible roles and their
directory layout. The
library directory is the location for placing
custom ansible modules.
the mac_pkg module
This is the meat of battleschool. How do you install mac apps?
If you look most of the playbooks in this git repo you will see the use of the mac_pkg module. Mac apps are usually a pkg (or mpgk) installer, or the bare .app directory. They can be archived in a number of formats: DMG or zip commonly. Pkg files may not be archived at all. Less common formats (tar or 7zip) are not supported yet.
Lets look at adium.yml
--- - hosts: workstation tasks: - name: install Adium mac_pkg: pkg_type=app url=http://sourceforge.net/projects/adium/files/Adium_1.5.7.dmg/download archive_type=dmg archive_path=Adium.app sudo: yes
- hosts: workstation this is required in each playbook as it targets the local workstation. Though this is generally
arbitrary for most ansible users, it must be
workstation in battleschool.
pkg_type=app type must be pkg, app or script. Defaults to pkg.
This is an example of a
url=.... the url of the app to download, alternatively a local src path, such as
src=https://gibb.tech/local/path/to/app.dmg, may be
archive_type=dmg one of dmg, zip or none. Defaults to none.
archive_path=Adium.app The path to the app or pkg in the archive.
sudo: yes required for mac_pkg tasks (this will prompt you to enter you sudo password only once)
--- - hosts: workstation tasks: - name: install java 7 update 25 mac_pkg: pkg_name=com.oracle.jdk7u25 pkg_version=1.1 url=https://edelivery.oracle.com/otn-pub/java/jdk/7u25-b15/jdk-7u25-macosx-x64.dmg curl_opts='--cookie gpw_e24=http%3A%2F%2Fwww.oracle.com' archive_type=dmg archive_path='JDK 7 Update 25.pkg' sudo: yes
pkg_name=com.oracle.jdk7u25 the name of the pkg found by
pkg_version=1.1 the version of the package as reported by
pkgutil --pkg-info com.oracle.jdk7u25
curl_opts=... cookie needed to download java from oracle, supports all curl options
NOTE: battleschool, currently does not install apps from the Apple App Store.
So, you like homebrew and want to use it to install apps on you mac. No problem. Battleschool can install homebrew for you (see this playbook). Already have homebrew installed? No, problem, it won’t try and install it again.
Where to start?
Probably the easiest way to start is by looking at my configuration:
Config file: https://db.tt/aG2uyydU
My url playbook: https://db.tt/VcyI9dvr
My playbook git repo: https://github.com/spencergibb/ansible-osx
How to contact me or the community?
Google group: https://groups.google.com/d/forum/battle-school
Github project for issues, forks, pull requests: https://github.com/spencergibb/battleschool