Support multiple environments from a single configuration
Change-Id: I848d834aa36943027c126e26e93e4a4680521144 Story: 2002009 Task: 40037
This commit is contained in:
parent
f8575af9c0
commit
1419636930
@ -47,7 +47,7 @@
|
||||
console_allocation_pool_start: "{{ ironic_serial_console_tcp_pool_start }}"
|
||||
console_allocation_pool_end: "{{ ironic_serial_console_tcp_pool_end }}"
|
||||
console_allocation_ironic_nodes: "{{ baremetal_nodes }}"
|
||||
console_allocation_filename: "{{ kayobe_config_path }}/console-allocation.yml"
|
||||
console_allocation_filename: "{{ kayobe_env_config_path }}/console-allocation.yml"
|
||||
when: cmd == "enable"
|
||||
|
||||
- name: Enable serial console
|
||||
|
@ -7,6 +7,15 @@
|
||||
# Path to Kayobe configuration directory on Ansible control host.
|
||||
kayobe_config_path: "{{ lookup('env', 'KAYOBE_CONFIG_PATH') | default('/etc/kayobe', true) }}"
|
||||
|
||||
# Name of Kayobe environment to use. Default is $KAYOBE_ENVIRONMENT, or an
|
||||
# empty string if $KAYOBE_ENVIRONMENT is not set. Can also be set via the
|
||||
# --environment argument when invoking kayobe.
|
||||
kayobe_environment: "{{ lookup('env', 'KAYOBE_ENVIRONMENT') }}"
|
||||
|
||||
# Path to Kayobe configuration directory on Ansible control host with an
|
||||
# environment path appended if kayobe_environment is set.
|
||||
kayobe_env_config_path: "{{ kayobe_config_path ~ ('/environments/' ~ kayobe_environment if kayobe_environment else '') }}"
|
||||
|
||||
###############################################################################
|
||||
# Remote path configuration (seed, seed-hypervisor and overcloud hosts).
|
||||
|
||||
|
@ -109,7 +109,7 @@ seed_users: "{{ users_default }}"
|
||||
# squid:
|
||||
# name: "squid"
|
||||
# image: "stackhpc/squid:3.5.20-1"
|
||||
# pre: "{{ kayobe_config_path }}/containers/squid/pre.yml"
|
||||
# post: "{{ kayobe_config_path }}/containers/squid/post.yml"
|
||||
# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml"
|
||||
# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml"
|
||||
#
|
||||
seed_containers: {}
|
||||
|
@ -29,5 +29,5 @@
|
||||
- item | net_bootproto != 'dhcp'
|
||||
roles:
|
||||
- role: ip-allocation
|
||||
ip_allocation_filename: "{{ kayobe_config_path }}/network-allocation.yml"
|
||||
ip_allocation_filename: "{{ kayobe_env_config_path }}/network-allocation.yml"
|
||||
ip_allocation_hostname: "{{ inventory_hostname }}"
|
||||
|
@ -32,7 +32,7 @@
|
||||
- block:
|
||||
- name: Check whether a Kolla extra globals configuration file exists
|
||||
stat:
|
||||
path: "{{ kayobe_config_path ~ '/kolla/globals.yml' }}"
|
||||
path: "{{ kayobe_env_config_path ~ '/kolla/globals.yml' }}"
|
||||
get_checksum: False
|
||||
get_md5: False
|
||||
mime: False
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
- name: Read the Kolla extra globals configuration file
|
||||
set_fact:
|
||||
kolla_extra_globals: "{{ lookup('template', kayobe_config_path ~ '/kolla/globals.yml') | from_yaml }}"
|
||||
kolla_extra_globals: "{{ lookup('template', kayobe_env_config_path ~ '/kolla/globals.yml') | from_yaml }}"
|
||||
when: globals_stat.stat.exists
|
||||
tags:
|
||||
- config
|
||||
@ -79,9 +79,9 @@
|
||||
kolla_ansible_install_epel: "{{ dnf_install_epel }}"
|
||||
kolla_external_fqdn_cert: "{{ kolla_config_path }}/certificates/haproxy.pem"
|
||||
kolla_internal_fqdn_cert: "{{ kolla_config_path }}/certificates/haproxy-internal.pem"
|
||||
kolla_ansible_passwords_path: "{{ kayobe_config_path }}/kolla/passwords.yml"
|
||||
kolla_overcloud_group_vars_path: "{{ kayobe_config_path }}/kolla/inventory/group_vars"
|
||||
kolla_ansible_certificates_path: "{{ kayobe_config_path }}/kolla/certificates"
|
||||
kolla_ansible_passwords_path: "{{ kayobe_env_config_path }}/kolla/passwords.yml"
|
||||
kolla_overcloud_group_vars_path: "{{ kayobe_env_config_path }}/kolla/inventory/group_vars"
|
||||
kolla_ansible_certificates_path: "{{ kayobe_env_config_path }}/kolla/certificates"
|
||||
# NOTE: This differs from the default SELinux mode in kolla ansible,
|
||||
# which is permissive. The justification for using this mode is twofold:
|
||||
# 1. it avoids filling up the audit log
|
||||
|
@ -4,7 +4,7 @@
|
||||
tags:
|
||||
- kolla-bifrost
|
||||
vars:
|
||||
kolla_bifrost_extra_globals_path: "{{ kayobe_config_path ~ '/kolla/config/bifrost/bifrost.yml' }}"
|
||||
kolla_bifrost_extra_globals_path: "{{ kayobe_env_config_path ~ '/kolla/config/bifrost/bifrost.yml' }}"
|
||||
|
||||
pre_tasks:
|
||||
- name: Check whether a Kolla Bifrost extra globals configuration file exists
|
||||
|
@ -7,4 +7,4 @@
|
||||
- role: kolla
|
||||
kolla_install_epel: "{{ dnf_install_epel }}"
|
||||
- role: kolla-build
|
||||
kolla_build_extra_config_path: "{{ kayobe_config_path }}/kolla/kolla-build.conf"
|
||||
kolla_build_extra_config_path: "{{ kayobe_env_config_path }}/kolla/kolla-build.conf"
|
||||
|
@ -101,7 +101,7 @@
|
||||
- block:
|
||||
- name: Check whether Kolla extra configuration files exist
|
||||
stat:
|
||||
path: "{{ kayobe_config_path }}/kolla/config/{{ item.file }}"
|
||||
path: "{{ kayobe_env_config_path }}/kolla/config/{{ item.file }}"
|
||||
get_checksum: False
|
||||
get_md5: False
|
||||
mime: False
|
||||
@ -245,4 +245,4 @@
|
||||
kolla_extra_octavia: "{{ kolla_extra_config.octavia | default }}"
|
||||
kolla_extra_sahara: "{{ kolla_extra_config.sahara | default }}"
|
||||
kolla_extra_zookeeper: "{{ kolla_extra_config.zookeeper | default }}"
|
||||
kolla_extra_config_path: "{{ kayobe_config_path }}/kolla/config"
|
||||
kolla_extra_config_path: "{{ kayobe_env_config_path }}/kolla/config"
|
||||
|
@ -61,7 +61,7 @@
|
||||
- grafana
|
||||
pre_tasks:
|
||||
- name: Include Kolla passwords for Grafana local admin account credentials
|
||||
include_vars: "{{ kayobe_config_path }}/kolla/passwords.yml"
|
||||
include_vars: "{{ kayobe_env_config_path }}/kolla/passwords.yml"
|
||||
roles:
|
||||
- role: stackhpc.grafana-conf
|
||||
grafana_conf_organisation: "{{ grafana_control_plane_organisation }}"
|
||||
|
@ -53,4 +53,4 @@
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
dest: "{{ kayobe_config_path }}/inventory/overcloud"
|
||||
dest: "{{ kayobe_env_config_path }}/inventory/overcloud"
|
||||
|
@ -31,5 +31,5 @@
|
||||
- include_role:
|
||||
name: swift-rings
|
||||
vars:
|
||||
swift_config_path: "{{ kayobe_config_path }}/kolla/config/swift"
|
||||
swift_config_path: "{{ kayobe_env_config_path }}/kolla/config/swift"
|
||||
when: kolla_enable_swift | bool
|
||||
|
@ -18,8 +18,8 @@ For example, to deploy a squid container image:
|
||||
seed_containers:
|
||||
squid:
|
||||
image: "stackhpc/squid:3.5.20-1"
|
||||
pre: "{{ kayobe_config_path }}/containers/squid/pre.yml"
|
||||
post: "{{ kayobe_config_path }}/containers/squid/post.yml"
|
||||
pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml"
|
||||
post: "{{ kayobe_env_config_path }}/containers/squid/post.yml"
|
||||
|
||||
Please notice the *optional* pre and post Ansible task files - those need to
|
||||
be created in ``kayobe-config`` path and will be run before and after
|
||||
|
@ -4,9 +4,19 @@
|
||||
###############################################################################
|
||||
# Local path configuration (Ansible control host).
|
||||
|
||||
# Path to Kayobe configuration directory on Ansible control host.
|
||||
# Path to Kayobe configuration directory on Ansible control host, with an
|
||||
# environment path appended if kayobe_environment is set.
|
||||
#kayobe_config_path:
|
||||
|
||||
# Name of Kayobe environment to use. Default is $KAYOBE_ENVIRONMENT, or an
|
||||
# empty string if $KAYOBE_ENVIRONMENT is not set. Can also be set via the
|
||||
# --environment argument when invoking kayobe.
|
||||
#kayobe_environment:
|
||||
|
||||
# Path to Kayobe configuration directory on Ansible control host with an
|
||||
# environment path appended if kayobe_environment is set.
|
||||
#kayobe_env_config_path:
|
||||
|
||||
###############################################################################
|
||||
# Remote path configuration (seed, seed-hypervisor and overcloud hosts).
|
||||
|
||||
|
@ -92,8 +92,8 @@
|
||||
# squid:
|
||||
# name: "squid"
|
||||
# image: "stackhpc/squid:3.5.20-1"
|
||||
# pre: "{{ kayobe_config_path }}/containers/squid/pre.yml"
|
||||
# post: "{{ kayobe_config_path }}/containers/squid/post.yml"
|
||||
# pre: "{{ kayobe_env_config_path }}/containers/squid/pre.yml"
|
||||
# post: "{{ kayobe_env_config_path }}/containers/squid/post.yml"
|
||||
#
|
||||
#seed_containers:
|
||||
|
||||
|
@ -30,12 +30,15 @@ DEFAULT_CONFIG_PATH = "/etc/kayobe"
|
||||
|
||||
CONFIG_PATH_ENV = "KAYOBE_CONFIG_PATH"
|
||||
|
||||
ENVIRONMENT_ENV = "KAYOBE_ENVIRONMENT"
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def add_args(parser):
|
||||
"""Add arguments required for running Ansible playbooks to a parser."""
|
||||
default_config_path = os.getenv(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH)
|
||||
default_environment = os.getenv(ENVIRONMENT_ENV)
|
||||
parser.add_argument("-b", "--become", action="store_true",
|
||||
help="run operations with become (nopasswd implied)")
|
||||
parser.add_argument("-C", "--check", action="store_true",
|
||||
@ -45,6 +48,9 @@ def add_args(parser):
|
||||
help="path to Kayobe configuration. "
|
||||
"(default=$%s or %s)" %
|
||||
(CONFIG_PATH_ENV, DEFAULT_CONFIG_PATH))
|
||||
parser.add_argument("--environment", default=default_environment,
|
||||
help="specify environment name (default=$%s or None)" %
|
||||
ENVIRONMENT_ENV)
|
||||
parser.add_argument("-e", "--extra-vars", metavar="EXTRA_VARS",
|
||||
action="append",
|
||||
help="set additional variables as key=value or "
|
||||
@ -69,12 +75,23 @@ def add_args(parser):
|
||||
"note this has no affect on kolla-ansible.")
|
||||
|
||||
|
||||
def _get_inventory_path(parsed_args):
|
||||
def _get_kayobe_environment_path(parsed_args):
|
||||
"""Return the path to the Kayobe environment or None if not specified."""
|
||||
env_path = None
|
||||
if parsed_args.environment:
|
||||
# Specified via --environment or KAYOBE_ENVIRONMENT.
|
||||
kc_environments = os.path.join(parsed_args.config_path, "environments")
|
||||
env_path = os.path.join(kc_environments, parsed_args.environment)
|
||||
return env_path
|
||||
|
||||
|
||||
def _get_inventory_path(parsed_args, env_path):
|
||||
"""Return the path to the Kayobe inventory."""
|
||||
if parsed_args.inventory:
|
||||
return parsed_args.inventory
|
||||
else:
|
||||
return os.path.join(parsed_args.config_path, "inventory")
|
||||
return os.path.join(env_path if env_path else parsed_args.config_path,
|
||||
"inventory")
|
||||
|
||||
|
||||
def _validate_args(parsed_args, playbooks):
|
||||
@ -86,7 +103,15 @@ def _validate_args(parsed_args, playbooks):
|
||||
parsed_args.config_path, result["message"])
|
||||
sys.exit(1)
|
||||
|
||||
inventory = _get_inventory_path(parsed_args)
|
||||
env_path = _get_kayobe_environment_path(parsed_args)
|
||||
if env_path:
|
||||
result = utils.is_readable_dir(env_path)
|
||||
if not result["result"]:
|
||||
LOG.error("Kayobe environment %s is invalid: %s",
|
||||
env_path, result["message"])
|
||||
sys.exit(1)
|
||||
|
||||
inventory = _get_inventory_path(parsed_args, env_path)
|
||||
result = utils.is_readable_dir(inventory)
|
||||
if not result["result"]:
|
||||
LOG.error("Kayobe inventory %s is invalid: %s",
|
||||
@ -101,19 +126,25 @@ def _validate_args(parsed_args, playbooks):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def _get_vars_files(config_path):
|
||||
def _get_vars_files(vars_paths):
|
||||
"""Return a list of Kayobe Ansible configuration variable files.
|
||||
|
||||
The files will be sorted alphabetically by name.
|
||||
The list of directories given as argument is searched to create the list of
|
||||
variable files. The files will be sorted alphabetically by name for each
|
||||
directory, but ordering of directories is kept to allow overrides.
|
||||
"""
|
||||
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)["result"]:
|
||||
root, ext = os.path.splitext(vars_file)
|
||||
if ext in (".yml", ".yaml", ".json"):
|
||||
vars_files.append(abs_path)
|
||||
return sorted(vars_files)
|
||||
for vars_path in vars_paths:
|
||||
path_vars_files = []
|
||||
for vars_file in os.listdir(vars_path):
|
||||
abs_path = os.path.join(vars_path, vars_file)
|
||||
if utils.is_readable_file(abs_path)["result"]:
|
||||
root, ext = os.path.splitext(vars_file)
|
||||
if ext in (".yml", ".yaml", ".json"):
|
||||
path_vars_files.append(abs_path)
|
||||
vars_files += sorted(path_vars_files)
|
||||
|
||||
return vars_files
|
||||
|
||||
|
||||
def build_args(parsed_args, playbooks,
|
||||
@ -126,9 +157,13 @@ def build_args(parsed_args, playbooks,
|
||||
if list_tasks or (parsed_args.list_tasks and list_tasks is None):
|
||||
cmd += ["--list-tasks"]
|
||||
cmd += vault.build_args(parsed_args, "--vault-password-file")
|
||||
inventory = _get_inventory_path(parsed_args)
|
||||
env_path = _get_kayobe_environment_path(parsed_args)
|
||||
inventory = _get_inventory_path(parsed_args, env_path)
|
||||
cmd += ["--inventory", inventory]
|
||||
vars_files = _get_vars_files(parsed_args.config_path)
|
||||
vars_paths = [parsed_args.config_path]
|
||||
if env_path:
|
||||
vars_paths.append(env_path)
|
||||
vars_files = _get_vars_files(vars_paths)
|
||||
for vars_file in vars_files:
|
||||
cmd += ["-e", "@%s" % vars_file]
|
||||
if parsed_args.extra_vars:
|
||||
@ -165,6 +200,10 @@ def _get_environment(parsed_args):
|
||||
# the environment variable is set, so that it can be referenced by
|
||||
# playbooks.
|
||||
env.setdefault(CONFIG_PATH_ENV, parsed_args.config_path)
|
||||
# If an environment has been specified via --environment, ensure the
|
||||
# environment variable is set, so that it can be referenced by playbooks.
|
||||
if parsed_args.environment:
|
||||
env.setdefault(ENVIRONMENT_ENV, parsed_args.environment)
|
||||
# If a custom Ansible configuration file exists, use it.
|
||||
ansible_cfg_path = os.path.join(parsed_args.config_path, "ansible.cfg")
|
||||
if utils.is_readable_file(ansible_cfg_path)["result"]:
|
||||
@ -291,6 +330,7 @@ def prune_galaxy_roles(parsed_args):
|
||||
|
||||
def passwords_yml_exists(parsed_args):
|
||||
"""Return whether passwords.yml exists in the kayobe configuration."""
|
||||
passwords_path = os.path.join(parsed_args.config_path,
|
||||
'kolla', 'passwords.yml')
|
||||
env_path = _get_kayobe_environment_path(parsed_args)
|
||||
path = env_path if env_path else parsed_args.config_path
|
||||
passwords_path = os.path.join(path, 'kolla', 'passwords.yml')
|
||||
return utils.is_readable_file(passwords_path)["result"]
|
||||
|
@ -52,7 +52,7 @@ class TestCase(unittest.TestCase):
|
||||
expected_env = {"KAYOBE_CONFIG_PATH": "/etc/kayobe"}
|
||||
mock_run.assert_called_once_with(expected_cmd, check_output=False,
|
||||
quiet=False, env=expected_env)
|
||||
mock_vars.assert_called_once_with("/etc/kayobe")
|
||||
mock_vars.assert_called_once_with(["/etc/kayobe"])
|
||||
|
||||
@mock.patch.object(utils, "run_command")
|
||||
@mock.patch.object(ansible, "_get_vars_files")
|
||||
@ -68,6 +68,7 @@ class TestCase(unittest.TestCase):
|
||||
"-b",
|
||||
"-C",
|
||||
"--config-path", "/path/to/config",
|
||||
"--environment", "test-env",
|
||||
"-e", "ev_name1=ev_value1",
|
||||
"-i", "/path/to/inventory",
|
||||
"-l", "group1:host",
|
||||
@ -92,10 +93,12 @@ class TestCase(unittest.TestCase):
|
||||
"playbook1.yml",
|
||||
"playbook2.yml",
|
||||
]
|
||||
expected_env = {"KAYOBE_CONFIG_PATH": "/path/to/config"}
|
||||
expected_env = {"KAYOBE_CONFIG_PATH": "/path/to/config",
|
||||
"KAYOBE_ENVIRONMENT": "test-env"}
|
||||
mock_run.assert_called_once_with(expected_cmd, check_output=False,
|
||||
quiet=False, env=expected_env)
|
||||
mock_vars.assert_called_once_with("/path/to/config")
|
||||
mock_vars.assert_called_once_with(
|
||||
["/path/to/config", "/path/to/config/environments/test-env"])
|
||||
|
||||
@mock.patch.object(utils, "run_command")
|
||||
@mock.patch.object(ansible, "_get_vars_files")
|
||||
@ -114,6 +117,7 @@ class TestCase(unittest.TestCase):
|
||||
"--become",
|
||||
"--check",
|
||||
"--config-path", "/path/to/config",
|
||||
"--environment", "test-env",
|
||||
"--extra-vars", "ev_name1=ev_value1",
|
||||
"--inventory", "/path/to/inventory",
|
||||
"--limit", "group1:host1",
|
||||
@ -141,6 +145,7 @@ class TestCase(unittest.TestCase):
|
||||
"playbook2.yml",
|
||||
]
|
||||
expected_env = {"KAYOBE_CONFIG_PATH": "/path/to/config",
|
||||
"KAYOBE_ENVIRONMENT": "test-env",
|
||||
"KAYOBE_VAULT_PASSWORD": "test-pass"}
|
||||
expected_calls = [
|
||||
mock.call(["which", "kayobe-vault-password-helper"],
|
||||
@ -149,7 +154,8 @@ class TestCase(unittest.TestCase):
|
||||
env=expected_env)
|
||||
]
|
||||
self.assertEqual(expected_calls, mock_run.mock_calls)
|
||||
mock_vars.assert_called_once_with("/path/to/config")
|
||||
mock_vars.assert_called_once_with(
|
||||
["/path/to/config", "/path/to/config/environments/test-env"])
|
||||
|
||||
@mock.patch.object(utils, "run_command")
|
||||
@mock.patch.object(ansible, "_get_vars_files")
|
||||
@ -262,7 +268,7 @@ class TestCase(unittest.TestCase):
|
||||
expected_env = {"KAYOBE_CONFIG_PATH": "/etc/kayobe"}
|
||||
mock_run.assert_called_once_with(expected_cmd, check_output=False,
|
||||
quiet=False, env=expected_env)
|
||||
mock_vars.assert_called_once_with("/etc/kayobe")
|
||||
mock_vars.assert_called_once_with(["/etc/kayobe"])
|
||||
|
||||
@mock.patch.object(utils, "run_command")
|
||||
@mock.patch.object(ansible, "_get_vars_files")
|
||||
@ -291,7 +297,7 @@ class TestCase(unittest.TestCase):
|
||||
expected_env = {"KAYOBE_CONFIG_PATH": "/etc/kayobe"}
|
||||
mock_run.assert_called_once_with(expected_cmd, check_output=False,
|
||||
quiet=False, env=expected_env)
|
||||
mock_vars.assert_called_once_with("/etc/kayobe")
|
||||
mock_vars.assert_called_once_with(["/etc/kayobe"])
|
||||
|
||||
@mock.patch.object(utils, "run_command")
|
||||
@mock.patch.object(ansible, "_get_vars_files")
|
||||
@ -320,7 +326,7 @@ class TestCase(unittest.TestCase):
|
||||
expected_env = {"KAYOBE_CONFIG_PATH": "/etc/kayobe"}
|
||||
mock_run.assert_called_once_with(expected_cmd, check_output=False,
|
||||
quiet=False, env=expected_env)
|
||||
mock_vars.assert_called_once_with("/etc/kayobe")
|
||||
mock_vars.assert_called_once_with(["/etc/kayobe"])
|
||||
|
||||
@mock.patch.object(utils, "run_command")
|
||||
@mock.patch.object(utils, "is_readable_file")
|
||||
@ -346,7 +352,7 @@ class TestCase(unittest.TestCase):
|
||||
}
|
||||
mock_run.assert_called_once_with(expected_cmd, check_output=False,
|
||||
quiet=False, env=expected_env)
|
||||
mock_vars.assert_called_once_with("/etc/kayobe")
|
||||
mock_vars.assert_called_once_with(["/etc/kayobe"])
|
||||
mock_readable.assert_called_once_with("/etc/kayobe/ansible.cfg")
|
||||
|
||||
@mock.patch.object(utils, "run_command")
|
||||
@ -374,7 +380,7 @@ class TestCase(unittest.TestCase):
|
||||
}
|
||||
mock_run.assert_called_once_with(expected_cmd, check_output=False,
|
||||
quiet=False, env=expected_env)
|
||||
mock_vars.assert_called_once_with("/etc/kayobe")
|
||||
mock_vars.assert_called_once_with(["/etc/kayobe"])
|
||||
mock_readable.assert_called_once_with("/etc/kayobe/ansible.cfg")
|
||||
|
||||
@mock.patch.object(utils, "run_command")
|
||||
|
Loading…
x
Reference in New Issue
Block a user