From d7069283fd89e6164414d83afa688c3d2afae48f Mon Sep 17 00:00:00 2001 From: Alex-Welsh Date: Fri, 16 Sep 2022 13:39:30 +0100 Subject: [PATCH] added option to skip hooks adds the argument --skip-hooks/-sh which will stop the execution of hooked ansible playbooks. Either a pattern can be specified to match against or hook execution can be stopped altogether with "all" Story: 2009241 Task: 43390 Change-Id: I4f2176aa056fec62e31d07140e3d05779480a93d --- doc/source/custom-ansible-playbooks.rst | 18 ++++++++ kayobe/ansible.py | 3 ++ kayobe/cli/commands.py | 24 +++++++--- kayobe/tests/unit/cli/test_commands.py | 44 ++++++++++++++++++- ...option-to-skip-hooks-719ba214a6d4b773.yaml | 6 +++ 5 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/add-option-to-skip-hooks-719ba214a6d4b773.yaml diff --git a/doc/source/custom-ansible-playbooks.rst b/doc/source/custom-ansible-playbooks.rst index 0c6179367..890dfdf8a 100644 --- a/doc/source/custom-ansible-playbooks.rst +++ b/doc/source/custom-ansible-playbooks.rst @@ -213,6 +213,24 @@ you could do the following:: The sequence number for the ``foo.yml`` playbook is ``10``. +Hook execution can be disabled with ``--skip-hooks``. ``--skip-hooks all`` will halt hook execution altogether. +``--skip-hooks `` will skip playbooks matching the ````. + +For example, if the following playbooks exist: + +- ``$KAYOBE_CONFIG_PATH/hooks/control-host-bootstrap/pre.d/example1.yml`` +- ``$KAYOBE_CONFIG_PATH/hooks/control-host-bootstrap/pre.d/example2.yml`` +- ``$KAYOBE_CONFIG_PATH/hooks/control-host-bootstrap/post.d/example1.yml`` + +And the following command is used:: + + (kayobe) $ kayobe control host bootstrap --skip-hooks example1 + +Only ``$KAYOBE_CONFIG_PATH/hooks/control-host-bootstrap/pre.d/example2.yml`` will be executed. + +This example assumes that the term ``example1`` does not appear in +``$KAYOBE_CONFIG_PATH``. If it did, all hooks would be skipped. + Failure handling ---------------- diff --git a/kayobe/ansible.py b/kayobe/ansible.py index 9d47a9243..dd5bc66df 100644 --- a/kayobe/ansible.py +++ b/kayobe/ansible.py @@ -77,6 +77,9 @@ def add_args(parser): action="store_true", help="only print names of tasks, don't run them, " "note this has no affect on kolla-ansible.") + parser.add_argument("-sh", "--skip-hooks", action="store", default=None, + help="disables hooks. Specify a pattern to skip" + "specific playbooks. \"all\" skips all playbooks") def _get_kayobe_environment_path(parsed_args): diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py index 315c787bf..11fc164f0 100644 --- a/kayobe/cli/commands.py +++ b/kayobe/cli/commands.py @@ -15,6 +15,7 @@ import glob import json import os +import re import sys from cliff.command import Command @@ -190,18 +191,27 @@ class HookDispatcher(CommandHook): self.logger.debug("Discovered the following hooks: %s" % hooks) return hooks - def hooks(self, config_path, target): - hooks = self._find_hooks(config_path, target) + def hooks(self, config_path, target, filter): + hooks_out = [] + if filter == "all": + self.logger.debug("Skipping all hooks") + return hooks_out + hooks_in = self._find_hooks(config_path, target) # Hooks can be prefixed with a sequence number to adjust running order, # e.g 10-my-custom-playbook.yml. Sort by sequence number. - hooks = sorted(hooks, key=_split_hook_sequence_number) - # Resolve symlinks so that we can reference roles. - hooks = [os.path.realpath(hook) for hook in hooks] - return hooks + hooks_in = sorted(hooks_in, key=_split_hook_sequence_number) + for hook in hooks_in: + # Resolve symlinks so that we can reference roles. + hook = os.path.realpath(hook) + if filter and re.search(filter, hook): + self.logger.debug("Skipping hook: %s", hook) + else: + hooks_out.append(hook) + return hooks_out def run_hooks(self, parsed_args, target): config_path = parsed_args.config_path - hooks = self.hooks(config_path, target) + hooks = self.hooks(config_path, target, parsed_args.skip_hooks) if hooks: self.logger.debug("Running hooks: %s" % hooks) self.command.run_kayobe_playbooks(parsed_args, hooks) diff --git a/kayobe/tests/unit/cli/test_commands.py b/kayobe/tests/unit/cli/test_commands.py index c86671815..6d8952deb 100644 --- a/kayobe/tests/unit/cli/test_commands.py +++ b/kayobe/tests/unit/cli/test_commands.py @@ -2506,5 +2506,47 @@ class TestHookDispatcher(unittest.TestCase): "z-test-alphabetical.yml", ] mock_path.realpath.side_effect = lambda x: x - actual = dispatcher.hooks("config/path", "pre") + actual = dispatcher.hooks("config/path", "pre", None) + self.assertListEqual(actual, expected_result) + + @mock.patch('kayobe.cli.commands.os.path') + def test_hook_filter_all(self, mock_path): + mock_command = mock.MagicMock() + dispatcher = commands.HookDispatcher(command=mock_command) + dispatcher._find_hooks = mock.MagicMock() + dispatcher._find_hooks.return_value = [ + "5-hook.yml", + "5-multiple-dashes-in-name.yml", + "10-before-hook.yml", + "10-hook.yml", + "no-prefix.yml", + "z-test-alphabetical.yml", + ] + mock_path.realpath.side_effect = lambda x: x + actual = dispatcher.hooks("config/path", "pre", "all") + self.assertListEqual(actual, []) + + @mock.patch('kayobe.cli.commands.os.path') + def test_hook_filter_one(self, mock_path): + mock_command = mock.MagicMock() + dispatcher = commands.HookDispatcher(command=mock_command) + dispatcher._find_hooks = mock.MagicMock() + dispatcher._find_hooks.return_value = [ + "5-hook.yml", + "5-multiple-dashes-in-name.yml", + "10-before-hook.yml", + "10-hook.yml", + "no-prefix.yml", + "z-test-alphabetical.yml", + ] + expected_result = [ + "5-hook.yml", + "10-before-hook.yml", + "10-hook.yml", + "no-prefix.yml", + "z-test-alphabetical.yml", + ] + mock_path.realpath.side_effect = lambda x: x + actual = dispatcher.hooks("config/path", "pre", + "5-multiple-dashes-in-name.yml") self.assertListEqual(actual, expected_result) diff --git a/releasenotes/notes/add-option-to-skip-hooks-719ba214a6d4b773.yaml b/releasenotes/notes/add-option-to-skip-hooks-719ba214a6d4b773.yaml new file mode 100644 index 000000000..e80cea092 --- /dev/null +++ b/releasenotes/notes/add-option-to-skip-hooks-719ba214a6d4b773.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Adds the --skip-hooks argument to ignore hooks for the execution of a + command. See `story 2009241 + `_ for details. \ No newline at end of file