diff --git a/Pipfile b/Pipfile index 116b02ecb..ab6757e36 100644 --- a/Pipfile +++ b/Pipfile @@ -5,6 +5,7 @@ name = "pypi" [packages] tobiko = {editable = true, path = "."} +ansible = "*" [dev-packages] diff --git a/extra-requirements.txt b/extra-requirements.txt new file mode 100644 index 000000000..f3a3f524c --- /dev/null +++ b/extra-requirements.txt @@ -0,0 +1 @@ +ansible>=2.4.0 diff --git a/tobiko/cmd/create.py b/tobiko/cmd/create.py index b5f61d58f..3821463cd 100644 --- a/tobiko/cmd/create.py +++ b/tobiko/cmd/create.py @@ -39,6 +39,10 @@ class CreateUtil(base.TobikoCMD): '--stack', '-s', help="The name of the stack to create.\n" "This is based on the template name in templates dir") + parser.add_argument( + '--playbook', '-p', + help="The name of the playbook to execute.\n" + "This is based on the playbook name in playbooks dir") parser.add_argument( '--all', '-a', action='store_true', dest='all', help="Create all the stacks defined in Tobiko.") @@ -62,6 +66,10 @@ class CreateUtil(base.TobikoCMD): parameters=constants.DEFAULT_PARAMS, wait=wait) + def run_playbook(self, playbook): + """Executes given playbook.""" + self.ansibleManager.run_playbook(playbook, mode='create') + class NoSuchTemplateError(exceptions.TobikoException): message = "No such template. Existing templates:\n%(templates)s" @@ -70,9 +78,12 @@ class NoSuchTemplateError(exceptions.TobikoException): def main(): """Create CLI main entry.""" create_cmd = CreateUtil() - create_cmd.create_stacks(stack_name=create_cmd.args.stack, - all_stacks=create_cmd.args.all, - wait=create_cmd.args.wait) + if create_cmd.args.playbook: + create_cmd.run_playbook(create_cmd.args.playbook) + else: + create_cmd.create_stacks(stack_name=create_cmd.args.stack, + all_stacks=create_cmd.args.all, + wait=create_cmd.args.wait) if __name__ == '__main__': diff --git a/tobiko/common/managers/ansible.py b/tobiko/common/managers/ansible.py index 1abb5515f..e4018b84e 100644 --- a/tobiko/common/managers/ansible.py +++ b/tobiko/common/managers/ansible.py @@ -15,6 +15,12 @@ from __future__ import absolute_import import os +from collections import namedtuple + +from ansible.executor import playbook_executor +from ansible.inventory.manager import InventoryManager +from ansible.parsing.dataloader import DataLoader +from ansible.vars.manager import VariableManager from oslo_log import log from tobiko.common import constants @@ -26,9 +32,16 @@ LOG = log.getLogger(__name__) class AnsibleManager(object): """Manages Ansible entities.""" - def __init__(self, client_manager, templates_dir): - self.client_manager = client_manager.heat_client - self.playbooks_dir = templates_dir + def __init__(self, client_manager, playbooks_dir): + self.client_manager = client_manager + self.playbooks_dir = playbooks_dir + self.loader = DataLoader() + self.inventory = InventoryManager(loader=self.loader, + sources='localhost,') + self.variable_manager = VariableManager(loader=self.loader, + inventory=self.inventory) + self.options = self.get_options() + self.passwords = dict(vault_pass='secret') def get_playbooks_names(self, strip_suffix=False): """Returns a list of all the files in playbooks dir.""" @@ -39,3 +52,44 @@ class AnsibleManager(object): playbooks = [ f[:-len(constants.TEMPLATE_SUFFIX)] for f in playbooks] return playbooks + + def get_options(self): + """Returns namedtuple of Ansible options.""" + Options = namedtuple('Options', ['connection', 'module_path', + 'forks', 'become', 'become_method', + 'become_user', 'check', 'diff', + 'listhosts', 'listtasks', + 'listtags', 'syntax']) + + options = Options(connection='local', module_path=['/to/mymodules'], + forks=10, become=None, become_method=None, + become_user=None, check=False, diff=False, + listhosts=False, + listtasks=False, listtags=False, syntax=False) + + return options + + def run_playbook(self, playbook, mode='create'): + """Executes given playbook.""" + playbook_path = self.playbooks_dir + '/' + playbook + + extra_vars = {'mode': mode, + 'auth_url': self.client_manager.credentials['auth_url'], + 'username': self.client_manager.credentials['username'], + 'project_name': self.client_manager.credentials[ + 'project_name'], + 'image': constants.DEFAULT_PARAMS['image'], + 'flavor': constants.DEFAULT_PARAMS['flavor'], + 'password': self.client_manager.credentials['password']} + + self.variable_manager.extra_vars = extra_vars + + pb_executor = playbook_executor.PlaybookExecutor( + playbooks=[playbook_path], + inventory=self.inventory, + variable_manager=self.variable_manager, + loader=self.loader, + options=self.options, + passwords=self.passwords) + + pb_executor.run() diff --git a/tobiko/tests/scenario/playbooks/test_floatingip.yaml b/tobiko/tests/scenario/playbooks/test_floatingip.yaml index 8ce7d99a1..bac374cd3 100644 --- a/tobiko/tests/scenario/playbooks/test_floatingip.yaml +++ b/tobiko/tests/scenario/playbooks/test_floatingip.yaml @@ -11,8 +11,18 @@ project_name: "{{ project_name }}" name: server1 image: "{{ image }}" - key_name: "{{ key }}" timeout: 200 flavor: "{{ flavor }}" security_groups: default - auto_ip: yes + when: mode == 'create' + + - name: Remove instance + os_server: + state: absent + auth: + auth_url: "{{ auth_url }}" + username: "{{ username }}" + password: "{{ password }}" + project_name: "{{ project_name }}" + name: server1 + when: mode == 'delete' diff --git a/tox.ini b/tox.ini index 7c2ac11f1..cfa2ecd65 100644 --- a/tox.ini +++ b/tox.ini @@ -8,6 +8,7 @@ minversion = 2.0 deps = -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} -r{toxinidir}/requirements.txt + -r{toxinidir}/extra-requirements.txt setenv = VIRTUAL_ENV={envdir} @@ -33,6 +34,7 @@ commands = deps = {[tobiko]deps} -r{toxinidir}/test-requirements.txt + -r{toxinidir}/extra-requirements.txt setenv = {[tobiko]setenv}