I'm writing Ansible roles, one role per 'service' / part of infrastructure that I'm managing. Let's say that' I'm managing some webserver, which is a part of a larger system. The whole system is managed by several playbooks, one each for deploying it, restarting it, getting status, backing it up, destroying it, etc.
Logically, each part of this larger system (webserver, database, runner, message queue, ...) would be encapsulated in a single role, and that role should expose all the relevant functionalities: deploy, restart, status, destroy, etc. I'd then just call the appropriate functionality for each role from the appropriate playbook, and all would be well.
However, I simply can't figure out what's the preferred / idiomatic way of handling this?
I encountered these candidate solutions, but none of them seem to cover all requests.
potential solution 1: a role with multiple entrypoints
The documentation for role argument validation, as well as import_role and include_role (tasks_from:
) hints at using different task files in role/tasks/
as the entrypoint.
This approach even allows for specifying different arguments for validation for each entrypoint.
However, this approach forces you to use the include_role
and import_role
tasks, preventing you from using the role as a regular role (in roles:
).
potential solution 2: deciding based on args
This solution has you defining a special variable (say action
) which chooses the action, and then you run tasks selectively in the role by checking if it's the correct action (when: action == 'destroy'
).
The vars / args for the role are then a weird union of all of the possible args any of the actions uses. This may work for the webserver example, but doesn't look great if you have more complicated actions, where args' types may clash.
potential solution 3: tags
You write all the actions in a contiguous role/tasks/main.yml
. Yes, you can include them from other files in the tasks folder for better organization, each include tagged with the appropriate tag, but logically they still all run as a whole when you disregard the tags. You tag the steps with different tags (deploy
, restart
, ...), and then you can use it with include_role
.
This seems fine, but you again must specify all the args / vars for the whole module, and it interferes with your tag use for other purposes.
potential solution 4: a combo of 1 and 2
You use args to decide the action in role/tasks/main.yml
, then import the appropriate other action from role/tasks
.
potential solution 5: something else?
There may be a solution I'm missing.
So, what's the idiomatic way of doing this? Are there any other benefits of these individual solutions that I'm missing? Is there some literature from developers codifying this that I haven't seen?