diff --git a/lib/ansible/module_utils/ansible_tower.py b/lib/ansible/module_utils/ansible_tower.py index 85980c3469..eefbf76753 100644 --- a/lib/ansible/module_utils/ansible_tower.py +++ b/lib/ansible/module_utils/ansible_tower.py @@ -75,3 +75,13 @@ def tower_check_mode(module): module.exit_json(changed=True, tower_version='{0}'.format(result['version'])) except (exc.ServerError, exc.ConnectionError, exc.BadRequest) as excinfo: module.fail_json(changed=False, msg='Failed check mode: {0}'.format(excinfo)) + + +def tower_argument_spec(): + return dict( + tower_host = dict(), + tower_username = dict(), + tower_password = dict(no_log=True), + tower_verify_ssl = dict(type='bool', default=True), + tower_config_file = dict(type='path'), + ) diff --git a/lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_launch.py b/lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_launch.py new file mode 100644 index 0000000000..3a7679d9d1 --- /dev/null +++ b/lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_launch.py @@ -0,0 +1,167 @@ +#!/usr/bin/python +#coding: utf-8 -*- + +# (c) 2017, Wayne Witzel III +# +# This module is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this software. If not, see . + +ANSIBLE_METADATA = {'status': ['preview'], + 'supported_by': 'community', + 'version': '1.0'} + +DOCUMENTATION = ''' +--- +module: tower_job_launch +version_added: "2.3" +short_description: Launch an Ansible Job. +description: + - Launch an Ansible Tower jobs. See + U(https://www.ansible.com/tower) for an overview. +options: + job_template: + description: + - Name of the job_template to use. + required: True + job_explanation: + description: + - Job explanation field. + default: null + job_type: + description: + - Job_type to use for the job, only used if prompt for job_type is set. + choices: ["run", "check", "scan"] + default: null + inventory: + description: + - Inventory to use for the job, only used if prompt for inventory is set. + default: null + credential: + description: + - Credential to use for job, only used if prompt for credential is set. + default: null + extra_vars: + description: + - Extra_vars to use for the job_template. Use '@' for a file. + default: null + limit: + description: + - Limit to use for the job_template. + default: null + tags: + description: + - Specific tags to use for from playbook. + default: null + use_job_endpoint: + description: + - Disable launching jobs from job template. + default: False +extends_documentation_fragment: tower +''' + +EXAMPLES = ''' +- name: Launch a job + tower_job_launch: + job_template: "My Job Template" + register: job +- name: Wait for job max 120s + tower_job_wait: + job_id: job.id + timeout: 120 +''' + +RETURN = ''' +id: + description: job id of the newly launched job + returned: success + type: int + sample: 86 +status: + description: status of newly launched job + returned: success + type: string + sample: pending +''' + + +from ansible.module_utils.basic import AnsibleModule + +try: + import tower_cli + import tower_cli.utils.exceptions as exc + + from tower_cli.conf import settings + from ansible.module_utils.ansible_tower import ( + tower_auth_config, + tower_check_mode, + tower_argument_spec, + ) + + HAS_TOWER_CLI = True +except ImportError: + HAS_TOWER_CLI = False + + +def main(): + argument_spec = tower_argument_spec() + argument_spec.update(dict( + job_template = dict(required=True), + job_type = dict(choices=['run', 'check', 'scan']), + inventory = dict(), + credential = dict(), + limit = dict(), + tags = dict(type='list'), + extra_vars = dict(type='list'), + )) + + module = AnsibleModule( + argument_spec, + supports_check_mode=True + ) + + if not HAS_TOWER_CLI: + module.fail_json(msg='ansible-tower-cli required for this module') + + json_output = {} + tags = module.params.get('tags') + + tower_auth = tower_auth_config(module) + with settings.runtime_values(**tower_auth): + tower_check_mode(module) + try: + params = module.params.copy() + if isinstance(tags, list): + params['tags'] = ','.join(tags) + job = tower_cli.get_resource('job') + + lookup_fields = ('job_template', 'inventory', 'credential') + for field in lookup_fields: + try: + name = params.pop(field) + result = tower_cli.get_resource(field).get(name=name) + params[field] = result['id'] + except exc.NotFound as excinfo: + module.fail_json(msg='Unable to launch job, {0}/{1} was not found: {2}'.format(field, name, excinfo), changed=False) + + result = job.launch(no_input=True, **params) + json_output['id'] = result['id'] + json_output['status'] = result['status'] + except (exc.ConnectionError, exc.BadRequest) as excinfo: + module.fail_json(msg='Unable to launch job: {0}'.format(excinfo), changed=False) + + json_output['changed'] = result['changed'] + module.exit_json(**json_output) + + +if __name__ == '__main__': + main() diff --git a/lib/ansible/utils/module_docs_fragments/tower.py b/lib/ansible/utils/module_docs_fragments/tower.py new file mode 100644 index 0000000000..3a0b3ee777 --- /dev/null +++ b/lib/ansible/utils/module_docs_fragments/tower.py @@ -0,0 +1,64 @@ +# (c) 2017, Wayne Witzel III +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . +# + + +class ModuleDocFragment(object): + + # Ansible Tower documention fragment + DOCUMENTATION = ''' +options: + tower_host: + description: + - URL to your Tower instance. + required: False + default: null + tower_username: + description: + - Username for your Tower instance. + required: False + default: null + tower_password: + description: + - Password for your Tower instance. + required: False + default: null + tower_verify_ssl: + description: + - Dis/allow insecure connections to Tower. If C(no), SSL certificates will not be validated. + This should only be used on personally controlled sites using self-signed certificates. + required: False + default: True + tower_config_file: + description: + - Path to the Tower config file. See notes. + required: False + default: null + + +requirements: + - "python >= 2.6" + - "ansible-tower-cli >= 3.0.2" + +notes: + - If no I(config_file) is provided we will attempt to use the tower-cli library + defaults to find your Tower host information. + - I(config_file) should contain Tower configuration in the following format + host=hostname + username=username + password=password +'''