diff --git a/awx_collection/meta/runtime.yml b/awx_collection/meta/runtime.yml index 37cecb9bc5..2fad1211f5 100644 --- a/awx_collection/meta/runtime.yml +++ b/awx_collection/meta/runtime.yml @@ -96,20 +96,10 @@ plugin_routing: redirect: awx.awx.project_update tower_project: redirect: awx.awx.project - tower_receive: - redirect: awx.awx.receive - deprecation: - removal_date: TBD - warning_text: see plugin documentation for details tower_role: redirect: awx.awx.role tower_schedule: redirect: awx.awx.schedule - tower_send: - redirect: awx.awx.send - deprecation: - removal_date: TBD - warning_text: see plugin documentation for details tower_settings: redirect: awx.awx.settings tower_team: @@ -128,8 +118,3 @@ plugin_routing: redirect: awx.awx.workflow_launch tower_workflow_node_wait: redirect: awx.awx.workflow_node_wait - tower_workflow_template: - redirect: awx.awx.workflow_template - deprecation: - removal_date: TBD - warning_text: see plugin documentation for details diff --git a/awx_collection/plugins/modules/receive.py b/awx_collection/plugins/modules/receive.py deleted file mode 100644 index 4463355525..0000000000 --- a/awx_collection/plugins/modules/receive.py +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2017, John Westcott IV -# 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 - - -ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['deprecated'], 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: receive -deprecated: - removed_in: "14.0.0" - why: Deprecated in favor of upcoming C(_export) module. - alternative: Once published, use M(tower_export) instead. -author: "John Westcott IV (@john-westcott-iv)" -short_description: Receive assets from Automation Platform Controller. -description: - - Receive assets from Automation Platform Controller. See - U(https://www.ansible.com/tower) for an overview. -options: - all: - description: - - Export all assets - type: bool - default: 'False' - organization: - description: - - List of organization names to export - default: [] - type: list - elements: str - user: - description: - - List of user names to export - default: [] - type: list - elements: str - team: - description: - - List of team names to export - default: [] - type: list - elements: str - credential_type: - description: - - List of credential type names to export - default: [] - type: list - elements: str - credential: - description: - - List of credential names to export - default: [] - type: list - elements: str - notification_template: - description: - - List of notification template names to export - default: [] - type: list - elements: str - inventory: - description: - - List of inventory names to export - default: [] - type: list - elements: str - project: - description: - - List of project names to export - default: [] - type: list - elements: str - job_template: - description: - - List of job template names to export - default: [] - type: list - elements: str - workflow: - description: - - List of workflow names to export - default: [] - type: list - elements: str - -requirements: - - "ansible-tower-cli >= 3.3.0" - -notes: - - Specifying a name of "all" for any asset type will export all items of that asset type. - -extends_documentation_fragment: awx.awx.auth_legacy -''' - -EXAMPLES = ''' -- name: Export all Automation Platform Controller assets - receive: - all: True - controller_config_file: "~/tower_cli.cfg" - -- name: Export all inventories - receive: - inventory: - - all - -- name: Export a job template named "My Template" and all Credentials - receive: - job_template: - - "My Template" - credential: - - all -''' - -RETURN = ''' -assets: - description: The exported assets - returned: success - type: dict - sample: [ {}, {} ] -''' - -from ..module_utils.tower_legacy import TowerLegacyModule, tower_auth_config, HAS_TOWER_CLI - -try: - from tower_cli.cli.transfer.receive import Receiver - from tower_cli.cli.transfer.common import SEND_ORDER - from tower_cli.utils.exceptions import TowerCLIError - - from tower_cli.conf import settings - - TOWER_CLI_HAS_EXPORT = True -except ImportError: - TOWER_CLI_HAS_EXPORT = False - - -def main(): - argument_spec = dict( - all=dict(type='bool', default=False), - credential=dict(type='list', default=[], elements='str'), - credential_type=dict(type='list', default=[], elements='str'), - inventory=dict(type='list', default=[], elements='str'), - job_template=dict(type='list', default=[], elements='str'), - notification_template=dict(type='list', default=[], elements='str'), - organization=dict(type='list', default=[], elements='str'), - project=dict(type='list', default=[], elements='str'), - team=dict(type='list', default=[], elements='str'), - user=dict(type='list', default=[], elements='str'), - workflow=dict(type='list', default=[], elements='str'), - ) - - module = TowerLegacyModule(argument_spec=argument_spec, supports_check_mode=False) - - module.deprecate(msg="This module is deprecated and will be replaced by the AWX CLI export command.", version="awx.awx:14.0.0") - - if not HAS_TOWER_CLI: - module.fail_json(msg='ansible-tower-cli required for this module') - - if not TOWER_CLI_HAS_EXPORT: - module.fail_json(msg='ansible-tower-cli version does not support export') - - export_all = module.params.get('all') - assets_to_export = {} - for asset_type in SEND_ORDER: - assets_to_export[asset_type] = module.params.get(asset_type) - - result = dict( - assets=None, - changed=False, - message='', - ) - - tower_auth = tower_auth_config(module) - with settings.runtime_values(**tower_auth): - try: - receiver = Receiver() - result['assets'] = receiver.export_assets(all=export_all, asset_input=assets_to_export) - module.exit_json(**result) - except TowerCLIError as e: - result['message'] = e.message - module.fail_json(msg='Receive Failed', **result) - - -if __name__ == '__main__': - main() diff --git a/awx_collection/plugins/modules/send.py b/awx_collection/plugins/modules/send.py deleted file mode 100644 index 7bff90ea64..0000000000 --- a/awx_collection/plugins/modules/send.py +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/python -# coding: utf-8 -*- - -# (c) 2017, John Westcott IV -# 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 - - -ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['deprecated'], 'supported_by': 'community'} - - -DOCUMENTATION = ''' ---- -module: send -deprecated: - removed_in: "14.0.0" - why: Deprecated in favor of upcoming C(_import) module. - alternative: Once published, use M(tower_import) instead. -author: "John Westcott IV (@john-westcott-iv)" -short_description: Send assets to Automation Platform Controller. -description: - - Send assets to Automation Platform Controller. See - U(https://www.ansible.com/tower) for an overview. -options: - assets: - description: - - The assets to import. - - This can be the output of tower_receive or loaded from a file - type: str - files: - description: - - List of files to import. - default: [] - type: list - elements: str - prevent: - description: - - A list of asset types to prevent import for - default: [] - type: list - elements: str - password_management: - description: - - The password management option to use. - - The prompt option is not supported. - default: 'default' - choices: ["default", "random"] - type: str - -notes: - - One of assets or files needs to be passed in - -requirements: - - "ansible-tower-cli >= 3.3.0" - - six.moves.StringIO - - sys - -extends_documentation_fragment: awx.awx.auth_legacy -''' - -EXAMPLES = ''' -- name: Import all Automation Platform Controller assets - send: - assets: "{{ export_output.assets }}" - controller_config_file: "~/tower_cli.cfg" -''' - -RETURN = ''' -output: - description: The import messages - returned: success, fail - type: list - sample: [ 'Message 1', 'Message 2' ] -''' - -import os -import sys - -from ansible.module_utils.six.moves import StringIO -from ..module_utils.tower_legacy import TowerLegacyModule, tower_auth_config, HAS_TOWER_CLI - -from tempfile import mkstemp - -try: - from tower_cli.cli.transfer.send import Sender - from tower_cli.utils.exceptions import TowerCLIError - - from tower_cli.conf import settings - - TOWER_CLI_HAS_EXPORT = True -except ImportError: - TOWER_CLI_HAS_EXPORT = False - - -def main(): - argument_spec = dict( - assets=dict(), - files=dict(default=[], type='list', elements='str'), - prevent=dict(default=[], type='list', elements='str'), - password_management=dict(default='default', choices=['default', 'random']), - ) - - module = TowerLegacyModule(argument_spec=argument_spec, supports_check_mode=False) - - module.deprecate(msg="This module is deprecated and will be replaced by the AWX CLI import command", version="awx.awx:14.0.0") - - if not HAS_TOWER_CLI: - module.fail_json(msg='ansible-tower-cli required for this module') - - if not TOWER_CLI_HAS_EXPORT: - module.fail_json(msg='ansible-tower-cli version does not support export') - - assets = module.params.get('assets') - prevent = module.params.get('prevent') - password_management = module.params.get('password_management') - files = module.params.get('files') - - result = dict( - changed=False, - msg='', - output='', - ) - - if not assets and not files: - result['msg'] = "Assets or files must be specified" - module.fail_json(**result) - - path = None - if assets: - # We got assets so we need to dump this out to a temp file and append that to files - handle, path = mkstemp(prefix='', suffix='', dir='') - with open(path, 'w') as f: - f.write(assets) - files.append(path) - - tower_auth = tower_auth_config(module) - failed = False - with settings.runtime_values(**tower_auth): - try: - sender = Sender(no_color=False) - old_stdout = sys.stdout - sys.stdout = captured_stdout = StringIO() - try: - sender.send(files, prevent, password_management) - except TypeError: - # Newer versions of TowerCLI require 4 parameters - sender.send(files, prevent, [], password_management) - - if sender.error_messages > 0: - failed = True - result['msg'] = "Transfer Failed with %d errors" % sender.error_messages - if sender.changed_messages > 0: - result['changed'] = True - except TowerCLIError as e: - result['msg'] = e.message - failed = True - finally: - if path is not None: - os.remove(path) - result['output'] = captured_stdout.getvalue().split("\n") - sys.stdout = old_stdout - - # Return stdout so that module returns will work - if failed: - module.fail_json(**result) - else: - module.exit_json(**result) - - -if __name__ == '__main__': - main() diff --git a/awx_collection/plugins/modules/workflow_template.py b/awx_collection/plugins/modules/workflow_template.py deleted file mode 100644 index f100ee46f2..0000000000 --- a/awx_collection/plugins/modules/workflow_template.py +++ /dev/null @@ -1,221 +0,0 @@ -#!/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 - - -ANSIBLE_METADATA = {'status': ['deprecated'], 'supported_by': 'community', 'metadata_version': '1.1'} - - -DOCUMENTATION = ''' ---- -module: workflow_template -deprecated: - removed_in: "14.0.0" - why: Deprecated in favor of C(_workflow_job_template) and C(_workflow_job_template_node) modules. - alternative: Use M(tower_workflow_job_template) and M(_workflow_job_template_node) instead. -author: "Adrien Fleury (@fleu42)" -short_description: create, update, or destroy Automation Platform Controller workflow template. -description: - - A tower-cli based module for CRUD actions on workflow job templates. - - Enables use of the old schema functionality. - - Not updated for new features, convert to the modules for - workflow_job_template and workflow_job_template node instead. -options: - allow_simultaneous: - description: - - If enabled, simultaneous runs of this job template will be allowed. - type: bool - ask_extra_vars: - description: - - Prompt user for (extra_vars) on launch. - type: bool - ask_inventory: - description: - - Prompt user for inventory on launch. - type: bool - description: - description: - - The description to use for the workflow. - type: str - extra_vars: - description: - - Extra variables used by Ansible in YAML or key=value format. - type: dict - inventory: - description: - - Name of the inventory to use for the job template. - type: str - name: - description: - - The name to use for the workflow. - required: True - type: str - organization: - description: - - The organization the workflow is linked to. - type: str - schema: - description: - - > - The schema is a JSON- or YAML-formatted string defining the - hierarchy structure that connects the nodes. Refer to the Automation Platform - documentation for more information. - type: list - elements: dict - 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. - type: dict - state: - description: - - Desired state of the resource. - default: "present" - choices: ["present", "absent"] - type: str - -requirements: -- ansible-tower-cli >= 3.0.2 - -extends_documentation_fragment: awx.awx.auth_legacy -''' - - -EXAMPLES = ''' -- workflow_template: - name: Workflow Template - description: My very first Workflow Template - organization: My optional Organization - schema: "{{ lookup('file', 'my_workflow.json') }}" - -- workflow_template: - name: Workflow Template - state: absent -''' - - -RETURN = ''' # ''' - - -from ..module_utils.tower_legacy import TowerLegacyModule, tower_auth_config, tower_check_mode - -import json - -try: - import tower_cli - import tower_cli.exceptions as exc - from tower_cli.conf import settings -except ImportError: - pass - - -def main(): - argument_spec = dict( - name=dict(required=True), - description=dict(), - extra_vars=dict(type='dict'), - organization=dict(), - allow_simultaneous=dict(type='bool'), - schema=dict(type='list', elements='dict'), - survey=dict(type='dict'), - survey_enabled=dict(type='bool'), - inventory=dict(), - ask_inventory=dict(type='bool'), - ask_extra_vars=dict(type='bool'), - state=dict(choices=['present', 'absent'], default='present'), - ) - - module = TowerLegacyModule(argument_spec=argument_spec, supports_check_mode=False) - - module.deprecate( - msg=( - "This module is replaced by the combination of tower_workflow_job_template and " - "tower_workflow_job_template_node. This uses the old tower-cli and wll be " - "removed in 2022." - ), - version='awx.awx:14.0.0', - ) - - 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) - - 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') - - if module.params.get('ask_extra_vars'): - params['ask_variables_on_launch'] = module.params.get('ask_extra_vars') - - if module.params.get('ask_inventory'): - params['ask_inventory_on_launch'] = module.params.get('ask_inventory') - - for key in ('allow_simultaneous', 'inventory', 'survey_enabled', 'description'): - if module.params.get(key): - params[key] = module.params.get(key) - - # Special treatment for tower-cli extra_vars - extra_vars = module.params.get('extra_vars') - if extra_vars: - params['extra_vars'] = [json.dumps(extra_vars)] - - try: - if state == 'present': - params['create_on_missing'] = True - result = wfjt_res.modify(**params) - json_output['id'] = result['id'] - if schema: - wfjt_res.schema(result['id'], json.dumps(schema)) - elif state == 'absent': - params['fail_on_missing'] = False - result = wfjt_res.delete(**params) - except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as 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() diff --git a/awx_collection/test/awx/test_send_receive.py b/awx_collection/test/awx/test_send_receive.py deleted file mode 100644 index 47f79e2733..0000000000 --- a/awx_collection/test/awx/test_send_receive.py +++ /dev/null @@ -1,57 +0,0 @@ -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - -import pytest -import json - -from awx.main.models import Organization, Project, Inventory, Host, CredentialType, Credential, JobTemplate - - -# warns based on password_management param, but not security issue -@pytest.mark.django_db -def test_receive_send_jt(run_module, admin_user, mocker, silence_deprecation): - org = Organization.objects.create(name='SRtest') - proj = Project.objects.create( - name='SRtest', - playbook_files=['debug.yml'], - scm_type='git', - scm_url='https://github.com/ansible/test-playbooks.git', - organization=org, - allow_override=True, # so we do not require playbooks populated - ) - inv = Inventory.objects.create(name='SRtest', organization=org) - Host.objects.create(name='SRtest', inventory=inv) - ct = CredentialType.defaults['ssh']() - ct.save() - cred = Credential.objects.create(name='SRtest', credential_type=ct, organization=org) - jt = JobTemplate.objects.create(name='SRtest', project=proj, inventory=inv, playbook='helloworld.yml') - jt.credentials.add(cred) - jt.admin_role.members.add(admin_user) # work around send/receive bug - - # receive everything - result = run_module('receive', dict(all=True), admin_user) - - assert 'assets' in result, result - assets = result['assets'] - assert not result.get('changed', True) - assert set(a['asset_type'] for a in assets) == set(('organization', 'inventory', 'job_template', 'credential', 'project', 'user')) - - # delete everything - for obj in (jt, inv, proj, cred, org): - obj.delete() - - def fake_wait(self, pk, parent_pk=None, **kwargs): - return {"changed": True} - - # recreate everything - with mocker.patch('sys.stdin.isatty', return_value=True): - with mocker.patch('tower_cli.models.base.MonitorableResource.wait'): - result = run_module('send', dict(assets=json.dumps(assets)), admin_user) - - assert not result.get('failed'), result - - new = JobTemplate.objects.get(name='SRtest') - assert new.project.name == 'SRtest' - assert new.inventory.name == 'SRtest' - assert [cred.name for cred in new.credentials.all()] == ['SRtest'] diff --git a/awx_collection/test/awx/test_workflow_template.py b/awx_collection/test/awx/test_workflow_template.py deleted file mode 100644 index 0776cc420b..0000000000 --- a/awx_collection/test/awx/test_workflow_template.py +++ /dev/null @@ -1,102 +0,0 @@ -from __future__ import absolute_import, division, print_function - -__metaclass__ = type - -import pytest - -from awx.main.models import WorkflowJobTemplate, JobTemplate, Project, InventorySource, Inventory, WorkflowJobTemplateNode - - -@pytest.mark.django_db -def test_create_workflow_job_template(run_module, admin_user, organization, survey_spec, silence_deprecation): - result = run_module( - 'workflow_template', - { - 'name': 'foo-workflow', - 'organization': organization.name, - 'extra_vars': {'foo': 'bar', 'another-foo': {'barz': 'bar2'}}, - 'survey': survey_spec, - 'survey_enabled': True, - 'state': 'present', - }, - admin_user, - ) - - wfjt = WorkflowJobTemplate.objects.get(name='foo-workflow') - assert wfjt.extra_vars == '{"foo": "bar", "another-foo": {"barz": "bar2"}}' - - result.pop('invocation', None) - assert result == {"workflow_template": "foo-workflow", "state": "present", "id": wfjt.id, "changed": True} # TODO: remove after refactor - - assert wfjt.organization_id == organization.id - assert wfjt.survey_spec == survey_spec - - -@pytest.mark.django_db -def test_with_nested_workflow(run_module, admin_user, organization, silence_deprecation): - wfjt1 = WorkflowJobTemplate.objects.create(name='first', organization=organization) - - result = run_module( - 'workflow_template', - {'name': 'foo-workflow', 'organization': organization.name, 'schema': [{'workflow': wfjt1.name}], 'state': 'present'}, - admin_user, - ) - assert not result.get('failed', False), result.get('msg', result) - - wfjt = WorkflowJobTemplate.objects.get(name='foo-workflow') - node = wfjt.workflow_nodes.first() - assert node is not None - assert node.unified_job_template == wfjt1 - - -@pytest.mark.django_db -def test_schema_with_branches(run_module, admin_user, organization, silence_deprecation): - - proj = Project.objects.create(organization=organization, name='Ansible Examples') - inv = Inventory.objects.create(organization=organization, name='test-inv') - jt = JobTemplate.objects.create(project=proj, playbook='helloworld.yml', inventory=inv, name='Hello world') - inv_src = InventorySource.objects.create(inventory=inv, name='AWS servers', source='ec2') - - result = run_module( - 'workflow_template', - { - 'name': 'foo-workflow', - 'organization': organization.name, - 'schema': [ - { - 'job_template': 'Hello world', - 'failure': [{'inventory_source': 'AWS servers', 'success': [{'project': 'Ansible Examples', 'always': [{'job_template': "Hello world"}]}]}], - } - ], - 'state': 'present', - }, - admin_user, - ) - assert not result.get('failed', False), result.get('msg', result) - - wfjt = WorkflowJobTemplate.objects.get(name='foo-workflow') - root_nodes = wfjt.workflow_nodes.filter( - **{ - '%ss_success__isnull' % WorkflowJobTemplateNode.__name__.lower(): True, - '%ss_failure__isnull' % WorkflowJobTemplateNode.__name__.lower(): True, - '%ss_always__isnull' % WorkflowJobTemplateNode.__name__.lower(): True, - } - ) - assert len(root_nodes) == 1 - node = root_nodes[0] - assert node.unified_job_template == jt - second = node.failure_nodes.first() - assert second.unified_job_template == inv_src - third = second.success_nodes.first() - assert third.unified_job_template == proj - fourth = third.always_nodes.first() - assert fourth.unified_job_template == jt - - -@pytest.mark.django_db -def test_with_missing_ujt(run_module, admin_user, organization, silence_deprecation): - result = run_module( - 'workflow_template', {'name': 'foo-workflow', 'organization': organization.name, 'schema': [{'foo': 'bar'}], 'state': 'present'}, admin_user - ) - assert result.get('failed', False), result - assert 'You should provide exactly one of the attributes job_template,' in result['msg']