Add unit tests and style checks for Kayobe python module
Unit tests can be run via: tox -e py27 Style checks can be run via: tox -e pep8
This commit is contained in:
parent
caf9b52ac7
commit
baf17c8cff
|
@ -23,3 +23,12 @@ ansible/roles/yatesr.timezone/
|
||||||
|
|
||||||
# Virtualenv
|
# Virtualenv
|
||||||
ansible/kolla-venv
|
ansible/kolla-venv
|
||||||
|
|
||||||
|
# Tox
|
||||||
|
.tox/
|
||||||
|
|
||||||
|
# Python build artifacts
|
||||||
|
kayobe
|
||||||
|
|
||||||
|
# Python build artifacts
|
||||||
|
kayobe.egg-info
|
||||||
|
|
|
@ -16,19 +16,6 @@ CONFIG_PATH_ENV = "KAYOBE_CONFIG_PATH"
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def galaxy_install(role_file, roles_path):
|
|
||||||
"""Install Ansible roles via Ansible Galaxy."""
|
|
||||||
cmd = ["ansible-galaxy", "install"]
|
|
||||||
cmd += ["--roles-path", roles_path]
|
|
||||||
cmd += ["--role-file", role_file]
|
|
||||||
try:
|
|
||||||
subprocess.check_call(cmd)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
LOG.error("Failed to install Ansible roles from %s via Ansible "
|
|
||||||
"Galaxy: returncode %d", role_file, e.returncode)
|
|
||||||
sys.exit(e.returncode)
|
|
||||||
|
|
||||||
|
|
||||||
def add_args(parser):
|
def add_args(parser):
|
||||||
"""Add arguments required for running Ansible playbooks to a parser."""
|
"""Add arguments required for running Ansible playbooks to a parser."""
|
||||||
default_config_path = os.getenv(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH)
|
default_config_path = os.getenv(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH)
|
||||||
|
@ -53,9 +40,9 @@ def add_args(parser):
|
||||||
parser.add_argument("-l", "--limit", metavar="SUBSET",
|
parser.add_argument("-l", "--limit", metavar="SUBSET",
|
||||||
help="further limit selected hosts to an additional "
|
help="further limit selected hosts to an additional "
|
||||||
"pattern")
|
"pattern")
|
||||||
parser.add_argument("-t", "--tags", metavar="TAGS", action="append",
|
parser.add_argument("-t", "--tags", metavar="TAGS",
|
||||||
help="only run plays and tasks tagged with these "
|
help="only run plays and tasks tagged with these "
|
||||||
"values")
|
"values")
|
||||||
|
|
||||||
|
|
||||||
def _get_inventory_path(parsed_args):
|
def _get_inventory_path(parsed_args):
|
||||||
|
@ -75,7 +62,7 @@ def _validate_args(parsed_args, playbooks):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
inventory = _get_inventory_path(parsed_args)
|
inventory = _get_inventory_path(parsed_args)
|
||||||
result = utils.is_readable_file(inventory)
|
result = utils.is_readable_dir(inventory)
|
||||||
if not result["result"]:
|
if not result["result"]:
|
||||||
LOG.error("Kayobe inventory %s is invalid: %s",
|
LOG.error("Kayobe inventory %s is invalid: %s",
|
||||||
inventory, result["message"])
|
inventory, result["message"])
|
||||||
|
@ -89,18 +76,27 @@ def _validate_args(parsed_args, playbooks):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_vars_files(config_path):
|
||||||
|
"""Return a list of Kayobe Ansible configuration variable files."""
|
||||||
|
vars_files = []
|
||||||
|
for vars_file in os.listdir(config_path):
|
||||||
|
abs_path = os.path.join(config_path, vars_file)
|
||||||
|
if utils.is_readable_file(abs_path):
|
||||||
|
root, ext = os.path.splitext(vars_file)
|
||||||
|
if ext in (".yml", ".yaml", ".json"):
|
||||||
|
vars_files.append(abs_path)
|
||||||
|
return vars_files
|
||||||
|
|
||||||
|
|
||||||
def build_args(parsed_args, playbooks,
|
def build_args(parsed_args, playbooks,
|
||||||
extra_vars=None, limit=None, tags=None):
|
extra_vars=None, limit=None, tags=None):
|
||||||
"""Build arguments required for running Ansible playbooks."""
|
"""Build arguments required for running Ansible playbooks."""
|
||||||
cmd = ["ansible-playbook"]
|
cmd = ["ansible-playbook"]
|
||||||
inventory = _get_inventory_path(parsed_args)
|
inventory = _get_inventory_path(parsed_args)
|
||||||
cmd += ["--inventory", inventory]
|
cmd += ["--inventory", inventory]
|
||||||
for vars_file in os.listdir(parsed_args.config_path):
|
vars_files = _get_vars_files(parsed_args.config_path)
|
||||||
abs_path = os.path.join(parsed_args.config_path, vars_file)
|
for vars_file in vars_files:
|
||||||
if os.path.isfile(abs_path):
|
cmd += ["-e", "@%s" % vars_file]
|
||||||
root, ext = os.path.splitext(vars_file)
|
|
||||||
if ext in (".yml", ".yaml", ".json"):
|
|
||||||
cmd += ["-e", "@%s" % abs_path]
|
|
||||||
if parsed_args.extra_vars:
|
if parsed_args.extra_vars:
|
||||||
for extra_var in parsed_args.extra_vars:
|
for extra_var in parsed_args.extra_vars:
|
||||||
cmd += ["-e", extra_var]
|
cmd += ["-e", extra_var]
|
||||||
|
@ -141,7 +137,7 @@ def run_playbook(parsed_args, playbook, *args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def config_dump(parsed_args, host=None, hosts=None, var_name=None,
|
def config_dump(parsed_args, host=None, hosts=None, var_name=None,
|
||||||
facts=False, extra_vars=None):
|
facts=None, extra_vars=None):
|
||||||
dump_dir = tempfile.mkdtemp()
|
dump_dir = tempfile.mkdtemp()
|
||||||
try:
|
try:
|
||||||
if not extra_vars:
|
if not extra_vars:
|
||||||
|
|
|
@ -47,7 +47,7 @@ class ControlHostBootstrap(KayobeAnsibleMixin, Command):
|
||||||
self.app.LOG.error("%s is not currently supported", linux_distname)
|
self.app.LOG.error("%s is not currently supported", linux_distname)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
utils.yum_install(["ansible"])
|
utils.yum_install(["ansible"])
|
||||||
ansible.galaxy_install("ansible/requirements.yml", "ansible/roles")
|
utils.galaxy_install("ansible/requirements.yml", "ansible/roles")
|
||||||
playbooks = ["ansible/%s.yml" % playbook for playbook in
|
playbooks = ["ansible/%s.yml" % playbook for playbook in
|
||||||
"bootstrap", "kolla"]
|
"bootstrap", "kolla"]
|
||||||
ansible.run_playbooks(parsed_args, playbooks)
|
ansible.run_playbooks(parsed_args, playbooks)
|
||||||
|
|
|
@ -26,16 +26,16 @@ def add_args(parser):
|
||||||
help="path to Kolla configuration. "
|
help="path to Kolla configuration. "
|
||||||
"(default=$%s or %s)" %
|
"(default=$%s or %s)" %
|
||||||
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
|
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
|
||||||
parser.add_argument("--kolla-extra-vars", metavar="EXTRA_VARS",
|
parser.add_argument("-ke", "--kolla-extra-vars", metavar="EXTRA_VARS",
|
||||||
action="append",
|
action="append",
|
||||||
help="set additional variables as key=value or "
|
help="set additional variables as key=value or "
|
||||||
"YAML/JSON for Kolla Ansible")
|
"YAML/JSON for Kolla Ansible")
|
||||||
parser.add_argument("--kolla-inventory", metavar="INVENTORY",
|
parser.add_argument("-ki", "--kolla-inventory", metavar="INVENTORY",
|
||||||
help="specify inventory host path "
|
help="specify inventory host path "
|
||||||
"(default=$%s/inventory or %s/inventory) or "
|
"(default=$%s/inventory or %s/inventory) or "
|
||||||
"comma-separated host list for Kolla Ansible" %
|
"comma-separated host list for Kolla Ansible" %
|
||||||
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
|
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
|
||||||
parser.add_argument("--kolla-tags", metavar="TAGS", action="append",
|
parser.add_argument("-kt", "--kolla-tags", metavar="TAGS",
|
||||||
help="only run plays and tasks tagged with these "
|
help="only run plays and tasks tagged with these "
|
||||||
"values in Kolla Ansible")
|
"values in Kolla Ansible")
|
||||||
parser.add_argument("--kolla-venv", metavar="VENV", default=default_venv,
|
parser.add_argument("--kolla-venv", metavar="VENV", default=default_venv,
|
||||||
|
@ -79,12 +79,13 @@ def build_args(parsed_args, command, inventory_filename, extra_vars=None,
|
||||||
"""Build arguments required for running Kolla Ansible."""
|
"""Build arguments required for running Kolla Ansible."""
|
||||||
venv_activate = os.path.join(parsed_args.kolla_venv, "bin", "activate")
|
venv_activate = os.path.join(parsed_args.kolla_venv, "bin", "activate")
|
||||||
cmd = ["source", venv_activate, "&&"]
|
cmd = ["source", venv_activate, "&&"]
|
||||||
cmd = ["kolla-ansible", command]
|
cmd += ["kolla-ansible", command]
|
||||||
inventory = _get_inventory_path(parsed_args, inventory_filename)
|
inventory = _get_inventory_path(parsed_args, inventory_filename)
|
||||||
cmd += ["--inventory", inventory]
|
cmd += ["--inventory", inventory]
|
||||||
cmd += ["--configdir", parsed_args.kolla_config_path]
|
if parsed_args.kolla_config_path != DEFAULT_CONFIG_PATH:
|
||||||
cmd += ["--passwords",
|
cmd += ["--configdir", parsed_args.kolla_config_path]
|
||||||
os.path.join(parsed_args.kolla_config_path, "passwords.yml")]
|
cmd += ["--passwords",
|
||||||
|
os.path.join(parsed_args.kolla_config_path, "passwords.yml")]
|
||||||
if parsed_args.kolla_extra_vars:
|
if parsed_args.kolla_extra_vars:
|
||||||
for extra_var in parsed_args.kolla_extra_vars:
|
for extra_var in parsed_args.kolla_extra_vars:
|
||||||
cmd += ["-e", extra_var]
|
cmd += ["-e", extra_var]
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from kayobe import ansible
|
||||||
|
from kayobe import utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(ansible, "_get_vars_files")
|
||||||
|
@mock.patch.object(ansible, "_validate_args")
|
||||||
|
def test_run_playbooks(self, mock_validate, mock_vars, mock_run):
|
||||||
|
mock_vars.return_value = ["/etc/kayobe/vars-file1.yml",
|
||||||
|
"/etc/kayobe/vars-file2.yaml"]
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
ansible.add_args(parser)
|
||||||
|
parsed_args = parser.parse_args([])
|
||||||
|
ansible.run_playbooks(parsed_args, ["playbook1.yml", "playbook2.yml"])
|
||||||
|
expected_cmd = [
|
||||||
|
"ansible-playbook",
|
||||||
|
"--inventory", "/etc/kayobe/inventory",
|
||||||
|
"-e", "@/etc/kayobe/vars-file1.yml",
|
||||||
|
"-e", "@/etc/kayobe/vars-file2.yaml",
|
||||||
|
"playbook1.yml",
|
||||||
|
"playbook2.yml",
|
||||||
|
]
|
||||||
|
mock_run.assert_called_once_with(expected_cmd, quiet=False)
|
||||||
|
mock_vars.assert_called_once_with("/etc/kayobe")
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(ansible, "_get_vars_files")
|
||||||
|
@mock.patch.object(ansible, "_validate_args")
|
||||||
|
def test_run_playbooks_all_the_args(self, mock_validate, mock_vars,
|
||||||
|
mock_run):
|
||||||
|
mock_vars.return_value = ["/path/to/config/vars-file1.yml",
|
||||||
|
"/path/to/config/vars-file2.yaml"]
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
ansible.add_args(parser)
|
||||||
|
args = [
|
||||||
|
"-b",
|
||||||
|
"-C",
|
||||||
|
"--config-path", "/path/to/config",
|
||||||
|
"-e", "ev_name1=ev_value1",
|
||||||
|
"-i", "/path/to/inventory",
|
||||||
|
"-l", "group1:host",
|
||||||
|
"-t", "tag1,tag2",
|
||||||
|
]
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
ansible.run_playbooks(parsed_args, ["playbook1.yml", "playbook2.yml"])
|
||||||
|
expected_cmd = [
|
||||||
|
"ansible-playbook",
|
||||||
|
"--inventory", "/path/to/inventory",
|
||||||
|
"-e", "@/path/to/config/vars-file1.yml",
|
||||||
|
"-e", "@/path/to/config/vars-file2.yaml",
|
||||||
|
"-e", "ev_name1=ev_value1",
|
||||||
|
"--become",
|
||||||
|
"--check",
|
||||||
|
"--limit", "group1:host",
|
||||||
|
"--tags", "tag1,tag2",
|
||||||
|
"playbook1.yml",
|
||||||
|
"playbook2.yml",
|
||||||
|
]
|
||||||
|
mock_run.assert_called_once_with(expected_cmd, quiet=False)
|
||||||
|
mock_vars.assert_called_once_with("/path/to/config")
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(ansible, "_get_vars_files")
|
||||||
|
@mock.patch.object(ansible, "_validate_args")
|
||||||
|
def test_run_playbooks_all_the_long_args(self, mock_validate, mock_vars,
|
||||||
|
mock_run):
|
||||||
|
mock_vars.return_value = ["/path/to/config/vars-file1.yml",
|
||||||
|
"/path/to/config/vars-file2.yaml"]
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
ansible.add_args(parser)
|
||||||
|
args = [
|
||||||
|
"--become",
|
||||||
|
"--check",
|
||||||
|
"--config-path", "/path/to/config",
|
||||||
|
"--extra-vars", "ev_name1=ev_value1",
|
||||||
|
"--inventory", "/path/to/inventory",
|
||||||
|
"--limit", "group1:host1",
|
||||||
|
"--tags", "tag1,tag2",
|
||||||
|
]
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
ansible.run_playbooks(parsed_args, ["playbook1.yml", "playbook2.yml"])
|
||||||
|
expected_cmd = [
|
||||||
|
"ansible-playbook",
|
||||||
|
"--inventory", "/path/to/inventory",
|
||||||
|
"-e", "@/path/to/config/vars-file1.yml",
|
||||||
|
"-e", "@/path/to/config/vars-file2.yaml",
|
||||||
|
"-e", "ev_name1=ev_value1",
|
||||||
|
"--become",
|
||||||
|
"--check",
|
||||||
|
"--limit", "group1:host1",
|
||||||
|
"--tags", "tag1,tag2",
|
||||||
|
"playbook1.yml",
|
||||||
|
"playbook2.yml",
|
||||||
|
]
|
||||||
|
mock_run.assert_called_once_with(expected_cmd, quiet=False)
|
||||||
|
mock_vars.assert_called_once_with("/path/to/config")
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(ansible, "_get_vars_files")
|
||||||
|
@mock.patch.object(ansible, "_validate_args")
|
||||||
|
def test_run_playbooks_func_args(self, mock_validate, mock_vars, mock_run):
|
||||||
|
mock_vars.return_value = ["/etc/kayobe/vars-file1.yml",
|
||||||
|
"/etc/kayobe/vars-file2.yaml"]
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
ansible.add_args(parser)
|
||||||
|
args = [
|
||||||
|
"--extra-vars", "ev_name1=ev_value1",
|
||||||
|
"--limit", "group1:host1",
|
||||||
|
"--tags", "tag1,tag2",
|
||||||
|
]
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
kwargs = {
|
||||||
|
"extra_vars": {"ev_name2": "ev_value2"},
|
||||||
|
"limit": "group2:host2",
|
||||||
|
"tags": "tag3,tag4",
|
||||||
|
}
|
||||||
|
ansible.run_playbooks(parsed_args, ["playbook1.yml", "playbook2.yml"],
|
||||||
|
**kwargs)
|
||||||
|
expected_cmd = [
|
||||||
|
"ansible-playbook",
|
||||||
|
"--inventory", "/etc/kayobe/inventory",
|
||||||
|
"-e", "@/etc/kayobe/vars-file1.yml",
|
||||||
|
"-e", "@/etc/kayobe/vars-file2.yaml",
|
||||||
|
"-e", "ev_name1=ev_value1",
|
||||||
|
"-e", "ev_name2=ev_value2",
|
||||||
|
"--limit", "group1:host1&group2:host2",
|
||||||
|
"--tags", "tag1,tag2,tag3,tag4",
|
||||||
|
"playbook1.yml",
|
||||||
|
"playbook2.yml",
|
||||||
|
]
|
||||||
|
mock_run.assert_called_once_with(expected_cmd, quiet=False)
|
||||||
|
mock_vars.assert_called_once_with("/etc/kayobe")
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(ansible, "_get_vars_files")
|
||||||
|
@mock.patch.object(ansible, "_validate_args")
|
||||||
|
def test_run_playbooks_failure(self, mock_validate, mock_vars, mock_run):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
ansible.add_args(parser)
|
||||||
|
parsed_args = parser.parse_args([])
|
||||||
|
mock_run.side_effect = subprocess.CalledProcessError(1, "dummy")
|
||||||
|
self.assertRaises(SystemExit,
|
||||||
|
ansible.run_playbooks, parsed_args, "command")
|
||||||
|
|
||||||
|
@mock.patch.object(shutil, 'rmtree')
|
||||||
|
@mock.patch.object(utils, 'read_yaml_file')
|
||||||
|
@mock.patch.object(os, 'listdir')
|
||||||
|
@mock.patch.object(ansible, 'run_playbook')
|
||||||
|
@mock.patch.object(tempfile, 'mkdtemp')
|
||||||
|
def test_config_dump(self, mock_mkdtemp, mock_run, mock_listdir, mock_read,
|
||||||
|
mock_rmtree):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parsed_args = parser.parse_args([])
|
||||||
|
dump_dir = mock_mkdtemp.return_value
|
||||||
|
mock_listdir.return_value = ["host1.yml", "host2.yml"]
|
||||||
|
mock_read.side_effect = [
|
||||||
|
{"var1": "value1"},
|
||||||
|
{"var2": "value2"}
|
||||||
|
]
|
||||||
|
result = ansible.config_dump(parsed_args)
|
||||||
|
expected_result = {
|
||||||
|
"host1": {"var1": "value1"},
|
||||||
|
"host2": {"var2": "value2"},
|
||||||
|
}
|
||||||
|
self.assertEqual(result, expected_result)
|
||||||
|
mock_run.assert_called_once_with(parsed_args,
|
||||||
|
"ansible/dump-config.yml",
|
||||||
|
extra_vars={
|
||||||
|
"dump_path": dump_dir,
|
||||||
|
},
|
||||||
|
quiet=True)
|
||||||
|
mock_rmtree.assert_called_once_with(dump_dir)
|
||||||
|
mock_listdir.assert_called_once_with(dump_dir)
|
||||||
|
mock_read.assert_has_calls([
|
||||||
|
mock.call(os.path.join(dump_dir, "host1.yml")),
|
||||||
|
mock.call(os.path.join(dump_dir, "host2.yml")),
|
||||||
|
])
|
|
@ -0,0 +1,113 @@
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from kayobe import kolla_ansible
|
||||||
|
from kayobe import utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(kolla_ansible, "_validate_args")
|
||||||
|
def test_run(self, mock_validate, mock_run):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
kolla_ansible.add_args(parser)
|
||||||
|
parsed_args = parser.parse_args([])
|
||||||
|
kolla_ansible.run(parsed_args, "command", "overcloud")
|
||||||
|
expected_cmd = [
|
||||||
|
"source", "ansible/kolla-venv/bin/activate", "&&",
|
||||||
|
"kolla-ansible", "command",
|
||||||
|
"--inventory", "/etc/kolla/inventory/overcloud",
|
||||||
|
]
|
||||||
|
expected_cmd = " ".join(expected_cmd)
|
||||||
|
mock_run.assert_called_once_with(expected_cmd, shell=True, quiet=False)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(kolla_ansible, "_validate_args")
|
||||||
|
def test_run_all_the_args(self, mock_validate, mock_run):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
kolla_ansible.add_args(parser)
|
||||||
|
args = [
|
||||||
|
"--kolla-config-path", "/path/to/config",
|
||||||
|
"-ke", "ev_name1=ev_value1",
|
||||||
|
"-ki", "/path/to/inventory",
|
||||||
|
"-kt", "tag1,tag2",
|
||||||
|
]
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
kolla_ansible.run(parsed_args, "command", "overcloud")
|
||||||
|
expected_cmd = [
|
||||||
|
"source", "ansible/kolla-venv/bin/activate", "&&",
|
||||||
|
"kolla-ansible", "command",
|
||||||
|
"--inventory", "/path/to/inventory",
|
||||||
|
"--configdir", "/path/to/config",
|
||||||
|
"--passwords", "/path/to/config/passwords.yml",
|
||||||
|
"-e", "ev_name1=ev_value1",
|
||||||
|
"--tags", "tag1,tag2",
|
||||||
|
]
|
||||||
|
expected_cmd = " ".join(expected_cmd)
|
||||||
|
mock_run.assert_called_once_with(expected_cmd, shell=True, quiet=False)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(kolla_ansible, "_validate_args")
|
||||||
|
def test_run_all_the_long_args(self, mock_validate, mock_run):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
kolla_ansible.add_args(parser)
|
||||||
|
args = [
|
||||||
|
"--kolla-config-path", "/path/to/config",
|
||||||
|
"--kolla-extra-vars", "ev_name1=ev_value1",
|
||||||
|
"--kolla-inventory", "/path/to/inventory",
|
||||||
|
"--kolla-tags", "tag1,tag2",
|
||||||
|
]
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
kolla_ansible.run(parsed_args, "command", "overcloud")
|
||||||
|
expected_cmd = [
|
||||||
|
"source", "ansible/kolla-venv/bin/activate", "&&",
|
||||||
|
"kolla-ansible", "command",
|
||||||
|
"--inventory", "/path/to/inventory",
|
||||||
|
"--configdir", "/path/to/config",
|
||||||
|
"--passwords", "/path/to/config/passwords.yml",
|
||||||
|
"-e", "ev_name1=ev_value1",
|
||||||
|
"--tags", "tag1,tag2",
|
||||||
|
]
|
||||||
|
expected_cmd = " ".join(expected_cmd)
|
||||||
|
mock_run.assert_called_once_with(expected_cmd, shell=True, quiet=False)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(kolla_ansible, "_validate_args")
|
||||||
|
def test_run_func_args(self, mock_validate, mock_run):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
kolla_ansible.add_args(parser)
|
||||||
|
args = [
|
||||||
|
"--kolla-extra-vars", "ev_name1=ev_value1",
|
||||||
|
"--kolla-tags", "tag1,tag2",
|
||||||
|
]
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
kwargs = {
|
||||||
|
"extra_vars": {"ev_name2": "ev_value2"},
|
||||||
|
"tags": "tag3,tag4",
|
||||||
|
}
|
||||||
|
kolla_ansible.run(parsed_args, "command", "overcloud", **kwargs)
|
||||||
|
expected_cmd = [
|
||||||
|
"source", "ansible/kolla-venv/bin/activate", "&&",
|
||||||
|
"kolla-ansible", "command",
|
||||||
|
"--inventory", "/etc/kolla/inventory/overcloud",
|
||||||
|
"-e", "ev_name1=ev_value1",
|
||||||
|
"-e", "ev_name2=ev_value2",
|
||||||
|
"--tags", "tag1,tag2,tag3,tag4",
|
||||||
|
]
|
||||||
|
expected_cmd = " ".join(expected_cmd)
|
||||||
|
mock_run.assert_called_once_with(expected_cmd, shell=True, quiet=False)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
@mock.patch.object(kolla_ansible, "_validate_args")
|
||||||
|
def test_run_failure(self, mock_validate, mock_run):
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
kolla_ansible.add_args(parser)
|
||||||
|
parsed_args = parser.parse_args([])
|
||||||
|
mock_run.side_effect = subprocess.CalledProcessError(1, "dummy")
|
||||||
|
self.assertRaises(SystemExit,
|
||||||
|
kolla_ansible.run, parsed_args, "command",
|
||||||
|
"overcloud")
|
|
@ -0,0 +1,73 @@
|
||||||
|
import subprocess
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from kayobe import utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
def test_yum_install(self, mock_run):
|
||||||
|
utils.yum_install(["package1", "package2"])
|
||||||
|
mock_run.assert_called_once_with(["sudo", "yum", "-y", "install",
|
||||||
|
"package1", "package2"])
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
def test_yum_install_failure(self, mock_run):
|
||||||
|
mock_run.side_effect = subprocess.CalledProcessError(1, "command")
|
||||||
|
self.assertRaises(SystemExit,
|
||||||
|
utils.yum_install, ["package1", "package2"])
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
def test_galaxy_install(self, mock_run):
|
||||||
|
utils.galaxy_install("/path/to/role/file", "/path/to/roles")
|
||||||
|
mock_run.assert_called_once_with(["ansible-galaxy", "install",
|
||||||
|
"--roles-path", "/path/to/roles",
|
||||||
|
"--role-file", "/path/to/role/file"])
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "run_command")
|
||||||
|
def test_galaxy_install_failure(self, mock_run):
|
||||||
|
mock_run.side_effect = subprocess.CalledProcessError(1, "command")
|
||||||
|
self.assertRaises(SystemExit,
|
||||||
|
utils.galaxy_install, "/path/to/role/file",
|
||||||
|
"/path/to/roles")
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "read_file")
|
||||||
|
def test_read_yaml_file(self, mock_read):
|
||||||
|
mock_read.return_value = """---
|
||||||
|
key1: value1
|
||||||
|
key2: value2
|
||||||
|
"""
|
||||||
|
result = utils.read_yaml_file("/path/to/file")
|
||||||
|
self.assertEqual(result, {"key1": "value1", "key2": "value2"})
|
||||||
|
mock_read.assert_called_once_with("/path/to/file")
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "read_file")
|
||||||
|
def test_read_yaml_file_open_failure(self, mock_read):
|
||||||
|
mock_read.side_effect = IOError
|
||||||
|
self.assertRaises(SystemExit, utils.read_yaml_file, "/path/to/file")
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "read_file")
|
||||||
|
def test_read_yaml_file_not_yaml(self, mock_read):
|
||||||
|
mock_read.return_value = "[1{!"
|
||||||
|
self.assertRaises(SystemExit, utils.read_yaml_file, "/path/to/file")
|
||||||
|
|
||||||
|
@mock.patch.object(subprocess, "check_call")
|
||||||
|
def test_run_command(self, mock_call):
|
||||||
|
utils.run_command(["command", "to", "run"])
|
||||||
|
mock_call.assert_called_once_with(["command", "to", "run"])
|
||||||
|
|
||||||
|
@mock.patch.object(subprocess, "check_call")
|
||||||
|
def test_run_command_quiet(self, mock_call):
|
||||||
|
utils.run_command(["command", "to", "run"], quiet=True)
|
||||||
|
mock_call.assert_called_once_with(["command", "to", "run"],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
@mock.patch.object(subprocess, "check_call")
|
||||||
|
def test_run_command_failure(self, mock_call):
|
||||||
|
mock_call.side_effect = subprocess.CalledProcessError(1, "command")
|
||||||
|
self.assertRaises(subprocess.CalledProcessError, utils.run_command,
|
||||||
|
["command", "to", "run"])
|
|
@ -2,6 +2,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,25 +14,43 @@ def yum_install(packages):
|
||||||
cmd = ["sudo", "yum", "-y", "install"]
|
cmd = ["sudo", "yum", "-y", "install"]
|
||||||
cmd += packages
|
cmd += packages
|
||||||
try:
|
try:
|
||||||
subprocess.check_call(cmd)
|
run_command(cmd)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print ("Failed to install packages %s via Yum: returncode %d" %
|
print ("Failed to install packages %s via Yum: returncode %d" %
|
||||||
(", ".join(packages), e.returncode))
|
(", ".join(packages), e.returncode))
|
||||||
sys.exit(e.returncode)
|
sys.exit(e.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def galaxy_install(role_file, roles_path):
|
||||||
|
"""Install Ansible roles via Ansible Galaxy."""
|
||||||
|
cmd = ["ansible-galaxy", "install"]
|
||||||
|
cmd += ["--roles-path", roles_path]
|
||||||
|
cmd += ["--role-file", role_file]
|
||||||
|
try:
|
||||||
|
run_command(cmd)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
LOG.error("Failed to install Ansible roles from %s via Ansible "
|
||||||
|
"Galaxy: returncode %d", role_file, e.returncode)
|
||||||
|
sys.exit(e.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def read_file(path, mode="r"):
|
||||||
|
"""Read the content of a file."""
|
||||||
|
with open(path, mode) as f:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
def read_yaml_file(path):
|
def read_yaml_file(path):
|
||||||
"""Read and decode a YAML file."""
|
"""Read and decode a YAML file."""
|
||||||
try:
|
try:
|
||||||
with open(path, "r") as f:
|
content = read_file(path)
|
||||||
content = f.read()
|
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
print ("Failed to open config dump file %s: %s" %
|
print ("Failed to open config dump file %s: %s" %
|
||||||
(path, repr(e)))
|
(path, repr(e)))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
try:
|
try:
|
||||||
return yaml.load(content)
|
return yaml.load(content)
|
||||||
except ValueError as e:
|
except yaml.YAMLError as e:
|
||||||
print ("Failed to decode config dump YAML file %s: %s" %
|
print ("Failed to decode config dump YAML file %s: %s" %
|
||||||
(path, repr(e)))
|
(path, repr(e)))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
cliff
|
cliff
|
||||||
|
PyYAML
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
hacking
|
||||||
|
coverage
|
||||||
|
flake8-import-order
|
||||||
|
mock
|
||||||
|
unittest2
|
|
@ -0,0 +1,35 @@
|
||||||
|
[tox]
|
||||||
|
minversion = 1.8
|
||||||
|
skipsdist = True
|
||||||
|
envlist = py27,pep8
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
usedevelop = True
|
||||||
|
install_command = pip install -U {opts} {packages}
|
||||||
|
setenv = VIRTUAL_ENV={envdir}
|
||||||
|
PYTHONDONTWRITEBYTECODE = 1
|
||||||
|
LANGUAGE=en_US
|
||||||
|
LC_ALL=en_US.UTF-8
|
||||||
|
PYTHONWARNINGS=default::DeprecationWarning
|
||||||
|
TESTS_DIR=./kayobe/tests/unit/
|
||||||
|
deps = -r{toxinidir}/test-requirements.txt
|
||||||
|
commands = unit2 discover {posargs}
|
||||||
|
passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
|
||||||
|
|
||||||
|
[testenv:pep8]
|
||||||
|
whitelist_externals = bash
|
||||||
|
commands =
|
||||||
|
flake8 {posargs}
|
||||||
|
|
||||||
|
[testenv:venv]
|
||||||
|
setenv = PYTHONHASHSEED=0
|
||||||
|
commands = {posargs}
|
||||||
|
|
||||||
|
[flake8]
|
||||||
|
exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build
|
||||||
|
import-order-style = pep8
|
||||||
|
max-complexity=17
|
||||||
|
# [H106] Don’t put vim configuration in source files.
|
||||||
|
# [H203] Use assertIs(Not)None to check for None.
|
||||||
|
# [H904] Delay string interpolations at logging calls.
|
||||||
|
enable-extensions=H106,H203,H904
|
Loading…
Reference in New Issue