""" Module responsible for running the Ansible part of the OpenAppStack setup. """ import logging import os import subprocess import yaml log = logging.getLogger(__name__) # pylint: disable=invalid-name ANSIBLE_INVENTORY = './clusters/{cluster_name}/inventory.yml' ANSIBLE_PATH = os.path.join(os.path.dirname(__file__), '..', 'ansible') def run_ansible(clus, playbook, ansible_params=None): """ Call `ansible-playbook` in a subprocess to run the specified playbook. Runs in the package's ansible directory. :param str playbook: path to the playbook to run. :param list ansible_params: Optionally provide a list of lists with ansible params. Each inner list may only contain one element. Can be directly forwarded from argparse. Example: `ansible_params = [[become-user=root], [verbose]]` """ # playbook path here is relative to private_data_dir/project, see # https://ansible-runner.readthedocs.io/en/latest/intro.html#inputdir ansible_playbook_command = ['ansible-playbook'] if ansible_params: for param in ansible_params: if len(param) > 1: log.warning('More than 1 parameter. Ignoring the rest! Use ' '--ansible-param several times to supply ' 'more than 1 parameter') param = param[0] ansible_playbook_command.append(param) ansible_playbook_command += \ ['-e', 'cluster_dir=' + clus.cluster_dir] ansible_playbook_command += \ ['-i', clus.inventory_file, playbook] log.info('Running "%s" in ansible directory "%s"', ansible_playbook_command, ANSIBLE_PATH) process = subprocess.Popen( ansible_playbook_command, cwd=ANSIBLE_PATH) returncode = process.wait() if returncode > 0: raise RuntimeError('Playbook failed with rc %s.' % returncode) def create_inventory(cluster): """ Creates inventory for the ansible playbook. Needs the droplet's hostname for identification and the IP for connecting with Ansible :param cluster.Cluster cluster: Cluster object to for which inventory file will be written. Used for getting hostname and IP address. """ # Create inventory with open(os.path.join(ANSIBLE_PATH, 'inventory.yml.example'), 'r') as stream: inventory = yaml.safe_load(stream) # Rename the hostname in the inventory to one provided by the user. if cluster.hostname != 'oas-dev': inventory['all']['hosts'][cluster.hostname] = \ inventory['all']['hosts']['oas-dev'] del inventory['all']['hosts']['oas-dev'] inventory['all']['hosts'][cluster.hostname]['ansible_host'] = \ cluster.ip_address inventory['all']['hosts'][cluster.hostname]['domain'] = \ cluster.domain if cluster.docker_mirror_endpoint \ and cluster.docker_mirror_server \ and cluster.docker_mirror_username \ and cluster.docker_mirror_password: docker_mirror = {} docker_mirror['enabled'] = True docker_mirror['endpoint'] = cluster.docker_mirror_endpoint docker_mirror['username'] = cluster.docker_mirror_username docker_mirror['password'] = cluster.docker_mirror_password docker_mirror['server'] = cluster.docker_mirror_server inventory['all']['hosts'][cluster.hostname]['docker_mirror'] = \ docker_mirror inventory['all']['children']['master']['hosts'] = cluster.hostname inventory['all']['children']['worker']['hosts'] = cluster.hostname file_contents = yaml.safe_dump(inventory, default_flow_style=False) log.debug(file_contents) with open(cluster.inventory_file, 'w') as stream: stream.write(file_contents) log.info("Created %s", cluster.inventory_file) return inventory