#!/usr/bin/python # coding: utf-8 -*- # Copyright: (c) 2018, Adrien Fleury # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) from __future__ import absolute_import, division, print_function __metaclass__ = type DOCUMENTATION = ''' --- module: ngci_tower_workflow_template author: "Puneeth Kosaraju" version_added: "2.7.6" short_description: create, update, or destroy Ansible Tower workflow template. description: - Create, update, or destroy Ansible Tower workflows. See U(https://www.ansible.com/tower) for an overview. options: allow_simultaneous: description: - If enabled, simultaneous runs of this job template will be allowed. type: bool description: description: - The description to use for the workflow. extra_vars: description: - Extra variables used by Ansible in YAML or key=value format. name: description: - The name to use for the workflow. required: True organization: description: - The organization the workflow is linked to. schema: description: - > The schema is a JSON- or YAML-formatted string defining the hierarchy structure that connects the nodes. Refer to Tower documentation for more information. survey_enabled: description: - Setting that variable will prompt the user for job type on the workflow launch. type: bool survey: description: - The definition of the survey associated to the workflow. state: description: - Desired state of the resource. default: "present" choices: ["present", "absent"] extends_documentation_fragment: tower ''' EXAMPLES = ''' - tower_workflow_template: name: Workflow Template description: My very first Worflow Template organization: My optional Organization schema: "{{ lookup('file', 'my_workflow.json') }}" - tower_worflow_template: name: Workflow Template state: absent ''' RETURN = ''' # ''' from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.ansible_tower import ( TowerModule, tower_auth_config, tower_check_mode ) import yaml import json import logging try: import tower_cli import tower_cli.exceptions as exc from tower_cli.conf import settings except ImportError: pass # function to match workflow records by name and retrieve the id metadata and convert it to string def getWorkflowIDByName(w, name): for d in w: if d['name'] == name: return str(d['id']) return "" # recursive function to translate any 'unified_job_template' entries with ID references instead of label def replaceUnifiedJobTemplateName(d, w): # Replace 'unified_job_template' names with their corresponding IDs, # the tower-cli API requires it to be this way. if isinstance(d, list): for n in d: replaceUnifiedJobTemplateName(n, w) # dictionary type found if isinstance(d, dict): for k, v in d.items(): # recurive function to be called, if successive nodes are found if isinstance(v, list): replaceUnifiedJobTemplateName(v, w) elif k == "unified_job_template": # retrieve workflow information by ID and update name with ID information d["unified_job_template"] = getWorkflowIDByName(w, d["unified_job_template"]) def main(): argument_spec = dict( name=dict(required=True), description=dict(required=False), extra_vars=dict(required=False), organization=dict(required=False), allow_simultaneous=dict(type='bool', required=False), schema=dict(required=False), survey=dict(required=False), survey_enabled=dict(type='bool', required=False), state=dict(choices=['present', 'absent'], default='present'), ) module = TowerModule( argument_spec=argument_spec, supports_check_mode=False ) logging.basicConfig(filename='/root/load-workflow-templates.log', level=logging.DEBUG) name = module.params.get('name') state = module.params.get('state') schema = None if module.params.get('schema'): schema = module.params.get('schema') if schema and state == 'absent': module.fail_json( msg='Setting schema when state is absent is not allowed', changed=False ) extra_vars = None if module.params.get('extra_vars'): extra_vars = module.params.get('extra_vars') json_output = {'workflow_template': name, 'state': state} tower_auth = tower_auth_config(module) with settings.runtime_values(**tower_auth): tower_check_mode(module) wfjt_res = tower_cli.get_resource('workflow') params = {} params['name'] = name if module.params.get('description'): params['description'] = module.params.get('description') if module.params.get('organization'): organization_res = tower_cli.get_resource('organization') try: organization = organization_res.get( name=module.params.get('organization')) params['organization'] = organization['id'] except exc.NotFound as excinfo: module.fail_json( msg='Failed to update organization source,' 'organization not found: {0}'.format(excinfo), changed=False ) if module.params.get('survey'): params['survey_spec'] = module.params.get('survey') for key in ('allow_simultaneous', 'survey_enabled', 'description'): if module.params.get(key): params[key] = module.params.get(key) # Process extra_vars and convert the json string to python json dict if extra_vars: extra_vars_dict = json.loads(extra_vars) temp = [] for key, value in extra_vars_dict.items(): temp.append(json.dumps({key: value})) params['extra_vars'] = temp try: if state == 'present': params['create_on_missing'] = True result = wfjt_res.modify(**params) json_output['id'] = result['id'] if schema: # convert string to JSON format json_schema_obj = json.loads(schema) # Read all workflows available in the system allWorkflows = wfjt_res.list(all_pages=True) # replace any unified_job_template name references with workflow ID replaceUnifiedJobTemplateName(json_schema_obj, allWorkflows['results']) # Create workflow template schema wfjt_res.schema(result['id'], yaml.safe_dump(json_schema_obj)) elif state == 'absent': params['fail_on_missing'] = False result = wfjt_res.delete(**params) except (exc.ConnectionError, exc.BadRequest) as excinfo: logging.debug("There may be connection error: \n {0}".format(excinfo)) module.fail_json(msg='Failed to update workflow template: \ {0}'.format(excinfo), changed=False) except (exc.TowerCLIError) as excinfo: logging.debug("Exception: \n {0}".format(excinfo)) module.fail_json(msg='Failed to update workflow template: \ {0}'.format(excinfo), changed=False) json_output['changed'] = result['changed'] module.exit_json(**json_output) if __name__ == '__main__': main()