I've got a playbook that includes and tags various roles:
- name: base
hosts: "{{ host | default('localhost') }}"
roles:
- { role: apt, tags: [ 'base', 'apt', 'ubuntu']}
- { role: homebrew, tags: [ 'base', 'homebrew', osx' ]}
- { role: base16, tags: [ 'base', 'base16', 'osx' ]}
- { role: nodejs, tags: [ 'base', 'nodejs' ]}
- { role: tmux, tags: [ 'base', 'tmux' ]}
- { role: vim, tags: [ 'base', 'vim' ]}
- { role: virtualenv, tags: [ 'base', virtualenv', 'python' ]}
- { role: homebrew_cask, tags: [ 'desktop', 'homebrew_cask', osx' ]}
- { role: gnome_terminator, tags: [ 'desktop', 'gnome_terminator', ubuntu' ]}
Most of the tasks are using when clauses to determine which OS they should run on, for example:
- name: install base packages
when: ansible_distribution == 'MacOSX'
sudo: no
homebrew:
name: "{{ item.name }}"
state: latest
install_options: "{{ item.install_options|default() }}"
with_items: homebrew_packages
If I run ansible-playbook base.yml
without specifying any tags, all the tasks run. If I specify a tag, for example ansible-playbook base.yml --tags='base'
, only the roles tagged with base run
.
By default (if no tags are specified), I'd only like to run the roles tagged with 'base'
, and not the roles tagged with 'desktop'
.
It would also be really nice to set a default 'os' tag, based on the current operating system, to avoid including all the tasks for the ubuntu when I'm running the playbook on OSX (and vice-versa).
Any ideas if this is possible, and how I might do it?
You can check the docs here: http://docs.ansible.com/ansible/playbooks_tags.html#special-tags
Unfortunately there is no such feature. Tag handling in Ansible currently is very limited. You can not set default tags and you can not exclude tags by default.
There are some threads on the Google user group and feature requests on github regarding this. But no outcome yet. The common answer so far is, you should create a shell script and place it in front of your playbook. This script then can set the
--tags
and--skip-tags
accordingly to your needs. Very unpleasant but as far as I know the only option right now.I use command-line variable overrides (
-e
) to achieve this:Rather than define
desktop
as a tag, it could instead be defined as a variable with a default value offalse
. Then, for roles requiringdesktop
to be true, replace the tag with awhen
clause. The playbook posted in the question might be rewritten like this:This is probably just a simplified version of one of the existing answers. As stated elsewhere, tags aren't the answer at this time to defaulting some actions to not run unless something is explicitly specified. Variables, on the other hand, are perfect for this.
The reason to use default usually is: I want to type as less as possible in my most common use case. So I think what OP actually want is:
Are there ways to run 'base' tasks with as less arguments as possible.
As others pointed out, there are no "default" tag in ansible. But there are always ways.
First way is just use script to wrap it, like writing a
run.sh
like this:It is much shorter to type
./run.sh
instead of full command.Second way is for the people that is looking for the pure ansible solution. You can have two playbooks like:
base.yml
desktop.yml
For base only tasks, run
ansible-playbook base.yml
; for desktop only tasks, runansible-playbook desktop.yml
; for all tasks, runansible-playbook base.yml desktop.yml
It is also more error-prone than defining a 'default' tag.
OP also wants a default OS tag. It is easy to achieve that with
when
with
when
, you don't need to do anything in command line, ansible detects the type and runs corresponding tasks for you.Yes, this is very dangerous. If You forget to add '--tags=xxxxx' it may run unwanted tasks...
There is a workaround, it's nasty, but it would prevent running Your tasks when there are no tags in commandline.
You could use --extra-vars and use it in your playbook, then run:
And in Your playbook:
The result:
Since Ansible 2.5 there is a new feature which solves these kinds of situations.
So your problem should be addressed like this: