Writing my own modules in, say, Python feels like overkill. I can't find a
feature at the moment that would let me give a name to a yaml file
(containing task definitions) and then invoke that name as though it were
any other module.
Is anything like this already possible? Is it on a roadmap? (Would patches
to do this be accepted?)
which is klunky to read, error-prone to write, and makes refactoring the
common tasks tricky (particularly if the common tasks and their consumers
live in separately-gated repositories).
As far as I can tell* ansible avoids having sprawling search paths for
task includes (presumably so that it's easy to tell what's going on
without too much external context); but used judiciously, something like
this would let me introduce a smidgen of useful abstraction into my
playbooks.
Ah. But tasks for role dependencies are all fired off in advance, right?
I'm talking about having a common "subroutine" task, commonly provided
through a central point, that can be called like any other module might be
called, from an arbitrary point within a playbook.
(The point of this is to provide some abstraction, so that client
playbooks can be written in terms of higher-level operations than the
concrete modules typically provided. Is that just a misplaced desire to
"do ansible wrong"? )
If you want greater control of when your common tasks get executed, I would be more inclined to use rules and have verbose playbooks with the execution order explicitly specified.
Perhaps if you could give a better idea of what your common tasks are and the context in which you want to run them?
The common tasks involve configuring containers (it doesn't matter what
kind of container; that's liable to change) then installing software
elements into it and registering services.
However, to pick a simpler, concrete example, let's say I've a playbook
that needs to install a package, foo.
I want to use this playbook against both apt and yum-based systems; and
possibly against systems that use other packaging mechanisms in the
future.
[[[
- apt: name=foo
when: system == 'apt'
- yum: name=foo
when: system == 'yum'
]]]
Do I really need to repeat this logic everywhere I might want to install a
package? What I'm after is the ability to write:
- package: name=foo
and centralise the code that picks a concrete implementation.
Is there already a way to express this simple kind of abstraction in
ansible? I know I can do something like
but writing this is klunky and error-prone; I'm just wondering if there
are neater ways to achieve this - so that playbooks can separate the
"what" and the "how".
In terms of unified package management, I believe this is a direction that the Ansible project decided not to go in. I think the cleanest way from a playbook perspective would be to write your own module. But think about how much this might involve, noting that apt, yum, pacman et al don’t have interchangeable functionality - yes there are some commonalities but are really very different. That’s not including other package managers (thinking of npm, pip, rubygems etc). Also, package naming and what you do with a package after installing it varies greatly depending on distro, and by association, package manager.
I like to keep OS dependant tasks either in separate task files, or separate roles depending on the complexity. I don’t believe in this case that some duplication is a bad thing.
include: debian.yml
when: ansible_distribution == ‘Debian’ or ansible_distribution == ‘Ubuntu’
include: rhel.yml
when: ansible_distribution == ‘CentOS’ or ansible_distribution == ‘Red Hat Enterprise Linux’
To the top of each role. Debian/Ubuntu specific stuff (because config files are in different locations as well as package names being different) goes in the debian.yml file and CentOS/RHEL stuff goes in rhel.yml
Anything that is common to both (tagging for monitoring etc.) is in “main.yml” after the above include statements.
I realise its not exactly what you’re after but it might help?