Merge "Support Ansible diff mode"
This commit is contained in:
commit
bf440c5dd2
@ -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
|
limited to matching plays and tasks. The ``--skip-tags <TAGS>`` and
|
||||||
``--kolla-skip-tags <TAGS>`` arguments allow for avoiding execution of matching
|
``--kolla-skip-tags <TAGS>`` arguments allow for avoiding execution of matching
|
||||||
plays and tasks.
|
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.
|
||||||
|
@ -48,6 +48,10 @@ def add_args(parser):
|
|||||||
help="path to Kayobe configuration. "
|
help="path to Kayobe configuration. "
|
||||||
"(default=$%s or %s)" %
|
"(default=$%s or %s)" %
|
||||||
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
|
(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,
|
parser.add_argument("--environment", default=default_environment,
|
||||||
help="specify environment name (default=$%s or None)" %
|
help="specify environment name (default=$%s or None)" %
|
||||||
ENVIRONMENT_ENV)
|
ENVIRONMENT_ENV)
|
||||||
@ -161,7 +165,7 @@ def _get_vars_files(vars_paths):
|
|||||||
|
|
||||||
def build_args(parsed_args, playbooks,
|
def build_args(parsed_args, playbooks,
|
||||||
extra_vars=None, limit=None, tags=None, verbose_level=None,
|
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."""
|
"""Build arguments required for running Ansible playbooks."""
|
||||||
cmd = ["ansible-playbook"]
|
cmd = ["ansible-playbook"]
|
||||||
if verbose_level:
|
if verbose_level:
|
||||||
@ -193,6 +197,8 @@ def build_args(parsed_args, playbooks,
|
|||||||
cmd += ["--become"]
|
cmd += ["--become"]
|
||||||
if check or (parsed_args.check and check is None):
|
if check or (parsed_args.check and check is None):
|
||||||
cmd += ["--check"]
|
cmd += ["--check"]
|
||||||
|
if diff or (parsed_args.diff and diff is None):
|
||||||
|
cmd += ["--diff"]
|
||||||
if not ignore_limit and (parsed_args.limit or limit):
|
if not ignore_limit and (parsed_args.limit or limit):
|
||||||
limit_arg = utils.intersect_limits(parsed_args.limit, limit)
|
limit_arg = utils.intersect_limits(parsed_args.limit, limit)
|
||||||
cmd += ["--limit", limit_arg]
|
cmd += ["--limit", limit_arg]
|
||||||
@ -227,13 +233,14 @@ def _get_environment(parsed_args):
|
|||||||
def run_playbooks(parsed_args, playbooks,
|
def run_playbooks(parsed_args, playbooks,
|
||||||
extra_vars=None, limit=None, tags=None, quiet=False,
|
extra_vars=None, limit=None, tags=None, quiet=False,
|
||||||
check_output=False, verbose_level=None, check=None,
|
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."""
|
"""Run a Kayobe Ansible playbook."""
|
||||||
_validate_args(parsed_args, playbooks)
|
_validate_args(parsed_args, playbooks)
|
||||||
cmd = build_args(parsed_args, playbooks,
|
cmd = build_args(parsed_args, playbooks,
|
||||||
extra_vars=extra_vars, limit=limit, tags=tags,
|
extra_vars=extra_vars, limit=limit, tags=tags,
|
||||||
verbose_level=verbose_level, check=check,
|
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)
|
env = _get_environment(parsed_args)
|
||||||
try:
|
try:
|
||||||
utils.run_command(cmd, check_output=check_output, quiet=quiet, env=env)
|
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,
|
run_playbook(parsed_args, playbook_path,
|
||||||
extra_vars=extra_vars, tags=tags, check_output=True,
|
extra_vars=extra_vars, tags=tags, check_output=True,
|
||||||
verbose_level=verbose_level, check=False,
|
verbose_level=verbose_level, check=False,
|
||||||
list_tasks=False)
|
list_tasks=False, diff=False)
|
||||||
hostvars = {}
|
hostvars = {}
|
||||||
for path in os.listdir(dump_dir):
|
for path in os.listdir(dump_dir):
|
||||||
LOG.debug("Found dump file %s", path)
|
LOG.debug("Found dump file %s", path)
|
||||||
|
@ -157,6 +157,14 @@ def _get_environment(parsed_args):
|
|||||||
ansible_cfg_path = os.path.join(parsed_args.config_path, "ansible.cfg")
|
ansible_cfg_path = os.path.join(parsed_args.config_path, "ansible.cfg")
|
||||||
if utils.is_readable_file(ansible_cfg_path)["result"]:
|
if utils.is_readable_file(ansible_cfg_path)["result"]:
|
||||||
env.setdefault("ANSIBLE_CONFIG", ansible_cfg_path)
|
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
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ class TestCase(unittest.TestCase):
|
|||||||
"-b",
|
"-b",
|
||||||
"-C",
|
"-C",
|
||||||
"--config-path", "/path/to/config",
|
"--config-path", "/path/to/config",
|
||||||
|
"-D",
|
||||||
"--environment", "test-env",
|
"--environment", "test-env",
|
||||||
"-e", "ev_name1=ev_value1",
|
"-e", "ev_name1=ev_value1",
|
||||||
"-i", "/path/to/inventory",
|
"-i", "/path/to/inventory",
|
||||||
@ -88,6 +89,7 @@ class TestCase(unittest.TestCase):
|
|||||||
"-e", "ev_name1=ev_value1",
|
"-e", "ev_name1=ev_value1",
|
||||||
"--become",
|
"--become",
|
||||||
"--check",
|
"--check",
|
||||||
|
"--diff",
|
||||||
"--limit", "group1:host",
|
"--limit", "group1:host",
|
||||||
"--tags", "tag1,tag2",
|
"--tags", "tag1,tag2",
|
||||||
"playbook1.yml",
|
"playbook1.yml",
|
||||||
@ -117,6 +119,7 @@ class TestCase(unittest.TestCase):
|
|||||||
"--become",
|
"--become",
|
||||||
"--check",
|
"--check",
|
||||||
"--config-path", "/path/to/config",
|
"--config-path", "/path/to/config",
|
||||||
|
"--diff",
|
||||||
"--environment", "test-env",
|
"--environment", "test-env",
|
||||||
"--extra-vars", "ev_name1=ev_value1",
|
"--extra-vars", "ev_name1=ev_value1",
|
||||||
"--inventory", "/path/to/inventory",
|
"--inventory", "/path/to/inventory",
|
||||||
@ -138,6 +141,7 @@ class TestCase(unittest.TestCase):
|
|||||||
"-e", "ev_name1=ev_value1",
|
"-e", "ev_name1=ev_value1",
|
||||||
"--become",
|
"--become",
|
||||||
"--check",
|
"--check",
|
||||||
|
"--diff",
|
||||||
"--limit", "group1:host1",
|
"--limit", "group1:host1",
|
||||||
"--skip-tags", "tag3,tag4",
|
"--skip-tags", "tag3,tag4",
|
||||||
"--tags", "tag1,tag2",
|
"--tags", "tag1,tag2",
|
||||||
@ -249,6 +253,7 @@ class TestCase(unittest.TestCase):
|
|||||||
"tags": "tag3,tag4",
|
"tags": "tag3,tag4",
|
||||||
"verbose_level": 0,
|
"verbose_level": 0,
|
||||||
"check": True,
|
"check": True,
|
||||||
|
"diff": True,
|
||||||
}
|
}
|
||||||
ansible.run_playbooks(parsed_args, ["playbook1.yml", "playbook2.yml"],
|
ansible.run_playbooks(parsed_args, ["playbook1.yml", "playbook2.yml"],
|
||||||
**kwargs)
|
**kwargs)
|
||||||
@ -260,6 +265,7 @@ class TestCase(unittest.TestCase):
|
|||||||
"-e", "ev_name1=ev_value1",
|
"-e", "ev_name1=ev_value1",
|
||||||
"-e", "ev_name2='ev_value2'",
|
"-e", "ev_name2='ev_value2'",
|
||||||
"--check",
|
"--check",
|
||||||
|
"--diff",
|
||||||
"--limit", "group1:host1:&group2:host2",
|
"--limit", "group1:host1:&group2:host2",
|
||||||
"--tags", "tag1,tag2,tag3,tag4",
|
"--tags", "tag1,tag2,tag3,tag4",
|
||||||
"playbook1.yml",
|
"playbook1.yml",
|
||||||
@ -426,7 +432,7 @@ class TestCase(unittest.TestCase):
|
|||||||
},
|
},
|
||||||
check_output=True, tags=None,
|
check_output=True, tags=None,
|
||||||
verbose_level=None, check=False,
|
verbose_level=None, check=False,
|
||||||
list_tasks=False)
|
list_tasks=False, diff=False)
|
||||||
mock_rmtree.assert_called_once_with(dump_dir)
|
mock_rmtree.assert_called_once_with(dump_dir)
|
||||||
mock_listdir.assert_any_call(dump_dir)
|
mock_listdir.assert_any_call(dump_dir)
|
||||||
mock_read.assert_has_calls([
|
mock_read.assert_has_calls([
|
||||||
|
@ -54,6 +54,8 @@ class TestCase(unittest.TestCase):
|
|||||||
kolla_ansible.add_args(parser)
|
kolla_ansible.add_args(parser)
|
||||||
vault.add_args(parser)
|
vault.add_args(parser)
|
||||||
args = [
|
args = [
|
||||||
|
"-C",
|
||||||
|
"-D",
|
||||||
"--kolla-config-path", "/path/to/config",
|
"--kolla-config-path", "/path/to/config",
|
||||||
"-ke", "ev_name1=ev_value1",
|
"-ke", "ev_name1=ev_value1",
|
||||||
"-ki", "/path/to/inventory",
|
"-ki", "/path/to/inventory",
|
||||||
@ -73,8 +75,9 @@ class TestCase(unittest.TestCase):
|
|||||||
"--tags", "tag1,tag2",
|
"--tags", "tag1,tag2",
|
||||||
]
|
]
|
||||||
expected_cmd = " ".join(expected_cmd)
|
expected_cmd = " ".join(expected_cmd)
|
||||||
|
expected_env = {"EXTRA_OPTS": " --check --diff"}
|
||||||
mock_run.assert_called_once_with(expected_cmd, shell=True, quiet=False,
|
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(utils, "run_command")
|
||||||
@mock.patch.object(kolla_ansible, "_validate_args")
|
@mock.patch.object(kolla_ansible, "_validate_args")
|
||||||
@ -87,6 +90,8 @@ class TestCase(unittest.TestCase):
|
|||||||
mock_ask.return_value = "test-pass"
|
mock_ask.return_value = "test-pass"
|
||||||
args = [
|
args = [
|
||||||
"--ask-vault-pass",
|
"--ask-vault-pass",
|
||||||
|
"--check",
|
||||||
|
"--diff",
|
||||||
"--kolla-config-path", "/path/to/config",
|
"--kolla-config-path", "/path/to/config",
|
||||||
"--kolla-extra-vars", "ev_name1=ev_value1",
|
"--kolla-extra-vars", "ev_name1=ev_value1",
|
||||||
"--kolla-inventory", "/path/to/inventory",
|
"--kolla-inventory", "/path/to/inventory",
|
||||||
@ -110,7 +115,8 @@ class TestCase(unittest.TestCase):
|
|||||||
"--tags", "tag1,tag2",
|
"--tags", "tag1,tag2",
|
||||||
]
|
]
|
||||||
expected_cmd = " ".join(expected_cmd)
|
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 = [
|
expected_calls = [
|
||||||
mock.call(["which", "kayobe-vault-password-helper"],
|
mock.call(["which", "kayobe-vault-password-helper"],
|
||||||
check_output=True, universal_newlines=True),
|
check_output=True, universal_newlines=True),
|
||||||
|
11
releasenotes/notes/diff-mode-468e09bbb9185b50.yaml
Normal file
11
releasenotes/notes/diff-mode-468e09bbb9185b50.yaml
Normal 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.
|
Loading…
Reference in New Issue
Block a user