Merge "Support Ansible diff mode"

This commit is contained in:
Zuul 2021-10-21 16:31:56 +00:00 committed by Gerrit Code Review
commit bf440c5dd2
6 changed files with 55 additions and 7 deletions

View File

@ -69,3 +69,13 @@ playbooks to be limited to matching plays and tasks. The ``--kolla-tags
limited to matching plays and tasks. The ``--skip-tags <TAGS>`` and
``--kolla-skip-tags <TAGS>`` arguments allow for avoiding execution of matching
plays and tasks.
Check and diff mode
-------------------
Ansible supports `check and diff modes
<https://docs.ansible.com/ansible/latest/user_guide/playbooks_checkmode.html>`_,
which can be used to improve visibility into changes that would be made on
target systems. The Kayobe CLI supports the ``--check`` argument, and since
11.0.0, the ``--diff`` argument. Note that these modes are not always
guaranteed to work, when some tasks are dependent on earlier ones.

View File

@ -48,6 +48,10 @@ def add_args(parser):
help="path to Kayobe configuration. "
"(default=$%s or %s)" %
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
parser.add_argument("-D", "--diff", action="store_true",
help="when changing (small) files and templates, show "
"the differences in those files; works great "
"with --check")
parser.add_argument("--environment", default=default_environment,
help="specify environment name (default=$%s or None)" %
ENVIRONMENT_ENV)
@ -161,7 +165,7 @@ def _get_vars_files(vars_paths):
def build_args(parsed_args, playbooks,
extra_vars=None, limit=None, tags=None, verbose_level=None,
check=None, ignore_limit=False, list_tasks=None):
check=None, ignore_limit=False, list_tasks=None, diff=None):
"""Build arguments required for running Ansible playbooks."""
cmd = ["ansible-playbook"]
if verbose_level:
@ -193,6 +197,8 @@ def build_args(parsed_args, playbooks,
cmd += ["--become"]
if check or (parsed_args.check and check is None):
cmd += ["--check"]
if diff or (parsed_args.diff and diff is None):
cmd += ["--diff"]
if not ignore_limit and (parsed_args.limit or limit):
limit_arg = utils.intersect_limits(parsed_args.limit, limit)
cmd += ["--limit", limit_arg]
@ -227,13 +233,14 @@ def _get_environment(parsed_args):
def run_playbooks(parsed_args, playbooks,
extra_vars=None, limit=None, tags=None, quiet=False,
check_output=False, verbose_level=None, check=None,
ignore_limit=False, list_tasks=None):
ignore_limit=False, list_tasks=None, diff=None):
"""Run a Kayobe Ansible playbook."""
_validate_args(parsed_args, playbooks)
cmd = build_args(parsed_args, playbooks,
extra_vars=extra_vars, limit=limit, tags=tags,
verbose_level=verbose_level, check=check,
ignore_limit=ignore_limit, list_tasks=list_tasks)
ignore_limit=ignore_limit, list_tasks=list_tasks,
diff=diff)
env = _get_environment(parsed_args)
try:
utils.run_command(cmd, check_output=check_output, quiet=quiet, env=env)
@ -269,7 +276,7 @@ def config_dump(parsed_args, host=None, hosts=None, var_name=None,
run_playbook(parsed_args, playbook_path,
extra_vars=extra_vars, tags=tags, check_output=True,
verbose_level=verbose_level, check=False,
list_tasks=False)
list_tasks=False, diff=False)
hostvars = {}
for path in os.listdir(dump_dir):
LOG.debug("Found dump file %s", path)

View File

@ -157,6 +157,14 @@ def _get_environment(parsed_args):
ansible_cfg_path = os.path.join(parsed_args.config_path, "ansible.cfg")
if utils.is_readable_file(ansible_cfg_path)["result"]:
env.setdefault("ANSIBLE_CONFIG", ansible_cfg_path)
# kolla-ansible allows passing additional arguments to ansible-playbook via
# EXTRA_OPTS.
if parsed_args.check or parsed_args.diff:
extra_opts = env.setdefault("EXTRA_OPTS", "")
if parsed_args.check and "--check" not in extra_opts:
env["EXTRA_OPTS"] += " --check"
if parsed_args.diff and "--diff" not in extra_opts:
env["EXTRA_OPTS"] += " --diff"
return env

View File

@ -68,6 +68,7 @@ class TestCase(unittest.TestCase):
"-b",
"-C",
"--config-path", "/path/to/config",
"-D",
"--environment", "test-env",
"-e", "ev_name1=ev_value1",
"-i", "/path/to/inventory",
@ -88,6 +89,7 @@ class TestCase(unittest.TestCase):
"-e", "ev_name1=ev_value1",
"--become",
"--check",
"--diff",
"--limit", "group1:host",
"--tags", "tag1,tag2",
"playbook1.yml",
@ -117,6 +119,7 @@ class TestCase(unittest.TestCase):
"--become",
"--check",
"--config-path", "/path/to/config",
"--diff",
"--environment", "test-env",
"--extra-vars", "ev_name1=ev_value1",
"--inventory", "/path/to/inventory",
@ -138,6 +141,7 @@ class TestCase(unittest.TestCase):
"-e", "ev_name1=ev_value1",
"--become",
"--check",
"--diff",
"--limit", "group1:host1",
"--skip-tags", "tag3,tag4",
"--tags", "tag1,tag2",
@ -249,6 +253,7 @@ class TestCase(unittest.TestCase):
"tags": "tag3,tag4",
"verbose_level": 0,
"check": True,
"diff": True,
}
ansible.run_playbooks(parsed_args, ["playbook1.yml", "playbook2.yml"],
**kwargs)
@ -260,6 +265,7 @@ class TestCase(unittest.TestCase):
"-e", "ev_name1=ev_value1",
"-e", "ev_name2='ev_value2'",
"--check",
"--diff",
"--limit", "group1:host1:&group2:host2",
"--tags", "tag1,tag2,tag3,tag4",
"playbook1.yml",
@ -426,7 +432,7 @@ class TestCase(unittest.TestCase):
},
check_output=True, tags=None,
verbose_level=None, check=False,
list_tasks=False)
list_tasks=False, diff=False)
mock_rmtree.assert_called_once_with(dump_dir)
mock_listdir.assert_any_call(dump_dir)
mock_read.assert_has_calls([

View File

@ -54,6 +54,8 @@ class TestCase(unittest.TestCase):
kolla_ansible.add_args(parser)
vault.add_args(parser)
args = [
"-C",
"-D",
"--kolla-config-path", "/path/to/config",
"-ke", "ev_name1=ev_value1",
"-ki", "/path/to/inventory",
@ -73,8 +75,9 @@ class TestCase(unittest.TestCase):
"--tags", "tag1,tag2",
]
expected_cmd = " ".join(expected_cmd)
expected_env = {"EXTRA_OPTS": " --check --diff"}
mock_run.assert_called_once_with(expected_cmd, shell=True, quiet=False,
env={})
env=expected_env)
@mock.patch.object(utils, "run_command")
@mock.patch.object(kolla_ansible, "_validate_args")
@ -87,6 +90,8 @@ class TestCase(unittest.TestCase):
mock_ask.return_value = "test-pass"
args = [
"--ask-vault-pass",
"--check",
"--diff",
"--kolla-config-path", "/path/to/config",
"--kolla-extra-vars", "ev_name1=ev_value1",
"--kolla-inventory", "/path/to/inventory",
@ -110,7 +115,8 @@ class TestCase(unittest.TestCase):
"--tags", "tag1,tag2",
]
expected_cmd = " ".join(expected_cmd)
expected_env = {"KAYOBE_VAULT_PASSWORD": "test-pass"}
expected_env = {"EXTRA_OPTS": " --check --diff",
"KAYOBE_VAULT_PASSWORD": "test-pass"}
expected_calls = [
mock.call(["which", "kayobe-vault-password-helper"],
check_output=True, universal_newlines=True),

View File

@ -0,0 +1,11 @@
---
features:
- |
Adds a ``--diff`` argument to kayobe CLI commands. This is passed through
to ``ansible-playbook`` for Kayobe and Kolla Ansible playbooks, and can be
used with the ``--check`` argument to see changes that would be made to
files.
upgrade:
- |
The ``--check`` argument to kayobe CLI commands is now passed through to
Kolla Ansible playbooks.