Skip to content

Commit

Permalink
Implement support for "playbook sets"
Browse files Browse the repository at this point in the history
(cherry picked from commit 1530eb5)
  • Loading branch information
drybjed committed Jan 22, 2024
1 parent 5f7053b commit 5ec9f12
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ General
to the :command:`syslog` service. Use the ``--verbose`` or ``-v`` flag to
enable log output on the console.

- Users can define "playbook sets" on the view level of the "modern" project
directories. Playbook sets can be used as aliases to call multiple playbooks
using a custom name. See :ref:`playbook_sets` documentation for more details.

Changed
~~~~~~~

Expand Down
64 changes: 64 additions & 0 deletions docs/user-guide/project-directories.rst
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,70 @@ default collection for a given "infrastructure view" to one which contains
unprivileged playbooks and roles, or add more Ansible Collections which should
be searched for playbooks.

.. _playbook_sets:

Per-view playbook sets
~~~~~~~~~~~~~~~~~~~~~~

Users can define "playbook sets" at the view level, using the
`views.<name>.playbook_sets` configuration option. This option is a YAML
dictionary with lists of playbooks to execute when a particular "playbook set"
is specified on the command line. An example configuration:

.. code-block:: yaml
---
views:
system:
playbook_sets:
'webservice':
- 'layer/common'
- 'service/nginx'
- 'custom-app'
With the above configuration, users can execute a set of playbooks using the
command:

.. code-block:: console
debops run webservice -l webserver
which will be internally expanded to:

.. code-block:: console
debops run layer/common service/nginx custom-app -l webserver
After that, the usual playbook expansion will take place. The first two
playbooks will be found in the DebOps collection, and the :file:`custom-app`
playbook will be presumably in the :file:`ansible/views/system/playbooks/`
subdirectory of the project directory. If a potential playbook set is not found,
the argument will be expanded into a playbook if possible, or passed to the
:command:`ansible-playbook` command as-is.

This mechanism can be used to redefine existing playbooks into playbook sets.
For example, if users want to include additional playbooks in the "site"
playbook, they can:

.. code-block:: yaml
---
views:
system:
playbook_sets:
'site':
- 'site'
- '<namespace>.<collection>.custom_playbook'
Now calling the "site" playbook will execute the DebOps own :file:`site.yml`
playbook, and an additional playbook from a specific Ansible Collection.

Please remember that this feature does not modify the actual playbooks, just the
way they are called from the command line. This means that including the
:file:`site.yml` playbook in another playbook will run just that one playbook,
not all the playbooks defined in a playbook set.


DebOps and :command:`git` integration
-------------------------------------

Expand Down
7 changes: 5 additions & 2 deletions src/debops/_data/templates/projectdir/modern/view.yml.j2
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
{# Copyright (C) 2023 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2023 DebOps <https://debops.org/>
{# Copyright (C) 2023-2024 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2023-2024 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-or-later
#}
# Configuration for the '{{ view_name }}' view
Expand All @@ -13,6 +13,9 @@ views:
playbook_collections:
- 'debops.debops'

# YAML dictionary which defines lists of "playbook sets" to use in this view
playbook_sets: {}

# Configuration options for Ansible, will be included in the 'ansible.cfg'
# file generated by DebOps.
# Ref: https://docs.ansible.com/ansible/latest/reference_appendices/config.html
Expand Down
42 changes: 35 additions & 7 deletions src/debops/ansibleplaybookrunner.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright (C) 2020-2021 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2020-2021 DebOps <https://debops.org/>
# Copyright (C) 2020-2024 Maciej Delmanowski <drybjed@gmail.com>
# Copyright (C) 2020-2024 DebOps <https://debops.org/>
# SPDX-License-Identifier: GPL-3.0-or-later

from .utils import unexpanduser
Expand Down Expand Up @@ -108,18 +108,46 @@ def __init__(self, project, *args, **kwargs):
self._parsed_args.append(index)
else:
# Most likely a name of a playbook which we can expand
self._ansible_command.append(self._quote_spaces(
self._expand_playbook(project, argument)))
self._found_playbooks.append(self._quote_spaces(
self._expand_playbook(project, argument)))
self._parsed_args.append(index)

# Check the arguments for possible playbook sets and expand them
# if they're found
parsed_set = self._expand_playbook_set(project, argument)

for element in parsed_set:
self._ansible_command.append(self._quote_spaces(
self._expand_playbook(project, element)))
self._found_playbooks.append(self._quote_spaces(
self._expand_playbook(project, element)))
self._parsed_args.append(index)

def _quote_spaces(self, string):
if ' ' in string:
return '"{}"'.format(string)
else:
return string

def _expand_playbook_set(self, project, argument):
logger.debug('Checking if playbook "{}" is a playbook set'
.format(argument))
try:
playbook_set = (project.config.raw['views']
[project.view]
['playbook_sets']
[argument])
logger.notice('Found playbook set "{}" in view "{}"'
.format(argument, project.view))
if isinstance(playbook_set, list):
logger.debug('Playbook set "{}" expanded to: {}'
.format(argument, ' '.join(playbook_set)))
return playbook_set
else:
logger.error('Incorrect definition of playbook set',
extra={'block': 'stderr'})
raise ValueError('Incorrect definition of playbook set')
except KeyError:
logger.debug('No playbook set found')
return [argument]

def _ring_bell(self):
# Notify user at end of execution
if self.kwargs.get('bell', False):
Expand Down

0 comments on commit 5ec9f12

Please sign in to comment.