mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
add copy to modules
This commit is contained in:
parent
74a5247d9d
commit
9a7dd38cbb
@ -410,6 +410,27 @@ class TowerAPIModule(TowerModule):
|
||||
else:
|
||||
self.fail_json(msg="Failed to associate item {0}".format(response['json'].get('detail', response['json'])))
|
||||
|
||||
def copy_item(self, existing_item, name, item_type='unknown'):
|
||||
|
||||
if not existing_item:
|
||||
self.fail_json(msg="Unable to create copy {0} due to missing endpoint".format(item_type))
|
||||
item_url = existing_item['related']['copy']
|
||||
response = self.post_endpoint(item_url, **{'data': {'name': name}})
|
||||
|
||||
if response['status_code'] in [201]:
|
||||
self.json_output['id'] = response['json']['id']
|
||||
self.json_output['changed'] = True
|
||||
item_url = response['json']['url']
|
||||
else:
|
||||
if 'json' in response and '__all__' in response['json']:
|
||||
self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, name, response['json']['__all__'][0]))
|
||||
elif 'json' in response:
|
||||
self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, name, response['json']))
|
||||
else:
|
||||
self.fail_json(msg="Unable to create {0} {1}: {2}".format(item_type, name, response['status_code']))
|
||||
last_data = response['json']
|
||||
return last_data
|
||||
|
||||
def create_if_needed(self, existing_item, new_item, endpoint, on_create=None, auto_exit=True, item_type='unknown', associations=None):
|
||||
|
||||
# This will exit from the module on its own
|
||||
|
||||
@ -32,6 +32,14 @@ options:
|
||||
- Setting this option will change the existing name (looked up via the name field.
|
||||
required: False
|
||||
type: str
|
||||
copy_from:
|
||||
description:
|
||||
- Name or id to copy the credential from.
|
||||
- This will copy an existing credential and change any parameters supplied.
|
||||
- The new credential name will be the one provided in the name parameter.
|
||||
- The organization parameter is not used in this, to facilitate copy from one organization to another.
|
||||
- Provide the id or use the lookup plugin to provide the id if multiple credentials share the same name.
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- The description to use for the credential.
|
||||
@ -274,6 +282,12 @@ EXAMPLES = '''
|
||||
vault_password: 'new_password'
|
||||
vault_id: 'My ID'
|
||||
|
||||
- name: Copy Credential
|
||||
tower_credential:
|
||||
name: Copy password
|
||||
copy_from: Example password
|
||||
credential_type: Vault
|
||||
organization: Foo
|
||||
'''
|
||||
|
||||
from ..module_utils.tower_api import TowerAPIModule
|
||||
@ -318,6 +332,7 @@ def main():
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
new_name=dict(),
|
||||
copy_from=dict(),
|
||||
description=dict(),
|
||||
organization=dict(),
|
||||
credential_type=dict(),
|
||||
@ -356,6 +371,7 @@ def main():
|
||||
# Extract our parameters
|
||||
name = module.params.get('name')
|
||||
new_name = module.params.get('new_name')
|
||||
copy_from = module.params.get('copy_from')
|
||||
description = module.params.get('description')
|
||||
organization = module.params.get('organization')
|
||||
credential_type = module.params.get('credential_type')
|
||||
@ -385,6 +401,28 @@ def main():
|
||||
if organization:
|
||||
lookup_data['organization'] = org_id
|
||||
|
||||
# Attempt to look up credential to copy based on the provided name
|
||||
if copy_from:
|
||||
# Check if credential exists, as API will allow you to create an identical item with the same name in same org, but GUI will not.
|
||||
credential = module.get_one('credentials', name_or_id=name, **{'data': lookup_data})
|
||||
if credential is not None:
|
||||
module.fail_json(msg="A credential with the name {0} already exists.".format(name))
|
||||
else:
|
||||
# Lookup existing credential.
|
||||
copy_lookup_data = {
|
||||
'credential_type': cred_type_id,
|
||||
}
|
||||
copy_from_lookup = module.get_one('credentials', name_or_id=copy_from, **{'data': copy_lookup_data})
|
||||
if copy_from_lookup is None:
|
||||
module.fail_json(msg="A credential with the name {0} was not able to be found.".format(copy_from))
|
||||
else:
|
||||
# Because the initial copy will keep its organization, this can be different then the specified one.
|
||||
lookup_data['organization'] = copy_from_lookup['organization']
|
||||
module.copy_item(
|
||||
copy_from_lookup, name,
|
||||
item_type='credential'
|
||||
)
|
||||
|
||||
credential = module.get_one('credentials', name_or_id=name, **{'data': lookup_data})
|
||||
|
||||
if state == 'absent':
|
||||
|
||||
@ -52,6 +52,18 @@ options:
|
||||
elements: str
|
||||
aliases:
|
||||
- groups
|
||||
preserve_existing_hosts:
|
||||
description:
|
||||
- Provide option (False by default) to preserves existing hosts in an existing group in tower.
|
||||
default: False
|
||||
type: bool
|
||||
preserve_existing_children:
|
||||
description:
|
||||
- Provide option (False by default) to preserves existing children in an existing group in tower.
|
||||
default: False
|
||||
type: bool
|
||||
aliases:
|
||||
- preserve_existing_groups
|
||||
state:
|
||||
description:
|
||||
- Desired state of the resource.
|
||||
@ -74,6 +86,18 @@ EXAMPLES = '''
|
||||
inventory: "Local Inventory"
|
||||
state: present
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Add tower group
|
||||
tower_group:
|
||||
name: Cities
|
||||
description: "Local Host Group"
|
||||
inventory: Default Inventory
|
||||
hosts:
|
||||
- fda
|
||||
children:
|
||||
- NewYork
|
||||
preserve_existing_hosts: True
|
||||
preserve_existing_children: True
|
||||
'''
|
||||
|
||||
from ..module_utils.tower_api import TowerAPIModule
|
||||
@ -90,6 +114,8 @@ def main():
|
||||
variables=dict(type='dict'),
|
||||
hosts=dict(type='list', elements='str'),
|
||||
children=dict(type='list', elements='str', aliases=['groups']),
|
||||
preserve_existing_hosts=dict(type='bool', default=False),
|
||||
preserve_existing_children=dict(type='bool', default=False, aliases=['preserve_existing_groups']),
|
||||
state=dict(choices=['present', 'absent'], default='present'),
|
||||
)
|
||||
|
||||
@ -102,6 +128,8 @@ def main():
|
||||
inventory = module.params.get('inventory')
|
||||
description = module.params.get('description')
|
||||
state = module.params.pop('state')
|
||||
preserve_existing_hosts = module.params.get('preserve_existing_hosts')
|
||||
preserve_existing_children = module.params.get('preserve_existing_groups')
|
||||
variables = module.params.get('variables')
|
||||
|
||||
# Attempt to look up the related items the user specified (these will fail the module if not found)
|
||||
@ -141,6 +169,11 @@ def main():
|
||||
if sub_obj is None:
|
||||
module.fail_json(msg='Could not find {0} with name {1}'.format(resource, sub_name))
|
||||
id_list.append(sub_obj['id'])
|
||||
# Preserve existing objects
|
||||
if (preserve_existing_hosts and relationship == 'hosts') or (preserve_existing_children and relationship == 'children'):
|
||||
preserve_existing_check = module.get_endpoint(group['related'][relationship])
|
||||
for sub_obj in preserve_existing_check['json']['results']:
|
||||
id_list.append(sub_obj['id'])
|
||||
if id_list:
|
||||
association_fields[relationship] = id_list
|
||||
|
||||
|
||||
@ -27,6 +27,14 @@ options:
|
||||
- The name to use for the inventory.
|
||||
required: True
|
||||
type: str
|
||||
copy_from:
|
||||
description:
|
||||
- Name or id to copy the inventory from.
|
||||
- This will copy an existing inventory and change any parameters supplied.
|
||||
- The new inventory name will be the one provided in the name parameter.
|
||||
- The organization parameter is not used in this, to facilitate copy from one organization to another.
|
||||
- Provide the id or use the lookup plugin to provide the id if multiple inventories share the same name.
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- The description to use for the inventory.
|
||||
@ -72,6 +80,14 @@ EXAMPLES = '''
|
||||
organization: "Bar Org"
|
||||
state: present
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Copy tower inventory
|
||||
tower_inventory:
|
||||
name: Copy Foo Inventory
|
||||
copy_from: Default Inventory
|
||||
description: "Our Foo Cloud Servers"
|
||||
organization: Foo
|
||||
state: present
|
||||
'''
|
||||
|
||||
|
||||
@ -83,6 +99,7 @@ def main():
|
||||
# Any additional arguments that are not fields of the item can be added here
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
copy_from=dict(),
|
||||
description=dict(),
|
||||
organization=dict(required=True),
|
||||
variables=dict(type='dict'),
|
||||
@ -97,6 +114,7 @@ def main():
|
||||
|
||||
# Extract our parameters
|
||||
name = module.params.get('name')
|
||||
copy_from = module.params.get('copy_from')
|
||||
description = module.params.get('description')
|
||||
organization = module.params.get('organization')
|
||||
variables = module.params.get('variables')
|
||||
@ -108,6 +126,29 @@ def main():
|
||||
# Attempt to look up the related items the user specified (these will fail the module if not found)
|
||||
org_id = module.resolve_name_to_id('organizations', organization)
|
||||
|
||||
# Attempt to look up inventory to copy based on the provided name
|
||||
if copy_from:
|
||||
# Check if inventory exists, as API will allow you to create an identical item with the same name in same org, but GUI will not.
|
||||
inventory = module.get_one('inventories', name_or_id=name, **{
|
||||
'data': {
|
||||
'organization': org_id
|
||||
}
|
||||
})
|
||||
if inventory is not None:
|
||||
module.fail_json(msg="A inventory with the name {0} already exists.".format(name))
|
||||
else:
|
||||
# Lookup existing inventory.
|
||||
copy_from_lookup = module.get_one('inventories', name_or_id=copy_from)
|
||||
if copy_from_lookup is None:
|
||||
module.fail_json(msg="An inventory with the name {0} was not able to be found.".format(copy_from))
|
||||
else:
|
||||
# Because the initial copy will keep its organization, this can be different then the specified one.
|
||||
org_id = copy_from_lookup['organization']
|
||||
module.copy_item(
|
||||
copy_from_lookup, name,
|
||||
item_type='inventory'
|
||||
)
|
||||
|
||||
# Attempt to look up inventory based on the provided name and org ID
|
||||
inventory = module.get_one('inventories', name_or_id=name, **{
|
||||
'data': {
|
||||
@ -119,6 +160,9 @@ def main():
|
||||
# If the state was absent we can let the module delete it if needed, the module will handle exiting from this
|
||||
module.delete_if_needed(inventory)
|
||||
|
||||
# Reset Org id to push in case copy_from was used.
|
||||
org_id = module.resolve_name_to_id('organizations', organization)
|
||||
|
||||
# Create the data that gets sent for create and update
|
||||
inventory_fields = {
|
||||
'name': module.get_item_name(inventory) if inventory else name,
|
||||
|
||||
@ -31,6 +31,14 @@ options:
|
||||
description:
|
||||
- Setting this option will change the existing name (looed up via the name field.
|
||||
type: str
|
||||
copy_from:
|
||||
description:
|
||||
- Name or id to copy the job template from.
|
||||
- This will copy an existing job template and change any parameters supplied.
|
||||
- The new job template name will be the one provided in the name parameter.
|
||||
- The organization parameter is not used in this, to facilitate copy from one organization to another.
|
||||
- Provide the id or use the lookup plugin to provide the id if multiple job templates share the same name.
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- Description to use for the job template.
|
||||
@ -315,6 +323,15 @@ EXAMPLES = '''
|
||||
notification_templates_started:
|
||||
- Notification2
|
||||
|
||||
- name: Copy Job Template
|
||||
tower_job_template:
|
||||
name: copy job template
|
||||
copy_from: test job template
|
||||
job_type: "run"
|
||||
inventory: Copy Foo Inventory
|
||||
project: test
|
||||
playbook: hello_world.yml
|
||||
state: "present"
|
||||
'''
|
||||
|
||||
from ..module_utils.tower_api import TowerAPIModule
|
||||
@ -340,6 +357,7 @@ def main():
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
new_name=dict(),
|
||||
copy_from=dict(),
|
||||
description=dict(),
|
||||
organization=dict(),
|
||||
job_type=dict(choices=['run', 'check']),
|
||||
@ -393,6 +411,7 @@ def main():
|
||||
# Extract our parameters
|
||||
name = module.params.get('name')
|
||||
new_name = module.params.get("new_name")
|
||||
copy_from = module.params.get('copy_from')
|
||||
state = module.params.get('state')
|
||||
|
||||
# Deal with legacy credential and vault_credential
|
||||
@ -418,6 +437,25 @@ def main():
|
||||
organization_id = module.resolve_name_to_id('organizations', organization)
|
||||
search_fields['organization'] = new_fields['organization'] = organization_id
|
||||
|
||||
# Attempt to look up job template to copy based on the provided name
|
||||
if copy_from:
|
||||
# Check if job template exists, as API will allow you to create an identical item with the same name in same org, but GUI will not.
|
||||
job_template = module.get_one('job_templates', name_or_id=name, **{'data': search_fields})
|
||||
if job_template is not None:
|
||||
module.fail_json(msg="A job template with the name {0} already exists.".format(name))
|
||||
else:
|
||||
# Lookup existing job template.
|
||||
copy_from_lookup = module.get_one('job_templates', name_or_id=copy_from)
|
||||
if copy_from_lookup is None:
|
||||
module.fail_json(msg="A job template with the name {0} was not able to be found.".format(copy_from))
|
||||
else:
|
||||
# Because the initial copy will keep its organization, this can be different then the specified one.
|
||||
search_fields['organization'] = copy_from_lookup['organization']
|
||||
module.copy_item(
|
||||
copy_from_lookup, name,
|
||||
item_type='job_template'
|
||||
)
|
||||
|
||||
# Attempt to look up an existing item based on the provided data
|
||||
existing_item = module.get_one('job_templates', name_or_id=name, **{'data': search_fields})
|
||||
|
||||
|
||||
@ -31,6 +31,14 @@ options:
|
||||
description:
|
||||
- Setting this option will change the existing name (looked up via the name field.
|
||||
type: str
|
||||
copy_from:
|
||||
description:
|
||||
- Name or id to copy the notification from.
|
||||
- This will copy an existing notification and change any parameters supplied.
|
||||
- The new notification name will be the one provided in the name parameter.
|
||||
- The organization parameter is not used in this, to facilitate copy from one organization to another.
|
||||
- Provide the id or use the lookup plugin to provide the id if multiple notifications share the same name.
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- The description of the notification.
|
||||
@ -294,6 +302,12 @@ EXAMPLES = '''
|
||||
name: old notification
|
||||
state: absent
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Copy webhook notification
|
||||
tower_notification_template:
|
||||
name: foo notification
|
||||
copy_from: email notification
|
||||
organization: Foo
|
||||
'''
|
||||
|
||||
|
||||
@ -318,6 +332,7 @@ def main():
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
new_name=dict(),
|
||||
copy_from=dict(),
|
||||
description=dict(),
|
||||
organization=dict(),
|
||||
notification_type=dict(choices=[
|
||||
@ -360,6 +375,7 @@ def main():
|
||||
# Extract our parameters
|
||||
name = module.params.get('name')
|
||||
new_name = module.params.get('new_name')
|
||||
copy_from = module.params.get('copy_from')
|
||||
description = module.params.get('description')
|
||||
organization = module.params.get('organization')
|
||||
notification_type = module.params.get('notification_type')
|
||||
@ -379,6 +395,29 @@ def main():
|
||||
if organization:
|
||||
organization_id = module.resolve_name_to_id('organizations', organization)
|
||||
|
||||
# Attempt to look up notification template to copy based on the provided name
|
||||
if copy_from:
|
||||
# Check if notification template exists, as API will allow you to create an identical item with the same name in same org, but GUI will not.
|
||||
notification_template = module.get_one('notification_templates', name_or_id=name, **{
|
||||
'data': {
|
||||
'organization': organization_id
|
||||
}
|
||||
})
|
||||
if notification_template is not None:
|
||||
module.fail_json(msg="A notification template with the name {0} already exists.".format(name))
|
||||
else:
|
||||
# Lookup existing notification template.
|
||||
copy_from_lookup = module.get_one('notification_templates', name_or_id=copy_from)
|
||||
if copy_from_lookup is None:
|
||||
module.fail_json(msg="An notification template with the name {0} was not able to be found.".format(copy_from))
|
||||
else:
|
||||
# Because the initial copy will keep its organization, this can be different then the specified one.
|
||||
organization_id = copy_from_lookup['organization']
|
||||
module.copy_item(
|
||||
copy_from_lookup, name,
|
||||
item_type='notification_template'
|
||||
)
|
||||
|
||||
# Attempt to look up an existing item based on the provided data
|
||||
existing_item = module.get_one('notification_templates', name_or_id=name, **{
|
||||
'data': {
|
||||
@ -386,6 +425,10 @@ def main():
|
||||
}
|
||||
})
|
||||
|
||||
# Reset Org id to push in case copy_from was used.
|
||||
if organization:
|
||||
organization_id = module.resolve_name_to_id('organizations', organization)
|
||||
|
||||
if state == 'absent':
|
||||
# If the state was absent we can let the module delete it if needed, the module will handle exiting from this
|
||||
module.delete_if_needed(existing_item)
|
||||
|
||||
@ -27,6 +27,14 @@ options:
|
||||
- Name to use for the project.
|
||||
required: True
|
||||
type: str
|
||||
copy_from:
|
||||
description:
|
||||
- Name or id to copy the project from.
|
||||
- This will copy an existing project and change any parameters supplied.
|
||||
- The new project name will be the one provided in the name parameter.
|
||||
- The organization parameter is not used in this, to facilitate copy from one organization to another.
|
||||
- Provide the id or use the lookup plugin to provide the id if multiple projects share the same name.
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- Description to use for the project.
|
||||
@ -171,6 +179,14 @@ EXAMPLES = '''
|
||||
custom_virtualenv: "/var/lib/awx/var/lib/awx/venv/ansible-2.2"
|
||||
state: present
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Copy tower project
|
||||
tower_project:
|
||||
name: copy
|
||||
copy_from: test
|
||||
description: Foo copy project
|
||||
organization: Foo
|
||||
state: present
|
||||
'''
|
||||
|
||||
import time
|
||||
@ -225,6 +241,7 @@ def main():
|
||||
# Any additional arguments that are not fields of the item can be added here
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
copy_from=dict(),
|
||||
description=dict(),
|
||||
scm_type=dict(choices=['manual', 'git', 'svn', 'insights'], default='manual'),
|
||||
scm_url=dict(),
|
||||
@ -254,22 +271,14 @@ def main():
|
||||
|
||||
# Extract our parameters
|
||||
name = module.params.get('name')
|
||||
description = module.params.get('description')
|
||||
copy_from = module.params.get('copy_from')
|
||||
scm_type = module.params.get('scm_type')
|
||||
if scm_type == "manual":
|
||||
scm_type = ""
|
||||
scm_url = module.params.get('scm_url')
|
||||
local_path = module.params.get('local_path')
|
||||
scm_branch = module.params.get('scm_branch')
|
||||
scm_refspec = module.params.get('scm_refspec')
|
||||
credential = module.params.get('credential')
|
||||
scm_clean = module.params.get('scm_clean')
|
||||
scm_delete_on_update = module.params.get('scm_delete_on_update')
|
||||
scm_update_on_launch = module.params.get('scm_update_on_launch')
|
||||
scm_update_cache_timeout = module.params.get('scm_update_cache_timeout')
|
||||
allow_override = module.params.get('allow_override')
|
||||
timeout = module.params.get('timeout')
|
||||
custom_virtualenv = module.params.get('custom_virtualenv')
|
||||
organization = module.params.get('organization')
|
||||
state = module.params.get('state')
|
||||
wait = module.params.get('wait')
|
||||
@ -283,6 +292,25 @@ def main():
|
||||
org_id = module.resolve_name_to_id('organizations', organization)
|
||||
lookup_data['organization'] = org_id
|
||||
|
||||
# Attempt to look up project to copy based on the provided name
|
||||
if copy_from:
|
||||
# Check if project exists, as API will allow you to create an identical item with the same name in same org, but GUI will not.
|
||||
project = module.get_one('projects', name_or_id=name, data=lookup_data)
|
||||
if project is not None:
|
||||
module.fail_json(msg="A project with the name {0} already exists.".format(name))
|
||||
else:
|
||||
# Lookup existing project.
|
||||
copy_from_lookup = module.get_one('projects', name_or_id=copy_from)
|
||||
if copy_from_lookup is None:
|
||||
module.fail_json(msg="A project with the name {0} was not able to be found.".format(copy_from))
|
||||
else:
|
||||
# Because the initial copy will keep its organization, this can be different then the specified one.
|
||||
lookup_data['organization'] = copy_from_lookup['organization']
|
||||
module.copy_item(
|
||||
copy_from_lookup, name,
|
||||
item_type='project'
|
||||
)
|
||||
|
||||
# Attempt to look up project based on the provided name and org ID
|
||||
project = module.get_one('projects', name_or_id=name, data=lookup_data)
|
||||
|
||||
@ -318,25 +346,23 @@ def main():
|
||||
project_fields = {
|
||||
'name': module.get_item_name(project) if project else name,
|
||||
'scm_type': scm_type,
|
||||
'scm_url': scm_url,
|
||||
'scm_branch': scm_branch,
|
||||
'scm_refspec': scm_refspec,
|
||||
'scm_clean': scm_clean,
|
||||
'scm_delete_on_update': scm_delete_on_update,
|
||||
'timeout': timeout,
|
||||
'organization': org_id,
|
||||
'scm_update_on_launch': scm_update_on_launch,
|
||||
'scm_update_cache_timeout': scm_update_cache_timeout,
|
||||
'custom_virtualenv': custom_virtualenv,
|
||||
}
|
||||
if description is not None:
|
||||
project_fields['description'] = description
|
||||
|
||||
for field_name in (
|
||||
'scm_url', 'scm_branch', 'scm_refspec', 'scm_clean', 'scm_delete_on_update',
|
||||
'timeout', 'scm_update_cache_timeout', 'custom_virtualenv',
|
||||
'description', 'allow_override',
|
||||
):
|
||||
field_val = module.params.get(field_name)
|
||||
if field_val is not None:
|
||||
project_fields[field_name] = field_val
|
||||
|
||||
if credential is not None:
|
||||
project_fields['credential'] = credential
|
||||
if allow_override is not None:
|
||||
project_fields['allow_override'] = allow_override
|
||||
if scm_type == '':
|
||||
project_fields['local_path'] = local_path
|
||||
if local_path is not None:
|
||||
project_fields['local_path'] = local_path
|
||||
|
||||
if scm_update_cache_timeout != 0 and scm_update_on_launch is not True:
|
||||
module.warn('scm_update_cache_timeout will be ignored since scm_update_on_launch was not set to true')
|
||||
|
||||
@ -32,6 +32,14 @@ options:
|
||||
description:
|
||||
- Setting this option will change the existing name.
|
||||
type: str
|
||||
copy_from:
|
||||
description:
|
||||
- Name or id to copy the workflow job template from.
|
||||
- This will copy an existing workflow job template and change any parameters supplied.
|
||||
- The new workflow job template name will be the one provided in the name parameter.
|
||||
- The organization parameter is not used in this, to facilitate copy from one organization to another.
|
||||
- Provide the id or use the lookup plugin to provide the id if multiple workflow job templates share the same name.
|
||||
type: str
|
||||
description:
|
||||
description:
|
||||
- Optional description of this workflow job template.
|
||||
@ -142,6 +150,12 @@ EXAMPLES = '''
|
||||
name: example-workflow
|
||||
description: created by Ansible Playbook
|
||||
organization: Default
|
||||
|
||||
- name: Copy a workflow job template
|
||||
tower_workflow_job_template:
|
||||
name: copy-workflow
|
||||
copy_from: example-workflow
|
||||
organization: Foo
|
||||
'''
|
||||
|
||||
from ..module_utils.tower_api import TowerAPIModule
|
||||
@ -168,6 +182,7 @@ def main():
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
new_name=dict(),
|
||||
copy_from=dict(),
|
||||
description=dict(),
|
||||
extra_vars=dict(type='dict'),
|
||||
organization=dict(),
|
||||
@ -197,6 +212,7 @@ def main():
|
||||
# Extract our parameters
|
||||
name = module.params.get('name')
|
||||
new_name = module.params.get("new_name")
|
||||
copy_from = module.params.get('copy_from')
|
||||
state = module.params.get('state')
|
||||
|
||||
new_fields = {}
|
||||
@ -208,6 +224,34 @@ def main():
|
||||
organization_id = module.resolve_name_to_id('organizations', organization)
|
||||
search_fields['organization'] = new_fields['organization'] = organization_id
|
||||
|
||||
# Attempt to look up workflow job template to copy based on the provided name
|
||||
if copy_from:
|
||||
# Check if workflow job template exists, as API will allow you to create an identical item with the same name in same org, but GUI will not.
|
||||
workflow_job_template = module.get_one('workflow_job_templates', name_or_id=name, data=search_fields)
|
||||
if workflow_job_template is not None:
|
||||
module.fail_json(msg="A workflow job template with the name {0} already exists.".format(name))
|
||||
else:
|
||||
# Lookup existing workflow job template.
|
||||
copy_from_lookup = module.get_one('workflow_job_templates', name_or_id=copy_from)
|
||||
if copy_from_lookup is None:
|
||||
module.fail_json(msg="A workflow job template with the name {0} was not able to be found.".format(copy_from))
|
||||
else:
|
||||
workflow_copy_get_check = module.get_endpoint(copy_from_lookup['related']['copy'])
|
||||
if workflow_copy_get_check['status_code'] in [200]:
|
||||
if (workflow_copy_get_check['json']['can_copy'] and workflow_copy_get_check['json']['can_copy_without_user_input'] and
|
||||
not workflow_copy_get_check['json']['templates_unable_to_copy'] and not workflow_copy_get_check['json']['credentials_unable_to_copy']
|
||||
and not workflow_copy_get_check['json']['inventories_unable_to_copy']):
|
||||
# Because the initial copy will keep its organization, this can be different then the specified one.
|
||||
search_fields['organization'] = copy_from_lookup['organization']
|
||||
module.copy_item(
|
||||
copy_from_lookup, name,
|
||||
item_type='workflow_job_template'
|
||||
)
|
||||
else:
|
||||
module.fail_json(msg="Unable to copy workflow {0} error: {1}".format(copy_from, workflow_copy_get_check))
|
||||
else:
|
||||
module.fail_json(msg="Error accessing workflow {0} error: {1} ".format(copy_from, workflow_copy_get_check))
|
||||
|
||||
# Attempt to look up an existing item based on the provided data
|
||||
existing_item = module.get_one('workflow_job_templates', name_or_id=name, **{'data': search_fields})
|
||||
|
||||
|
||||
@ -203,6 +203,29 @@
|
||||
that:
|
||||
- result is not changed
|
||||
|
||||
- name: Copy ssh Credential
|
||||
tower_credential:
|
||||
name: "copy_{{ ssh_cred_name2 }}"
|
||||
copy_from: "{{ ssh_cred_name2 }}"
|
||||
credential_type: Machine
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: Delete an SSH credential
|
||||
tower_credential:
|
||||
name: "copy_{{ ssh_cred_name2 }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
credential_type: Machine
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Create a valid SSH credential from lookup source (old school)
|
||||
tower_credential:
|
||||
name: "{{ ssh_cred_name3 }}"
|
||||
@ -369,7 +392,7 @@
|
||||
- result is failed
|
||||
- "'Unable to create credential {{ vault_cred_name2 }}' in result.msg"
|
||||
- "'Additional properties are not allowed' in result.msg"
|
||||
- "'\\'vault_password\\' was unexpected' in result.msg"
|
||||
- "'\\'vault_********\\' was unexpected' in result.msg"
|
||||
|
||||
- name: Delete a Vault credential
|
||||
tower_credential:
|
||||
|
||||
@ -29,9 +29,79 @@
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Create a Group
|
||||
tower_group:
|
||||
name: "{{ group_name2 }}"
|
||||
inventory: "{{ inv_name }}"
|
||||
state: present
|
||||
variables:
|
||||
foo: bar
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Create a Group
|
||||
tower_group:
|
||||
name: "{{ group_name3 }}"
|
||||
inventory: "{{ inv_name }}"
|
||||
state: present
|
||||
variables:
|
||||
foo: bar
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: add hosts
|
||||
tower_host:
|
||||
name: "{{ item }}"
|
||||
inventory: "{{ inv_name }}"
|
||||
loop:
|
||||
- "{{ host_name1 }}"
|
||||
- "{{ host_name2 }}"
|
||||
- "{{ host_name3 }}"
|
||||
|
||||
- name: Create a Group with hosts and sub group
|
||||
tower_group:
|
||||
name: "{{ group_name1 }}"
|
||||
inventory: "{{ inv_name }}"
|
||||
hosts:
|
||||
- "{{ host_name1 }}"
|
||||
- "{{ host_name2 }}"
|
||||
children:
|
||||
- "{{ group_name2 }}"
|
||||
state: present
|
||||
variables:
|
||||
foo: bar
|
||||
register: result
|
||||
|
||||
- name: Create a Group with hosts and sub group
|
||||
tower_group:
|
||||
name: "{{ group_name1 }}"
|
||||
inventory: "{{ inv_name }}"
|
||||
hosts:
|
||||
- "{{ host_name3 }}"
|
||||
children:
|
||||
- "{{ group_name3 }}"
|
||||
state: present
|
||||
preserve_existing_hosts: True
|
||||
preserve_existing_children: True
|
||||
register: result
|
||||
|
||||
- name: "Find number of hosts in {{ group_name1 }}"
|
||||
set_fact:
|
||||
group1_host_count: "{{ lookup('awx.awx.tower_api', 'groups/{{result.id}}/all_hosts/') |length}}"
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- group1_host_count == "3"
|
||||
|
||||
- name: Delete a Group
|
||||
tower_group:
|
||||
name: "{{ result.id }}"
|
||||
name: "{{ group_name1 }}"
|
||||
inventory: "{{ inv_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
@ -40,6 +110,28 @@
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Delete a Group
|
||||
tower_group:
|
||||
name: "{{ group_name2 }}"
|
||||
inventory: "{{ inv_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Delete a Group
|
||||
tower_group:
|
||||
name: "{{ group_name3 }}"
|
||||
inventory: "{{ inv_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is not changed"
|
||||
|
||||
- name: Check module fails with correct msg
|
||||
tower_group:
|
||||
name: test-group
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Test Inventory module idempotency
|
||||
tower_inventory:
|
||||
name: "{{ result.id }}"
|
||||
@ -48,6 +47,30 @@
|
||||
- assert:
|
||||
that:
|
||||
- "result is not changed"
|
||||
|
||||
- name: Copy an inventory
|
||||
tower_inventory:
|
||||
name: "copy_{{ inv_name1 }}"
|
||||
copy_from: "{{ inv_name1 }}"
|
||||
organization: Default
|
||||
description: "Our Foo Cloud Servers"
|
||||
state: present
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Delete an Inventory
|
||||
tower_inventory:
|
||||
name: "copy_{{ inv_name1 }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Fail Change Regular to Smart
|
||||
tower_inventory:
|
||||
@ -133,6 +156,7 @@
|
||||
loop:
|
||||
- "{{ inv_name1 }}"
|
||||
- "{{ inv_name2 }}"
|
||||
- "copy_{{ inv_name1 }}"
|
||||
|
||||
- name: Delete Insights Credential
|
||||
tower_credential:
|
||||
|
||||
@ -155,6 +155,19 @@
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Copy Job Template
|
||||
tower_job_template:
|
||||
name: "copy_{{ jt1 }}"
|
||||
copy_from: "{{ jt1 }}"
|
||||
state: "present"
|
||||
|
||||
- name: Delete copied Job Template
|
||||
tower_job_template:
|
||||
name: "copy_{{ jt1 }}"
|
||||
job_type: run
|
||||
state: absent
|
||||
register: result
|
||||
|
||||
# This doesnt work if you include the credentials parameter
|
||||
- name: Delete Job Template 1
|
||||
tower_job_template:
|
||||
|
||||
@ -133,6 +133,28 @@
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: Copy email notification
|
||||
tower_notification_template:
|
||||
name: "copy_{{ email_not }}"
|
||||
copy_from: "{{ email_not }}"
|
||||
organization: Default
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: Delete copied email notification
|
||||
tower_notification_template:
|
||||
name: "copy_{{ email_not }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- result is changed
|
||||
|
||||
- name: Delete email notification
|
||||
tower_notification_template:
|
||||
name: "{{ email_not }}"
|
||||
|
||||
@ -75,13 +75,14 @@
|
||||
scm_credential: "{{ cred_name }}"
|
||||
check_mode: true
|
||||
|
||||
- name: Create a new test project
|
||||
- name: "Copy tower project from {{ project_name1 }}"
|
||||
tower_project:
|
||||
name: "{{ project_name2 }}"
|
||||
copy_from: "{{ project_name1 }}"
|
||||
organization: "{{ org_name }}"
|
||||
scm_type: git
|
||||
scm_url: https://github.com/ansible/test-playbooks
|
||||
scm_credential: "{{ cred_name }}"
|
||||
state: present
|
||||
register: result
|
||||
|
||||
# If this fails it may be because the check_mode task actually already created
|
||||
|
||||
@ -244,6 +244,52 @@
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Copy a workflow job template
|
||||
tower_workflow_job_template:
|
||||
name: "copy_{{ wfjt_name }}"
|
||||
copy_from: "{{ wfjt_name }}"
|
||||
organization: Default
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Fail Remove "on start" webhook notification from copied workflow job template
|
||||
tower_workflow_job_template:
|
||||
name: "copy_{{ wfjt_name }}"
|
||||
notification_templates_started:
|
||||
- "{{ email_not }}123"
|
||||
register: remove_copied_workflow_node
|
||||
ignore_errors: true
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "remove_copied_workflow_node is failed"
|
||||
- "remove_copied_workflow_node is not changed"
|
||||
- "'returned 0 items' in remove_copied_workflow_node.msg"
|
||||
|
||||
- name: Remove "on start" webhook notification from copied workflow job template
|
||||
tower_workflow_job_template:
|
||||
name: "copy_{{ wfjt_name }}"
|
||||
notification_templates_started:
|
||||
- "{{ email_not }}"
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Delete copied workflow job template
|
||||
tower_workflow_job_template:
|
||||
name: "copy_{{ wfjt_name }}"
|
||||
state: absent
|
||||
register: result
|
||||
|
||||
- assert:
|
||||
that:
|
||||
- "result is changed"
|
||||
|
||||
- name: Remove "on start" webhook notification from workflow job template
|
||||
tower_workflow_job_template:
|
||||
name: "{{ wfjt_name }}"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user