Migrated to awx.awx

pull/68298/head
Ansible Core Team 5 years ago committed by Matt Martz
parent 35063de590
commit 02541a15b2

@ -1,113 +0,0 @@
# This code is part of Ansible, but is an independent component.
# This particular file snippet, and this file snippet only, is BSD licensed.
# Modules you write using this snippet, which is embedded dynamically by Ansible
# still belong to the author of the module, and may assign their own license
# to the complete work.
#
# Copyright (c), Wayne Witzel III <wayne@riotousliving.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os
import traceback
TOWER_CLI_IMP_ERR = None
try:
import tower_cli.utils.exceptions as exc
from tower_cli.utils import parser
from tower_cli.api import client
HAS_TOWER_CLI = True
except ImportError:
TOWER_CLI_IMP_ERR = traceback.format_exc()
HAS_TOWER_CLI = False
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
def tower_auth_config(module):
'''tower_auth_config attempts to load the tower-cli.cfg file
specified from the `tower_config_file` parameter. If found,
if returns the contents of the file as a dictionary, else
it will attempt to fetch values from the module params and
only pass those values that have been set.
'''
config_file = module.params.pop('tower_config_file', None)
if config_file:
if not os.path.exists(config_file):
module.fail_json(msg='file not found: %s' % config_file)
if os.path.isdir(config_file):
module.fail_json(msg='directory can not be used as config file: %s' % config_file)
with open(config_file, 'rb') as f:
return parser.string_to_dict(f.read())
else:
auth_config = {}
host = module.params.pop('tower_host', None)
if host:
auth_config['host'] = host
username = module.params.pop('tower_username', None)
if username:
auth_config['username'] = username
password = module.params.pop('tower_password', None)
if password:
auth_config['password'] = password
module.params.pop('tower_verify_ssl', None) # pop alias if used
verify_ssl = module.params.pop('validate_certs', None)
if verify_ssl is not None:
auth_config['verify_ssl'] = verify_ssl
return auth_config
def tower_check_mode(module):
'''Execute check mode logic for Ansible Tower modules'''
if module.check_mode:
try:
result = client.get('/ping').json()
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))
class TowerModule(AnsibleModule):
def __init__(self, argument_spec, **kwargs):
args = dict(
tower_host=dict(),
tower_username=dict(),
tower_password=dict(no_log=True),
validate_certs=dict(type='bool', aliases=['tower_verify_ssl']),
tower_config_file=dict(type='path'),
)
args.update(argument_spec)
mutually_exclusive = kwargs.get('mutually_exclusive', [])
kwargs['mutually_exclusive'] = mutually_exclusive.extend((
('tower_config_file', 'tower_host'),
('tower_config_file', 'tower_username'),
('tower_config_file', 'tower_password'),
('tower_config_file', 'validate_certs'),
))
super(TowerModule, self).__init__(argument_spec=args, **kwargs)
if not HAS_TOWER_CLI:
self.fail_json(msg=missing_required_lib('ansible-tower-cli'),
exception=TOWER_CLI_IMP_ERR)

@ -1,362 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# Copyright: (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_credential
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: create, update, or destroy Ansible Tower credential.
description:
- Create, update, or destroy Ansible Tower credentials. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- The name to use for the credential.
required: True
type: str
description:
description:
- The description to use for the credential.
type: str
user:
description:
- User that should own this credential.
type: str
team:
description:
- Team that should own this credential.
type: str
project:
description:
- Project that should for this credential.
type: str
organization:
description:
- Organization that should own the credential.
required: True
type: str
kind:
description:
- Type of credential being added.
- The ssh choice refers to a Tower Machine credential.
required: True
type: str
choices: ["ssh", "vault", "net", "scm", "aws", "vmware", "satellite6", "cloudforms", "gce", "azure_rm", "openstack", "rhv", "insights", "tower"]
host:
description:
- Host for this credential.
type: str
username:
description:
- Username for this credential. ``access_key`` for AWS.
type: str
password:
description:
- Password for this credential. ``secret_key`` for AWS. ``api_key`` for RAX.
- Use "ASK" and launch in Tower to be prompted.
type: str
ssh_key_data:
description:
- SSH private key content. To extract the content from a file path, use the lookup function (see examples).
required: False
type: str
ssh_key_unlock:
description:
- Unlock password for ssh_key.
- Use "ASK" and launch in Tower to be prompted.
type: str
authorize:
description:
- Should use authorize for net type.
type: bool
default: 'no'
authorize_password:
description:
- Password for net credentials that require authorize.
type: str
client:
description:
- Client or application ID for azure_rm type.
type: str
security_token:
description:
- STS token for aws type.
version_added: "2.6"
type: str
secret:
description:
- Secret token for azure_rm type.
type: str
subscription:
description:
- Subscription ID for azure_rm type.
type: str
tenant:
description:
- Tenant ID for azure_rm type.
type: str
domain:
description:
- Domain for openstack type.
type: str
become_method:
description:
- Become method to use for privilege escalation.
choices: ["None", "sudo", "su", "pbrun", "pfexec", "pmrun"]
type: str
become_username:
description:
- Become username.
- Use "ASK" and launch in Tower to be prompted.
type: str
become_password:
description:
- Become password.
- Use "ASK" and launch in Tower to be prompted.
type: str
vault_password:
description:
- Vault password.
- Use "ASK" and launch in Tower to be prompted.
type: str
vault_id:
description:
- Vault identifier.
- This parameter is only valid if C(kind) is specified as C(vault).
type: str
version_added: "2.8"
state:
description:
- Desired state of the resource.
choices: ["present", "absent"]
default: "present"
type: str
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add tower credential
tower_credential:
name: Team Name
description: Team Description
organization: test-org
kind: ssh
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Create a valid SCM credential from a private_key file
tower_credential:
name: SCM Credential
organization: Default
state: present
kind: scm
username: joe
password: secret
ssh_key_data: "{{ lookup('file', '/tmp/id_rsa') }}"
ssh_key_unlock: "passphrase"
- name: Fetch private key
slurp:
src: '$HOME/.ssh/aws-private.pem'
register: aws_ssh_key
- name: Add Credential Into Tower
tower_credential:
name: Workshop Credential
ssh_key_data: "{{ aws_ssh_key['content'] | b64decode }}"
kind: ssh
organization: Default
tower_username: admin
tower_password: ansible
tower_host: https://localhost
run_once: true
delegate_to: localhost
'''
import os
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
KIND_CHOICES = {
'ssh': 'Machine',
'vault': 'Ansible Vault',
'net': 'Network',
'scm': 'Source Control',
'aws': 'Amazon Web Services',
'vmware': 'VMware vCenter',
'satellite6': 'Red Hat Satellite 6',
'cloudforms': 'Red Hat CloudForms',
'gce': 'Google Compute Engine',
'azure_rm': 'Microsoft Azure Resource Manager',
'openstack': 'OpenStack',
'rhv': 'Red Hat Virtualization',
'insights': 'Insights',
'tower': 'Ansible Tower',
}
def credential_type_for_v1_kind(params, module):
credential_type_res = tower_cli.get_resource('credential_type')
kind = params.pop('kind')
arguments = {'managed_by_tower': True}
if kind == 'ssh':
if params.get('vault_password'):
arguments['kind'] = 'vault'
else:
arguments['kind'] = 'ssh'
elif kind in ('net', 'scm', 'insights', 'vault'):
arguments['kind'] = kind
elif kind in KIND_CHOICES:
arguments.update(dict(
kind='cloud',
name=KIND_CHOICES[kind]
))
return credential_type_res.get(**arguments)
def main():
argument_spec = dict(
name=dict(required=True),
user=dict(),
team=dict(),
kind=dict(required=True,
choices=KIND_CHOICES.keys()),
host=dict(),
username=dict(),
password=dict(no_log=True),
ssh_key_data=dict(no_log=True, type='str'),
ssh_key_unlock=dict(no_log=True),
authorize=dict(type='bool', default=False),
authorize_password=dict(no_log=True),
client=dict(),
security_token=dict(),
secret=dict(),
tenant=dict(),
subscription=dict(),
domain=dict(),
become_method=dict(),
become_username=dict(),
become_password=dict(no_log=True),
vault_password=dict(no_log=True),
description=dict(),
organization=dict(required=True),
project=dict(),
state=dict(choices=['present', 'absent'], default='present'),
vault_id=dict(),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
organization = module.params.get('organization')
state = module.params.get('state')
json_output = {'credential': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
credential = tower_cli.get_resource('credential')
try:
params = {}
params['create_on_missing'] = True
params['name'] = name
if organization:
org_res = tower_cli.get_resource('organization')
org = org_res.get(name=organization)
params['organization'] = org['id']
try:
tower_cli.get_resource('credential_type')
except (ImportError, AttributeError):
# /api/v1/ backwards compat
# older versions of tower-cli don't *have* a credential_type
# resource
params['kind'] = module.params['kind']
else:
credential_type = credential_type_for_v1_kind(module.params, module)
params['credential_type'] = credential_type['id']
if module.params.get('description'):
params['description'] = module.params.get('description')
if module.params.get('user'):
user_res = tower_cli.get_resource('user')
user = user_res.get(username=module.params.get('user'))
params['user'] = user['id']
if module.params.get('team'):
team_res = tower_cli.get_resource('team')
team = team_res.get(name=module.params.get('team'))
params['team'] = team['id']
if module.params.get('ssh_key_data'):
data = module.params.get('ssh_key_data')
if os.path.exists(data):
module.deprecate(
msg='ssh_key_data should be a string, not a path to a file.',
version="2.12"
)
if os.path.isdir(data):
module.fail_json(msg='attempted to read contents of directory: %s' % data)
with open(data, 'rb') as f:
module.params['ssh_key_data'] = to_text(f.read())
else:
module.params['ssh_key_data'] = data
if module.params.get('vault_id', None) and module.params.get('kind') != 'vault':
module.fail_json(msg="Parameter 'vault_id' is only valid if parameter 'kind' is specified as 'vault'")
for key in ('authorize', 'authorize_password', 'client',
'security_token', 'secret', 'tenant', 'subscription',
'domain', 'become_method', 'become_username',
'become_password', 'vault_password', 'project', 'host',
'username', 'password', 'ssh_key_data', 'vault_id',
'ssh_key_unlock'):
if 'kind' in params:
params[key] = module.params.get(key)
elif module.params.get(key):
params.setdefault('inputs', {})[key] = module.params.get(key)
if state == 'present':
result = credential.modify(**params)
json_output['id'] = result['id']
elif state == 'absent':
result = credential.delete(**params)
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update credential, organization not found: {0}'.format(excinfo), changed=False)
except (exc.ConnectionError, exc.BadRequest, exc.NotFound, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update credential: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,174 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
#
# (c) 2018, Adrien Fleury <fleu42@gmail.com>
# 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': ['preview'],
'supported_by': 'community',
'metadata_version': '1.1'}
DOCUMENTATION = '''
---
module: tower_credential_type
author: "Adrien Fleury (@fleu42)"
version_added: "2.7"
short_description: Create, update, or destroy custom Ansible Tower credential type.
description:
- Create, update, or destroy Ansible Tower credential type. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- The name of the credential type.
required: True
description:
description:
- The description of the credential type to give more detail about it.
required: False
kind:
description:
- >-
The type of credential type being added. Note that only cloud and
net can be used for creating credential types. Refer to the Ansible
for more information.
choices: [ 'ssh', 'vault', 'net', 'scm', 'cloud', 'insights' ]
required: False
inputs:
description:
- >-
Enter inputs using either JSON or YAML syntax. Refer to the Ansible
Tower documentation for example syntax.
required: False
injectors:
description:
- >-
Enter injectors using either JSON or YAML syntax. Refer to the
Ansible Tower documentation for example syntax.
required: False
state:
description:
- Desired state of the resource.
required: False
default: "present"
choices: ["present", "absent"]
validate_certs:
description:
- Tower option to avoid certificates check.
required: False
type: bool
aliases: [ tower_verify_ssl ]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- tower_credential_type:
name: Nexus
description: Credentials type for Nexus
kind: cloud
inputs: "{{ lookup('file', 'tower_credential_inputs_nexus.json') }}"
injectors: {'extra_vars': {'nexus_credential': 'test' }}
state: present
validate_certs: false
- tower_credential_type:
name: Nexus
state: absent
'''
RETURN = ''' # '''
from ansible.module_utils.ansible_tower import (
TowerModule,
tower_auth_config,
tower_check_mode
)
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
KIND_CHOICES = {
'ssh': 'Machine',
'vault': 'Ansible Vault',
'net': 'Network',
'scm': 'Source Control',
'cloud': 'Lots of others',
'insights': 'Insights'
}
def main():
argument_spec = dict(
name=dict(required=True),
description=dict(required=False),
kind=dict(required=False, choices=KIND_CHOICES.keys()),
inputs=dict(type='dict', required=False),
injectors=dict(type='dict', required=False),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(
argument_spec=argument_spec,
supports_check_mode=False
)
name = module.params.get('name')
kind = module.params.get('kind')
state = module.params.get('state')
json_output = {'credential_type': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
credential_type_res = tower_cli.get_resource('credential_type')
params = {}
params['name'] = name
params['kind'] = kind
params['managed_by_tower'] = False
if module.params.get('description'):
params['description'] = module.params.get('description')
if module.params.get('inputs'):
params['inputs'] = module.params.get('inputs')
if module.params.get('injectors'):
params['injectors'] = module.params.get('injectors')
try:
if state == 'present':
params['create_on_missing'] = True
result = credential_type_res.modify(**params)
json_output['id'] = result['id']
elif state == 'absent':
params['fail_on_missing'] = False
result = credential_type_res.delete(**params)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(
msg='Failed to update credential type: {0}'.format(excinfo),
changed=False
)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,177 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_group
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: create, update, or destroy Ansible Tower group.
description:
- Create, update, or destroy Ansible Tower groups. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- The name to use for the group.
required: True
description:
description:
- The description to use for the group.
inventory:
description:
- Inventory the group should be made a member of.
required: True
variables:
description:
- Variables to use for the group, use C(@) for a file.
credential:
description:
- Credential to use for the group.
source:
description:
- The source to use for this group.
choices: ["manual", "file", "ec2", "rax", "vmware", "gce", "azure", "azure_rm", "openstack", "satellite6" , "cloudforms", "custom"]
source_regions:
description:
- Regions for cloud provider.
source_vars:
description:
- Override variables from source with variables from this field.
instance_filters:
description:
- Comma-separated list of filter expressions for matching hosts.
group_by:
description:
- Limit groups automatically created from inventory source.
source_script:
description:
- Inventory script to be used when group type is C(custom).
overwrite:
description:
- Delete child groups and hosts not found in source.
type: bool
default: 'no'
overwrite_vars:
description:
- Override vars in child groups and hosts with those from external source.
update_on_launch:
description:
- Refresh inventory data from its source each time a job is run.
type: bool
default: 'no'
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add tower group
tower_group:
name: localhost
description: "Local Host Group"
inventory: "Local Inventory"
state: present
tower_config_file: "~/tower_cli.cfg"
'''
import os
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
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(),
inventory=dict(required=True),
variables=dict(),
credential=dict(),
source=dict(choices=["manual", "file", "ec2", "rax", "vmware",
"gce", "azure", "azure_rm", "openstack",
"satellite6", "cloudforms", "custom"], default="manual"),
source_regions=dict(),
source_vars=dict(),
instance_filters=dict(),
group_by=dict(),
source_script=dict(),
overwrite=dict(type='bool', default=False),
overwrite_vars=dict(),
update_on_launch=dict(type='bool', default=False),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
inventory = module.params.get('inventory')
credential = module.params.get('credential')
state = module.params.pop('state')
variables = module.params.get('variables')
if variables:
if variables.startswith('@'):
filename = os.path.expanduser(variables[1:])
with open(filename, 'r') as f:
variables = f.read()
json_output = {'group': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
group = tower_cli.get_resource('group')
try:
params = module.params.copy()
params['create_on_missing'] = True
params['variables'] = variables
inv_res = tower_cli.get_resource('inventory')
inv = inv_res.get(name=inventory)
params['inventory'] = inv['id']
if credential:
cred_res = tower_cli.get_resource('credential')
cred = cred_res.get(name=credential)
params['credential'] = cred['id']
if state == 'present':
result = group.modify(**params)
json_output['id'] = result['id']
elif state == 'absent':
result = group.delete(**params)
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update the group, inventory not found: {0}'.format(excinfo), changed=False)
except (exc.ConnectionError, exc.BadRequest, exc.NotFound, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update the group: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,131 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_host
version_added: "2.3"
author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower host.
description:
- Create, update, or destroy Ansible Tower hosts. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- The name to use for the host.
required: True
description:
description:
- The description to use for the host.
inventory:
description:
- Inventory the host should be made a member of.
required: True
enabled:
description:
- If the host should be enabled.
type: bool
default: 'yes'
variables:
description:
- Variables to use for the host. Use C(@) for a file.
state:
description:
- Desired state of the resource.
choices: ["present", "absent"]
default: "present"
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add tower host
tower_host:
name: localhost
description: "Local Host Group"
inventory: "Local Inventory"
state: present
tower_config_file: "~/tower_cli.cfg"
variables:
example_var: 123
'''
import os
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode, HAS_TOWER_CLI
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(),
inventory=dict(required=True),
enabled=dict(type='bool', default=True),
variables=dict(),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
description = module.params.get('description')
inventory = module.params.get('inventory')
enabled = module.params.get('enabled')
state = module.params.get('state')
variables = module.params.get('variables')
if variables:
if variables.startswith('@'):
filename = os.path.expanduser(variables[1:])
with open(filename, 'r') as f:
variables = f.read()
json_output = {'host': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
host = tower_cli.get_resource('host')
try:
inv_res = tower_cli.get_resource('inventory')
inv = inv_res.get(name=inventory)
if state == 'present':
result = host.modify(name=name, inventory=inv['id'], enabled=enabled,
variables=variables, description=description, create_on_missing=True)
json_output['id'] = result['id']
elif state == 'absent':
result = host.delete(name=name, inventory=inv['id'])
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update host, inventory not found: {0}'.format(excinfo), changed=False)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update host: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,130 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_inventory
version_added: "2.3"
author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower inventory.
description:
- Create, update, or destroy Ansible Tower inventories. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- The name to use for the inventory.
required: True
description:
description:
- The description to use for the inventory.
organization:
description:
- Organization the inventory belongs to.
required: True
variables:
description:
- Inventory variables. Use C(@) to get from file.
kind:
description:
- The kind field. Cannot be modified after created.
default: ""
choices: ["", "smart"]
version_added: "2.7"
host_filter:
description:
- The host_filter field. Only useful when C(kind=smart).
version_added: "2.7"
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add tower inventory
tower_inventory:
name: "Foo Inventory"
description: "Our Foo Cloud Servers"
organization: "Bar Org"
state: present
tower_config_file: "~/tower_cli.cfg"
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
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(),
organization=dict(required=True),
variables=dict(),
kind=dict(choices=['', 'smart'], default=''),
host_filter=dict(),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
description = module.params.get('description')
organization = module.params.get('organization')
variables = module.params.get('variables')
state = module.params.get('state')
kind = module.params.get('kind')
host_filter = module.params.get('host_filter')
json_output = {'inventory': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
inventory = tower_cli.get_resource('inventory')
try:
org_res = tower_cli.get_resource('organization')
org = org_res.get(name=organization)
if state == 'present':
result = inventory.modify(name=name, organization=org['id'], variables=variables,
description=description, kind=kind, host_filter=host_filter,
create_on_missing=True)
json_output['id'] = result['id']
elif state == 'absent':
result = inventory.delete(name=name, organization=org['id'])
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update inventory, organization not found: {0}'.format(excinfo), changed=False)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update inventory: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,315 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# Copyright: (c) 2018, Adrien Fleury <fleu42@gmail.com>
# 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': ['preview'],
'supported_by': 'community',
'metadata_version': '1.1'}
DOCUMENTATION = '''
---
module: tower_inventory_source
author: "Adrien Fleury (@fleu42)"
version_added: "2.7"
short_description: create, update, or destroy Ansible Tower inventory source.
description:
- Create, update, or destroy Ansible Tower inventories source. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- The name to use for the inventory source.
required: True
description:
description:
- The description to use for the inventory source.
inventory:
description:
- The inventory the source is linked to.
required: True
source:
description:
- Types of inventory source.
choices:
- file
- scm
- ec2
- gce
- azure
- azure_rm
- vmware
- satellite6
- cloudforms
- openstack
- rhv
- tower
- custom
required: True
credential:
description:
- Credential to use to retrieve the inventory from.
source_vars:
description:
- >-
The source_vars allow to Override variables found in the source config
file. For example with Openstack, specifying *private: false* would
change the output of the openstack.py script. It has to be YAML or
JSON.
timeout:
description:
- Number in seconds after which the Tower API methods will time out.
source_project:
description:
- Use a *project* as a source for the *inventory*.
source_path:
description:
- Path to the file to use as a source in the selected *project*.
update_on_project_update:
description:
- >-
That parameter will sync the inventory when the project is synced. It
can only be used with a SCM source.
type: bool
source_regions:
description:
- >-
List of regions for your cloud provider. You can include multiple all
regions. Only Hosts associated with the selected regions will be
updated. Refer to Ansible Tower documentation for more detail.
instance_filters:
description:
- >-
Provide a comma-separated list of filter expressions. Hosts are
imported when all of the filters match. Refer to Ansible Tower
documentation for more detail.
group_by:
description:
- >-
Specify which groups to create automatically. Group names will be
created similar to the options selected. If blank, all groups above
are created. Refer to Ansible Tower documentation for more detail.
source_script:
description:
- >-
The source custom script to use to build the inventory. It needs to
exist.
overwrite:
description:
- >-
If set, any hosts and groups that were previously present on the
external source but are now removed will be removed from the Tower
inventory. Hosts and groups that were not managed by the inventory
source will be promoted to the next manually created group or if
there is no manually created group to promote them into, they will be
left in the "all" default group for the inventory. When not checked,
local child hosts and groups not found on the external source will
remain untouched by the inventory update process.
type: bool
overwrite_vars:
description:
- >-
If set, all variables for child groups and hosts will be removed
and replaced by those found on the external source. When not checked,
a merge will be performed, combining local variables with those found
on the external source.
type: bool
update_on_launch:
description:
- >-
Each time a job runs using this inventory, refresh the inventory from
the selected source before executing job tasks.
type: bool
update_cache_timeout:
description:
- >-
Time in seconds to consider an inventory sync to be current. During
job runs and callbacks the task system will evaluate the timestamp of
the latest sync. If it is older than Cache Timeout, it is not
considered current, and a new inventory sync will be performed.
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
validate_certs:
description:
- Tower option to avoid certificates check.
type: bool
aliases: [ tower_verify_ssl ]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add tower inventory source
tower_inventory_source:
name: Inventory source
description: My Inventory source
inventory: My inventory
credential: Devstack_credential
source: openstack
update_on_launch: true
overwrite: true
source_vars: '{ private: false }'
state: present
validate_certs: false
'''
RETURN = ''' # '''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
SOURCE_CHOICES = {
'file': 'Directory or Script',
'scm': 'Sourced from a Project',
'ec2': 'Amazon EC2',
'gce': 'Google Compute Engine',
'azure': 'Microsoft Azure',
'azure_rm': 'Microsoft Azure Resource Manager',
'vmware': 'VMware vCenter',
'satellite6': 'Red Hat Satellite 6',
'cloudforms': 'Red Hat CloudForms',
'openstack': 'OpenStack',
'rhv': 'Red Hat Virtualization',
'tower': 'Ansible Tower',
'custom': 'Custom Script',
}
def main():
argument_spec = dict(
name=dict(required=True),
description=dict(required=False),
inventory=dict(required=True),
source=dict(required=True,
choices=SOURCE_CHOICES.keys()),
credential=dict(required=False),
source_vars=dict(required=False),
timeout=dict(type='int', required=False),
source_project=dict(required=False),
source_path=dict(required=False),
update_on_project_update=dict(type='bool', required=False),
source_regions=dict(required=False),
instance_filters=dict(required=False),
group_by=dict(required=False),
source_script=dict(required=False),
overwrite=dict(type='bool', required=False),
overwrite_vars=dict(type='bool', required=False),
update_on_launch=dict(type='bool', required=False),
update_cache_timeout=dict(type='int', required=False),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
inventory = module.params.get('inventory')
source = module.params.get('source')
state = module.params.get('state')
json_output = {'inventory_source': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
inventory_source = tower_cli.get_resource('inventory_source')
try:
params = {}
params['name'] = name
params['source'] = source
if module.params.get('description'):
params['description'] = module.params.get('description')
if module.params.get('credential'):
credential_res = tower_cli.get_resource('credential')
try:
credential = credential_res.get(
name=module.params.get('credential'))
params['credential'] = credential['id']
except (exc.NotFound) as excinfo:
module.fail_json(
msg='Failed to update credential source,'
'credential not found: {0}'.format(excinfo),
changed=False
)
if module.params.get('source_project'):
source_project_res = tower_cli.get_resource('project')
try:
source_project = source_project_res.get(
name=module.params.get('source_project'))
params['source_project'] = source_project['id']
except (exc.NotFound) as excinfo:
module.fail_json(
msg='Failed to update source project,'
'project not found: {0}'.format(excinfo),
changed=False
)
if module.params.get('source_script'):
source_script_res = tower_cli.get_resource('inventory_script')
try:
script = source_script_res.get(
name=module.params.get('source_script'))
params['source_script'] = script['id']
except (exc.NotFound) as excinfo:
module.fail_json(
msg='Failed to update source script,'
'script not found: {0}'.format(excinfo),
changed=False
)
try:
inventory_res = tower_cli.get_resource('inventory')
params['inventory'] = inventory_res.get(name=inventory)['id']
except (exc.NotFound) as excinfo:
module.fail_json(
msg='Failed to update inventory source, '
'inventory not found: {0}'.format(excinfo),
changed=False
)
for key in ('source_vars', 'timeout', 'source_path',
'update_on_project_update', 'source_regions',
'instance_filters', 'group_by', 'overwrite',
'overwrite_vars', 'update_on_launch',
'update_cache_timeout'):
if module.params.get(key) is not None:
params[key] = module.params.get(key)
if state == 'present':
params['create_on_missing'] = True
result = inventory_source.modify(**params)
json_output['id'] = result['id']
elif state == 'absent':
params['fail_on_missing'] = False
result = inventory_source.delete(**params)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update inventory source: \
{0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,101 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_job_cancel
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: Cancel an Ansible Tower Job.
description:
- Cancel Ansible Tower jobs. See
U(https://www.ansible.com/tower) for an overview.
options:
job_id:
description:
- ID of the job to cancel
required: True
fail_if_not_running:
description:
- Fail loudly if the I(job_id) does not reference a running job.
default: False
type: bool
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Cancel job
tower_job_cancel:
job_id: job.id
'''
RETURN = '''
id:
description: job id requesting to cancel
returned: success
type: int
sample: 94
status:
description: status of the cancel request
returned: success
type: str
sample: canceled
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def main():
argument_spec = dict(
job_id=dict(type='int', required=True),
fail_if_not_running=dict(type='bool', default=False),
)
module = TowerModule(
argument_spec=argument_spec,
supports_check_mode=True,
)
job_id = module.params.get('job_id')
json_output = {}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
job = tower_cli.get_resource('job')
params = module.params.copy()
try:
result = job.cancel(job_id, **params)
json_output['id'] = job_id
except (exc.ConnectionError, exc.BadRequest, exc.TowerCLIError, exc.AuthError) as excinfo:
module.fail_json(msg='Unable to cancel job_id/{0}: {1}'.format(job_id, excinfo), changed=False)
json_output['changed'] = result['changed']
json_output['status'] = result['status']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,159 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_job_launch
author: "Wayne Witzel III (@wwitzel3)"
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.
job_type:
description:
- Job_type to use for the job, only used if prompt for job_type is set.
choices: ["run", "check", "scan"]
inventory:
description:
- Inventory to use for the job, only used if prompt for inventory is set.
credential:
description:
- Credential to use for job, only used if prompt for credential is set.
extra_vars:
description:
- Extra_vars to use for the job_template. Prepend C(@) if a file.
limit:
description:
- Limit to use for the I(job_template).
tags:
description:
- Specific tags to use for from playbook.
use_job_endpoint:
description:
- Disable launching jobs from job template.
type: bool
default: 'no'
extends_documentation_fragment: tower
'''
EXAMPLES = '''
# Launch a job template
- 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
# Launch job template with inventory and credential for prompt on launch
- name: Launch a job with inventory and credential
tower_job_launch:
job_template: "My Job Template"
inventory: "My Inventory"
credential: "My Credential"
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: str
sample: pending
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def main():
argument_spec = dict(
job_template=dict(required=True, type='str'),
job_type=dict(choices=['run', 'check', 'scan']),
inventory=dict(type='str', default=None),
credential=dict(type='str', default=None),
limit=dict(),
tags=dict(type='list'),
extra_vars=dict(type='list'),
)
module = TowerModule(
argument_spec,
supports_check_mode=True
)
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)
if name:
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, exc.AuthError) 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()

@ -1,128 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_job_list
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: List Ansible Tower jobs.
description:
- List Ansible Tower jobs. See
U(https://www.ansible.com/tower) for an overview.
options:
status:
description:
- Only list jobs with this status.
choices: ['pending', 'waiting', 'running', 'error', 'failed', 'canceled', 'successful']
page:
description:
- Page number of the results to fetch.
all_pages:
description:
- Fetch all the pages and return a single result.
type: bool
default: 'no'
query:
description:
- Query used to further filter the list of jobs. C({"foo":"bar"}) will be passed at C(?foo=bar)
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: List running jobs for the testing.yml playbook
tower_job_list:
status: running
query: {"playbook": "testing.yml"}
tower_config_file: "~/tower_cli.cfg"
register: testing_jobs
'''
RETURN = '''
count:
description: Total count of objects return
returned: success
type: int
sample: 51
next:
description: next page available for the listing
returned: success
type: int
sample: 3
previous:
description: previous page available for the listing
returned: success
type: int
sample: 1
results:
description: a list of job objects represented as dictionaries
returned: success
type: list
sample: [{"allow_simultaneous": false, "artifacts": {}, "ask_credential_on_launch": false,
"ask_inventory_on_launch": false, "ask_job_type_on_launch": false, "failed": false,
"finished": "2017-02-22T15:09:05.633942Z", "force_handlers": false, "forks": 0, "id": 2,
"inventory": 1, "job_explanation": "", "job_tags": "", "job_template": 5, "job_type": "run"}, ...]
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def main():
argument_spec = dict(
status=dict(choices=['pending', 'waiting', 'running', 'error', 'failed', 'canceled', 'successful']),
page=dict(type='int'),
all_pages=dict(type='bool', default=False),
query=dict(type='dict'),
)
module = TowerModule(
argument_spec=argument_spec,
supports_check_mode=True
)
json_output = {}
query = module.params.get('query')
status = module.params.get('status')
page = module.params.get('page')
all_pages = module.params.get('all_pages')
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
try:
job = tower_cli.get_resource('job')
params = {'status': status, 'page': page, 'all_pages': all_pages}
if query:
params['query'] = query.items()
json_output = job.list(**params)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to list jobs: {0}'.format(excinfo), changed=False)
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,337 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_job_template
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: create, update, or destroy Ansible Tower job template.
description:
- Create, update, or destroy Ansible Tower job templates. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- Name to use for the job template.
required: True
description:
description:
- Description to use for the job template.
job_type:
description:
- The job type to use for the job template.
required: True
choices: ["run", "check", "scan"]
inventory:
description:
- Name of the inventory to use for the job template.
project:
description:
- Name of the project to use for the job template.
required: True
playbook:
description:
- Path to the playbook to use for the job template within the project provided.
required: True
credential:
description:
- Name of the credential to use for the job template.
version_added: 2.7
vault_credential:
description:
- Name of the vault credential to use for the job template.
version_added: 2.7
forks:
description:
- The number of parallel or simultaneous processes to use while executing the playbook.
limit:
description:
- A host pattern to further constrain the list of hosts managed or affected by the playbook
verbosity:
description:
- Control the output level Ansible produces as the playbook runs. 0 - Normal, 1 - Verbose, 2 - More Verbose, 3 - Debug, 4 - Connection Debug.
choices: [0, 1, 2, 3, 4]
default: 0
extra_vars_path:
description:
- Path to the C(extra_vars) YAML file.
job_tags:
description:
- Comma separated list of the tags to use for the job template.
force_handlers_enabled:
description:
- Enable forcing playbook handlers to run even if a task fails.
version_added: 2.7
type: bool
default: 'no'
skip_tags:
description:
- Comma separated list of the tags to skip for the job template.
start_at_task:
description:
- Start the playbook at the task matching this name.
version_added: 2.7
diff_mode_enabled:
description:
- Enable diff mode for the job template.
version_added: 2.7
type: bool
default: 'no'
fact_caching_enabled:
description:
- Enable use of fact caching for the job template.
version_added: 2.7
type: bool
default: 'no'
host_config_key:
description:
- Allow provisioning callbacks using this host config key.
ask_diff_mode:
description:
- Prompt user to enable diff mode (show changes) to files when supported by modules.
version_added: 2.7
type: bool
default: 'no'
ask_extra_vars:
description:
- Prompt user for (extra_vars) on launch.
type: bool
default: 'no'
ask_limit:
description:
- Prompt user for a limit on launch.
version_added: 2.7
type: bool
default: 'no'
ask_tags:
description:
- Prompt user for job tags on launch.
type: bool
default: 'no'
ask_skip_tags:
description:
- Prompt user for job tags to skip on launch.
version_added: 2.7
type: bool
default: 'no'
ask_job_type:
description:
- Prompt user for job type on launch.
type: bool
default: 'no'
ask_verbosity:
description:
- Prompt user to choose a verbosity level on launch.
version_added: 2.7
type: bool
default: 'no'
ask_inventory:
description:
- Prompt user for inventory on launch.
type: bool
default: 'no'
ask_credential:
description:
- Prompt user for credential on launch.
type: bool
default: 'no'
survey_enabled:
description:
- Enable a survey on the job template.
version_added: 2.7
type: bool
default: 'no'
survey_spec:
description:
- JSON/YAML dict formatted survey definition.
version_added: 2.8
type: dict
required: False
become_enabled:
description:
- Activate privilege escalation.
type: bool
default: 'no'
concurrent_jobs_enabled:
description:
- Allow simultaneous runs of the job template.
version_added: 2.7
type: bool
default: 'no'
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
extends_documentation_fragment: tower
notes:
- JSON for survey_spec can be found in Tower API Documentation. See
U(https://docs.ansible.com/ansible-tower/latest/html/towerapi/api_ref.html#/Job_Templates/Job_Templates_job_templates_survey_spec_create)
for POST operation payload example.
'''
EXAMPLES = '''
- name: Create tower Ping job template
tower_job_template:
name: "Ping"
job_type: "run"
inventory: "Local"
project: "Demo"
playbook: "ping.yml"
credential: "Local"
state: "present"
tower_config_file: "~/tower_cli.cfg"
survey_enabled: yes
survey_spec: "{{ lookup('file', 'my_survey.json') }}"
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def update_fields(p):
'''This updates the module field names
to match the field names tower-cli expects to make
calling of the modify/delete methods easier.
'''
params = p.copy()
field_map = {
'fact_caching_enabled': 'use_fact_cache',
'ask_diff_mode': 'ask_diff_mode_on_launch',
'ask_extra_vars': 'ask_variables_on_launch',
'ask_limit': 'ask_limit_on_launch',
'ask_tags': 'ask_tags_on_launch',
'ask_skip_tags': 'ask_skip_tags_on_launch',
'ask_verbosity': 'ask_verbosity_on_launch',
'ask_inventory': 'ask_inventory_on_launch',
'ask_credential': 'ask_credential_on_launch',
'ask_job_type': 'ask_job_type_on_launch',
'diff_mode_enabled': 'diff_mode',
'concurrent_jobs_enabled': 'allow_simultaneous',
'force_handlers_enabled': 'force_handlers',
}
params_update = {}
for old_k, new_k in field_map.items():
v = params.pop(old_k)
params_update[new_k] = v
extra_vars = params.get('extra_vars_path')
if extra_vars is not None:
params_update['extra_vars'] = ['@' + extra_vars]
params.update(params_update)
return params
def update_resources(module, p):
params = p.copy()
identity_map = {
'project': 'name',
'inventory': 'name',
'credential': 'name',
'vault_credential': 'name',
}
for k, v in identity_map.items():
try:
if params[k]:
key = 'credential' if '_credential' in k else k
result = tower_cli.get_resource(key).get(**{v: params[k]})
params[k] = result['id']
elif k in params:
# unset empty parameters to avoid ValueError: invalid literal for int() with base 10: ''
del(params[k])
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update job template: {0}'.format(excinfo), changed=False)
return params
def main():
argument_spec = dict(
name=dict(required=True),
description=dict(default=''),
job_type=dict(choices=['run', 'check', 'scan'], required=True),
inventory=dict(default=''),
project=dict(required=True),
playbook=dict(required=True),
credential=dict(default=''),
vault_credential=dict(default=''),
forks=dict(type='int'),
limit=dict(default=''),
verbosity=dict(type='int', choices=[0, 1, 2, 3, 4], default=0),
extra_vars_path=dict(type='path', required=False),
job_tags=dict(default=''),
force_handlers_enabled=dict(type='bool', default=False),
skip_tags=dict(default=''),
start_at_task=dict(default=''),
timeout=dict(type='int', default=0),
fact_caching_enabled=dict(type='bool', default=False),
host_config_key=dict(default=''),
ask_diff_mode=dict(type='bool', default=False),
ask_extra_vars=dict(type='bool', default=False),
ask_limit=dict(type='bool', default=False),
ask_tags=dict(type='bool', default=False),
ask_skip_tags=dict(type='bool', default=False),
ask_job_type=dict(type='bool', default=False),
ask_verbosity=dict(type='bool', default=False),
ask_inventory=dict(type='bool', default=False),
ask_credential=dict(type='bool', default=False),
survey_enabled=dict(type='bool', default=False),
survey_spec=dict(type='dict', required=False),
become_enabled=dict(type='bool', default=False),
diff_mode_enabled=dict(type='bool', default=False),
concurrent_jobs_enabled=dict(type='bool', default=False),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
state = module.params.pop('state')
json_output = {'job_template': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
jt = tower_cli.get_resource('job_template')
params = update_resources(module, module.params)
params = update_fields(params)
params['create_on_missing'] = True
try:
if state == 'present':
result = jt.modify(**params)
json_output['id'] = result['id']
elif state == 'absent':
result = jt.delete(**params)
except (exc.ConnectionError, exc.BadRequest, exc.NotFound, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update job template: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,149 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_job_wait
version_added: "2.3"
author: "Wayne Witzel III (@wwitzel3)"
short_description: Wait for Ansible Tower job to finish.
description:
- Wait for Ansible Tower job to finish and report success or failure. See
U(https://www.ansible.com/tower) for an overview.
options:
job_id:
description:
- ID of the job to monitor.
required: True
min_interval:
description:
- Minimum interval in seconds, to request an update from Tower.
default: 1
max_interval:
description:
- Maximum interval in seconds, to request an update from Tower.
default: 30
timeout:
description:
- Maximum time in seconds to wait for a job to finish.
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 that is being waited on
returned: success
type: int
sample: 99
elapsed:
description: total time in seconds the job took to run
returned: success
type: float
sample: 10.879
started:
description: timestamp of when the job started running
returned: success
type: str
sample: "2017-03-01T17:03:53.200234Z"
finished:
description: timestamp of when the job finished running
returned: success
type: str
sample: "2017-03-01T17:04:04.078782Z"
status:
description: current status of job
returned: success
type: str
sample: successful
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
from ansible.module_utils.six.moves import cStringIO as StringIO
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def main():
argument_spec = dict(
job_id=dict(type='int', required=True),
timeout=dict(type='int'),
min_interval=dict(type='float', default=1),
max_interval=dict(type='float', default=30),
)
module = TowerModule(
argument_spec,
supports_check_mode=True
)
json_output = {}
fail_json = None
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
job = tower_cli.get_resource('job')
params = module.params.copy()
# tower-cli gets very noisy when monitoring.
# We pass in our our outfile to suppress the out during our monitor call.
outfile = StringIO()
params['outfile'] = outfile
job_id = params.get('job_id')
try:
result = job.monitor(job_id, **params)
except exc.Timeout as excinfo:
result = job.status(job_id)
result['id'] = job_id
json_output['msg'] = 'Timeout waiting for job to finish.'
json_output['timeout'] = True
except exc.NotFound as excinfo:
fail_json = dict(msg='Unable to wait, no job_id {0} found: {1}'.format(job_id, excinfo), changed=False)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
fail_json = dict(msg='Unable to wait for job: {0}'.format(excinfo), changed=False)
if fail_json is not None:
module.fail_json(**fail_json)
json_output['success'] = True
for k in ('id', 'status', 'elapsed', 'started', 'finished'):
json_output[k] = result.get(k)
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,102 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_label
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: create, update, or destroy Ansible Tower label.
description:
- Create, update, or destroy Ansible Tower labels. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- Name to use for the label.
required: True
organization:
description:
- Organization the label should be applied to.
required: True
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add label to tower organization
tower_label:
name: Custom Label
organization: My Organization
state: present
tower_config_file: "~/tower_cli.cfg"
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
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),
organization=dict(required=True),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
organization = module.params.get('organization')
state = module.params.get('state')
json_output = {'label': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
label = tower_cli.get_resource('label')
try:
org_res = tower_cli.get_resource('organization')
org = org_res.get(name=organization)
if state == 'present':
result = label.modify(name=name, organization=org['id'], create_on_missing=True)
json_output['id'] = result['id']
elif state == 'absent':
result = label.delete(name=name, organization=org['id'])
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update label, organization not found: {0}'.format(excinfo), changed=False)
except (exc.ConnectionError, exc.BadRequest, exc.NotFound, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update label: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,393 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2018, Samuel Carpentier <samuelcarpentier0@gmail.ca>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_notification
author: "Samuel Carpentier (@samcarpentier)"
version_added: "2.8"
short_description: create, update, or destroy Ansible Tower notification.
description:
- Create, update, or destroy Ansible Tower notifications. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- The name of the notification.
required: True
description:
description:
- The description of the notification.
required: False
organization:
description:
- The organization the notification belongs to.
required: False
notification_type:
description:
- The type of notification to be sent.
required: True
choices: ["email", "slack", "twilio", "pagerduty", "hipchat", "webhook", "irc"]
notification_configuration:
description:
- The notification configuration file. Note providing this field would disable all notification-configuration-related fields.
required: False
username:
description:
- The mail server username. Required if I(notification_type=email).
required: False
sender:
description:
- The sender email address. Required if I(notification_type=email).
required: False
recipients:
description:
- The recipients email addresses. Required if I(notification_type=email).
required: False
use_tls:
description:
- The TLS trigger. Required if I(notification_type=email).
required: False
type: bool
host:
description:
- The mail server host. Required if I(notification_type=email).
required: False
use_ssl:
description:
- The SSL trigger. Required if I(notification_type=email) or if I(notification_type=irc).
required: False
type: bool
password:
description:
- The mail server password. Required if I(notification_type=email) or if I(notification_type=irc).
required: False
port:
description:
- The mail server port. Required if I(notification_type=email) or if I(notification_type=irc).
required: False
channels:
description:
- The destination Slack channels. Required if I(notification_type=slack).
required: False
type: list
token:
description:
- The access token. Required if I(notification_type=slack), if I(notification_type=pagerduty) or if I(notification_type=hipchat).
required: False
account_token:
description:
- The Twillio account token. Required if I(notification_type=twillio).
required: False
from_number:
description:
- The source phone number. Required if I(notification_type=twillio).
required: False
to_numbers:
description:
- The destination phone numbers. Required if I(notification_type=twillio).
required: False
account_sid:
description:
- The Twillio account SID. Required if I(notification_type=twillio).
required: False
subdomain:
description:
- The PagerDuty subdomain. Required if I(notification_type=pagerduty).
required: False
service_key:
description:
- The PagerDuty service/integration API key. Required if I(notification_type=pagerduty).
required: False
client_name:
description:
- The PagerDuty client identifier. Required if I(notification_type=pagerduty).
required: False
message_from:
description:
- The label to be shown with the notification. Required if I(notification_type=hipchat).
required: False
api_url:
description:
- The HipChat API URL. Required if I(notification_type=hipchat).
required: False
color:
description:
- The notification color. Required if I(notification_type=hipchat).
required: False
choices: ["yellow", "green", "red", "purple", "gray", "random"]
rooms:
description:
- HipChat rooms to send the notification to. Required if I(notification_type=hipchat).
required: False
type: list
notify:
description:
- The notify channel trigger. Required if I(notification_type=hipchat).
required: False
type: bool
url:
description:
- The target URL. Required if I(notification_type=webhook).
required: False
headers:
description:
- The HTTP headers as JSON string. Required if I(notification_type=webhook).
required: False
server:
description:
- The IRC server address. Required if I(notification_type=irc).
required: False
nickname:
description:
- The IRC nickname. Required if I(notification_type=irc).
required: False
targets:
description:
- The destination channels or users. Required if I(notification_type=irc).
required: False
type: list
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add Slack notification
tower_notification:
name: slack notification
notification_type: slack
channels:
- general
token: cefda9e2be1f21d11cdd9452f5b7f97fda977f42
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add webhook notification
tower_notification:
name: webhook notification
notification_type: webhook
url: http://www.example.com/hook
headers:
X-Custom-Header: value123
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add email notification
tower_notification:
name: email notification
notification_type: email
username: user
password: s3cr3t
sender: tower@example.com
recipients:
- user1@example.com
host: smtp.example.com
port: 25
use_tls: no
use_ssl: no
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add twilio notification
tower_notification:
name: twilio notification
notification_type: twilio
account_token: a_token
account_sid: a_sid
from_number: '+15551112222'
to_numbers:
- '+15553334444'
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add PagerDuty notification
tower_notification:
name: pagerduty notification
notification_type: pagerduty
token: a_token
subdomain: sub
client_name: client
service_key: a_key
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add HipChat notification
tower_notification:
name: hipchat notification
notification_type: hipchat
token: a_token
message_from: user1
api_url: https://hipchat.example.com
color: red
rooms:
- room-A
notify: yes
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add IRC notification
tower_notification:
name: irc notification
notification_type: irc
nickname: tower
password: s3cr3t
targets:
- user1
port: 8080
server: irc.example.com
use_ssl: no
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Delete notification
tower_notification:
name: old notification
notification_type: email
state: absent
tower_config_file: "~/tower_cli.cfg"
'''
RETURN = ''' # '''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.utils.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def main():
argument_spec = dict(
name=dict(required=True),
description=dict(required=False),
organization=dict(required=False),
notification_type=dict(required=True, choices=['email', 'slack', 'twilio', 'pagerduty', 'hipchat', 'webhook', 'irc']),
notification_configuration=dict(required=False),
username=dict(required=False),
sender=dict(required=False),
recipients=dict(required=False, type='list'),
use_tls=dict(required=False, type='bool'),
host=dict(required=False),
use_ssl=dict(required=False, type='bool'),
password=dict(required=False, no_log=True),
port=dict(required=False, type='int'),
channels=dict(required=False, type='list'),
token=dict(required=False, no_log=True),
account_token=dict(required=False, no_log=True),
from_number=dict(required=False),
to_numbers=dict(required=False, type='list'),
account_sid=dict(required=False),
subdomain=dict(required=False),
service_key=dict(required=False, no_log=True),
client_name=dict(required=False),
message_from=dict(required=False),
api_url=dict(required=False),
color=dict(required=False, choices=['yellow', 'green', 'red', 'purple', 'gray', 'random']),
rooms=dict(required=False, type='list'),
notify=dict(required=False, type='bool'),
url=dict(required=False),
headers=dict(required=False, type='dict', default={}),
server=dict(required=False),
nickname=dict(required=False),
targets=dict(required=False, type='list'),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
description = module.params.get('description')
organization = module.params.get('organization')
notification_type = module.params.get('notification_type')
notification_configuration = module.params.get('notification_configuration')
username = module.params.get('username')
sender = module.params.get('sender')
recipients = module.params.get('recipients')
use_tls = module.params.get('use_tls')
host = module.params.get('host')
use_ssl = module.params.get('use_ssl')
password = module.params.get('password')
port = module.params.get('port')
channels = module.params.get('channels')
token = module.params.get('token')
account_token = module.params.get('account_token')
from_number = module.params.get('from_number')
to_numbers = module.params.get('to_numbers')
account_sid = module.params.get('account_sid')
subdomain = module.params.get('subdomain')
service_key = module.params.get('service_key')
client_name = module.params.get('client_name')
message_from = module.params.get('message_from')
api_url = module.params.get('api_url')
color = module.params.get('color')
rooms = module.params.get('rooms')
notify = module.params.get('notify')
url = module.params.get('url')
headers = module.params.get('headers')
server = module.params.get('server')
nickname = module.params.get('nickname')
targets = module.params.get('targets')
state = module.params.get('state')
json_output = {'notification': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
notification_template = tower_cli.get_resource('notification_template')
try:
org_res = tower_cli.get_resource('organization')
org = org_res.get(name=organization)
if state == 'present':
result = notification_template.modify(name=name, description=description, organization=org['id'],
notification_type=notification_type,
notification_configuration=notification_configuration,
username=username, sender=sender, recipients=recipients,
use_tls=use_tls, host=host, use_ssl=use_ssl, password=password,
port=port, channels=channels, token=token,
account_token=account_token, from_number=from_number,
to_numbers=to_numbers, account_sid=account_sid,
subdomain=subdomain, service_key=service_key,
client_name=client_name, message_from=message_from,
api_url=api_url, color=color, rooms=rooms, notify=notify,
url=url, headers=headers, server=server, nickname=nickname,
targets=targets, create_on_missing=True)
json_output['id'] = result['id']
elif state == 'absent':
result = notification_template.delete(name=name)
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update notification template, organization not found: {0}'.format(excinfo), changed=False)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update notification template: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,95 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_organization
version_added: "2.3"
author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower organizations
description:
- Create, update, or destroy Ansible Tower organizations. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- Name to use for the organization.
required: True
description:
description:
- The description to use for the organization.
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Create tower organization
tower_organization:
name: "Foo"
description: "Foo bar organization"
state: present
tower_config_file: "~/tower_cli.cfg"
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
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(),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
description = module.params.get('description')
state = module.params.get('state')
json_output = {'organization': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
organization = tower_cli.get_resource('organization')
try:
if state == 'present':
result = organization.modify(name=name, description=description, create_on_missing=True)
json_output['id'] = result['id']
elif state == 'absent':
result = organization.delete(name=name)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update the organization: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,213 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_project
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: create, update, or destroy Ansible Tower projects
description:
- Create, update, or destroy Ansible Tower projects. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- Name to use for the project.
required: True
description:
description:
- Description to use for the project.
scm_type:
description:
- Type of SCM resource.
choices: ["manual", "git", "hg", "svn"]
default: "manual"
scm_url:
description:
- URL of SCM resource.
local_path:
description:
- The server playbook directory for manual projects.
scm_branch:
description:
- The branch to use for the SCM resource.
scm_credential:
description:
- Name of the credential to use with this SCM resource.
scm_clean:
description:
- Remove local modifications before updating.
type: bool
default: 'no'
scm_delete_on_update:
description:
- Remove the repository completely before updating.
type: bool
default: 'no'
scm_update_on_launch:
description:
- Before an update to the local repository before launching a job with this project.
type: bool
default: 'no'
scm_update_cache_timeout:
version_added: "2.8"
description:
- Cache Timeout to cache prior project syncs for a certain number of seconds.
Only valid if scm_update_on_launch is to True, otherwise ignored.
default: 0
job_timeout:
version_added: "2.8"
description:
- The amount of time (in seconds) to run before the SCM Update is canceled. A value of 0 means no timeout.
default: 0
custom_virtualenv:
version_added: "2.8"
description:
- Local absolute file path containing a custom Python virtualenv to use
organization:
description:
- Primary key of organization for project.
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add tower project
tower_project:
name: "Foo"
description: "Foo bar project"
organization: "test"
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add Tower Project with cache timeout and custom virtualenv
tower_project:
name: "Foo"
description: "Foo bar project"
organization: "test"
scm_update_on_launch: True
scm_update_cache_timeout: 60
custom_virtualenv: "/var/lib/awx/venv/ansible-2.2"
state: present
tower_config_file: "~/tower_cli.cfg"
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
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(),
description=dict(),
organization=dict(),
scm_type=dict(choices=['manual', 'git', 'hg', 'svn'], default='manual'),
scm_url=dict(),
scm_branch=dict(),
scm_credential=dict(),
scm_clean=dict(type='bool', default=False),
scm_delete_on_update=dict(type='bool', default=False),
scm_update_on_launch=dict(type='bool', default=False),
scm_update_cache_timeout=dict(type='int', default=0),
job_timeout=dict(type='int', default=0),
custom_virtualenv=dict(),
local_path=dict(),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
description = module.params.get('description')
organization = module.params.get('organization')
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_credential = module.params.get('scm_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')
job_timeout = module.params.get('job_timeout')
custom_virtualenv = module.params.get('custom_virtualenv')
state = module.params.get('state')
json_output = {'project': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
project = tower_cli.get_resource('project')
try:
if state == 'present':
try:
org_res = tower_cli.get_resource('organization')
org = org_res.get(name=organization)
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update project, organization not found: {0}'.format(organization), changed=False)
if scm_credential:
try:
cred_res = tower_cli.get_resource('credential')
try:
cred = cred_res.get(name=scm_credential)
except (tower_cli.exceptions.MultipleResults) as multi_res_excinfo:
module.warn('Multiple credentials found for {0}, falling back looking in project organization'.format(scm_credential))
cred = cred_res.get(name=scm_credential, organization=org['id'])
scm_credential = cred['id']
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update project, credential not found: {0}'.format(scm_credential), changed=False)
if (scm_update_cache_timeout is not None) 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')
result = project.modify(name=name, description=description,
organization=org['id'],
scm_type=scm_type, scm_url=scm_url, local_path=local_path,
scm_branch=scm_branch, scm_clean=scm_clean, credential=scm_credential,
scm_delete_on_update=scm_delete_on_update,
scm_update_on_launch=scm_update_on_launch,
scm_update_cache_timeout=scm_update_cache_timeout,
job_timeout=job_timeout,
custom_virtualenv=custom_virtualenv,
create_on_missing=True)
json_output['id'] = result['id']
elif state == 'absent':
result = project.delete(name=name)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update project: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,172 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, John Westcott IV <john.westcott.iv@redhat.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_receive
author: "John Westcott IV (@john-westcott-iv)"
version_added: "2.8"
short_description: Receive assets from Ansible Tower.
description:
- Receive assets from Ansible Tower. 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: []
user:
description:
- List of user names to export
default: []
team:
description:
- List of team names to export
default: []
credential_type:
description:
- List of credential type names to export
default: []
credential:
description:
- List of credential names to export
default: []
notification_template:
description:
- List of notification template names to export
default: []
inventory_script:
description:
- List of inventory script names to export
default: []
inventory:
description:
- List of inventory names to export
default: []
project:
description:
- List of project names to export
default: []
job_template:
description:
- List of job template names to export
default: []
workflow:
description:
- List of workflow names to export
default: []
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: tower
'''
EXAMPLES = '''
- name: Export all tower assets
tower_receive:
all: True
tower_config_file: "~/tower_cli.cfg"
- name: Export all inventories
tower_receive:
inventory:
- all
- name: Export a job template named "My Template" and all Credentials
tower_receive:
job_template:
- "My Template"
credential:
- all
'''
RETURN = '''
assets:
description: The exported assets
returned: success
type: dict
sample: [ {}, {} ]
'''
from ansible.module_utils.ansible_tower import TowerModule, 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=[]),
credential_type=dict(type='list', default=[]),
inventory=dict(type='list', default=[]),
inventory_script=dict(type='list', default=[]),
job_template=dict(type='list', default=[]),
notification_template=dict(type='list', default=[]),
organization=dict(type='list', default=[]),
project=dict(type='list', default=[]),
team=dict(type='list', default=[]),
user=dict(type='list', default=[]),
workflow=dict(type='list', default=[]),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=False)
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()

@ -1,157 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_role
version_added: "2.3"
author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower role.
description:
- Create, update, or destroy Ansible Tower roles. See
U(https://www.ansible.com/tower) for an overview.
options:
user:
description:
- User that receives the permissions specified by the role.
team:
description:
- Team that receives the permissions specified by the role.
role:
description:
- The role type to grant/revoke.
required: True
choices: ["admin", "read", "member", "execute", "adhoc", "update", "use", "auditor", "project_admin", "inventory_admin", "credential_admin",
"workflow_admin", "notification_admin", "job_template_admin"]
target_team:
description:
- Team that the role acts on.
inventory:
description:
- Inventory the role acts on.
job_template:
description:
- The job template the role acts on.
credential:
description:
- Credential the role acts on.
organization:
description:
- Organization the role acts on.
project:
description:
- Project the role acts on.
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add jdoe to the member role of My Team
tower_role:
user: jdoe
target_team: "My Team"
role: member
state: present
tower_config_file: "~/tower_cli.cfg"
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def update_resources(module, p):
'''update_resources attempts to fetch any of the resources given
by name using their unique field (identity)
'''
params = p.copy()
identity_map = {
'user': 'username',
'team': 'name',
'target_team': 'name',
'inventory': 'name',
'job_template': 'name',
'credential': 'name',
'organization': 'name',
'project': 'name',
}
for k, v in identity_map.items():
try:
if params[k]:
key = 'team' if k == 'target_team' else k
result = tower_cli.get_resource(key).get(**{v: params[k]})
params[k] = result['id']
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update role, {0} not found: {1}'.format(k, excinfo), changed=False)
return params
def main():
argument_spec = dict(
user=dict(),
team=dict(),
role=dict(choices=["admin", "read", "member", "execute", "adhoc", "update", "use", "auditor", "project_admin", "inventory_admin", "credential_admin",
"workflow_admin", "notification_admin", "job_template_admin"]),
target_team=dict(),
inventory=dict(),
job_template=dict(),
credential=dict(),
organization=dict(),
project=dict(),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
role_type = module.params.pop('role')
state = module.params.pop('state')
json_output = {'role': role_type, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
role = tower_cli.get_resource('role')
params = update_resources(module, module.params)
params['type'] = role_type
try:
if state == 'present':
result = role.grant(**params)
json_output['id'] = result['id']
elif state == 'absent':
result = role.revoke(**params)
except (exc.ConnectionError, exc.BadRequest, exc.NotFound, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update role: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,167 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, John Westcott IV <john.westcott.iv@redhat.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_send
author: "John Westcott IV (@john-westcott-iv)"
version_added: "2.8"
short_description: Send assets to Ansible Tower.
description:
- Send assets to Ansible Tower. 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
required: False
files:
description:
- List of files to import.
required: False
default: []
prevent:
description:
- A list of asset types to prevent import for
required: false
default: []
password_management:
description:
- The password management option to use.
- The prompt option is not supported.
required: false
default: 'default'
choices: ["default", "random"]
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: tower
'''
EXAMPLES = '''
- name: Import all tower assets
tower_send:
assets: "{{ export_output.assets }}"
tower_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 ansible.module_utils.ansible_tower import TowerModule, 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(required=False),
files=dict(required=False, default=[], type='list'),
prevent=dict(required=False, default=[], type='list'),
password_management=dict(required=False, default='default', choices=['default', 'random']),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=False)
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 as e:
# 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()

@ -1,104 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2018, Nikhil Jain <nikjain@redhat.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_settings
author: "Nikhil Jain (@jainnikhil30)"
version_added: "2.7"
short_description: Modify Ansible Tower settings.
description:
- Modify Ansible Tower settings. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- Name of setting to modify
required: True
value:
description:
- Value to be modified for given setting.
required: True
extends_documentation_fragment: tower
'''
RETURN = ''' # '''
EXAMPLES = '''
- name: Set the value of AWX_PROOT_BASE_PATH
tower_settings:
name: AWX_PROOT_BASE_PATH
value: "/tmp"
register: testing_settings
- name: Set the value of AWX_PROOT_SHOW_PATHS
tower_settings:
name: "AWX_PROOT_SHOW_PATHS"
value: "'/var/lib/awx/projects/', '/tmp'"
register: testing_settings
- name: Set the LDAP Auth Bind Password
tower_settings:
name: "AUTH_LDAP_BIND_PASSWORD"
value: "Password"
no_log: true
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
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),
value=dict(required=True),
)
module = TowerModule(
argument_spec=argument_spec,
supports_check_mode=False
)
json_output = {}
name = module.params.get('name')
value = module.params.get('value')
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
try:
setting = tower_cli.get_resource('setting')
result = setting.modify(setting=name, value=value)
json_output['id'] = result['id']
json_output['value'] = result['value']
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to modify the setting: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,107 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_team
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: create, update, or destroy Ansible Tower team.
description:
- Create, update, or destroy Ansible Tower teams. See
U(https://www.ansible.com/tower) for an overview.
options:
name:
description:
- Name to use for the team.
required: True
organization:
description:
- Organization the team should be made a member of.
required: True
state:
description:
- Desired state of the resource.
choices: ["present", "absent"]
default: "present"
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Create tower team
tower_team:
name: Team Name
description: Team Description
organization: test-org
state: present
tower_config_file: "~/tower_cli.cfg"
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
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(),
organization=dict(required=True),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
name = module.params.get('name')
description = module.params.get('description')
organization = module.params.get('organization')
state = module.params.get('state')
json_output = {'team': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
team = tower_cli.get_resource('team')
try:
org_res = tower_cli.get_resource('organization')
org = org_res.get(name=organization)
if state == 'present':
result = team.modify(name=name, organization=org['id'],
description=description, create_on_missing=True)
json_output['id'] = result['id']
elif state == 'absent':
result = team.delete(name=name, organization=org['id'])
except (exc.NotFound) as excinfo:
module.fail_json(msg='Failed to update team, organization not found: {0}'.format(excinfo), changed=False)
except (exc.ConnectionError, exc.BadRequest, exc.NotFound, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update team: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,159 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_user
author: "Wayne Witzel III (@wwitzel3)"
version_added: "2.3"
short_description: create, update, or destroy Ansible Tower user.
description:
- Create, update, or destroy Ansible Tower users. See
U(https://www.ansible.com/tower) for an overview.
options:
username:
description:
- The username of the user.
required: True
first_name:
description:
- First name of the user.
last_name:
description:
- Last name of the user.
email:
description:
- Email address of the user.
required: True
password:
description:
- Password of the user.
superuser:
description:
- User is a system wide administrator.
type: bool
default: 'no'
auditor:
description:
- User is a system wide auditor.
type: bool
default: 'no'
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
requirements:
- ansible-tower-cli >= 3.2.0
extends_documentation_fragment: tower
'''
EXAMPLES = '''
- name: Add tower user
tower_user:
username: jdoe
password: foobarbaz
email: jdoe@example.org
first_name: John
last_name: Doe
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add tower user as a system administrator
tower_user:
username: jdoe
password: foobarbaz
email: jdoe@example.org
superuser: yes
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Add tower user as a system auditor
tower_user:
username: jdoe
password: foobarbaz
email: jdoe@example.org
auditor: yes
state: present
tower_config_file: "~/tower_cli.cfg"
- name: Delete tower user
tower_user:
username: jdoe
email: jdoe@example.org
state: absent
tower_config_file: "~/tower_cli.cfg"
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config, tower_check_mode
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def main():
argument_spec = dict(
username=dict(required=True),
first_name=dict(),
last_name=dict(),
password=dict(no_log=True),
email=dict(required=True),
superuser=dict(type='bool', default=False),
auditor=dict(type='bool', default=False),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)
username = module.params.get('username')
first_name = module.params.get('first_name')
last_name = module.params.get('last_name')
password = module.params.get('password')
email = module.params.get('email')
superuser = module.params.get('superuser')
auditor = module.params.get('auditor')
state = module.params.get('state')
json_output = {'username': username, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
user = tower_cli.get_resource('user')
try:
if state == 'present':
result = user.modify(username=username, first_name=first_name, last_name=last_name,
email=email, password=password, is_superuser=superuser,
is_system_auditor=auditor, create_on_missing=True)
json_output['id'] = result['id']
elif state == 'absent':
result = user.delete(username=username)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(msg='Failed to update the user: {0}'.format(excinfo), changed=False)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

@ -1,164 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# 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': ['preview'],
'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_workflow_launch
author: "John Westcott IV (@john-westcott-iv)"
version_added: "2.8"
short_description: Run a workflow in Ansible Tower
description:
- Launch an Ansible Tower workflows. See
U(https://www.ansible.com/tower) for an overview.
options:
workflow_template:
description:
- The name of the workflow template to run.
required: True
extra_vars:
description:
- Any extra vars required to launch the job.
required: False
wait:
description:
- Wait for the workflow to complete.
required: False
default: True
type: bool
timeout:
description:
- If waiting for the workflow to complete this will abort after this
amount of seconds
requirements:
- "python >= 2.6"
extends_documentation_fragment: tower
'''
RETURN = '''
tower_version:
description: The version of Tower we connected to
returned: If connection to Tower works
type: str
sample: '3.4.0'
job_info:
description: dictionary containing information about the workflow executed
returned: If workflow launched
type: dict
'''
EXAMPLES = '''
- name: Launch a workflow
tower_workflow_launch:
name: "Test Workflow"
delegate_to: localhost
run_once: true
register: workflow_results
- name: Launch a Workflow with parameters without waiting
tower_workflow_launch:
workflow_template: "Test workflow"
extra_vars: "---\nmy: var"
wait: False
delegate_to: localhost
run_once: true
register: workflow_task_info
'''
from ansible.module_utils.ansible_tower import TowerModule, tower_auth_config
try:
import tower_cli
from tower_cli.api import client
from tower_cli.conf import settings
from tower_cli.exceptions import ServerError, ConnectionError, BadRequest, TowerCLIError
except ImportError:
pass
def main():
argument_spec = dict(
workflow_template=dict(required=True),
extra_vars=dict(required=False),
wait=dict(required=False, default=True, type='bool'),
timeout=dict(required=False, default=None, type='int'),
)
module = TowerModule(
argument_spec=argument_spec,
supports_check_mode=True
)
workflow_template = module.params.get('workflow_template')
extra_vars = module.params.get('extra_vars')
wait = module.params.get('wait')
timeout = module.params.get('timeout')
# If we are going to use this result to return we can consider ourselfs changed
result = dict(
changed=False,
msg='initial message'
)
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
# First we will test the connection. This will be a test for both check and run mode
# Note, we are not using the tower_check_mode method here because we want to do more than just a ping test
# If we are in check mode we also want to validate that we can find the workflow
try:
ping_result = client.get('/ping').json()
# Stuff the version into the results as an FYI
result['tower_version'] = ping_result['version']
except(ServerError, ConnectionError, BadRequest) as excinfo:
result['msg'] = "Failed to reach Tower: {0}".format(excinfo)
module.fail_json(**result)
# Now that we know we can connect, lets verify that we can resolve the workflow_template
try:
workflow = tower_cli.get_resource("workflow").get(**{'name': workflow_template})
except TowerCLIError as e:
result['msg'] = "Failed to find workflow: {0}".format(e)
module.fail_json(**result)
# Since we were able to find the workflow, if we are in check mode we can return now
if module.check_mode:
result['msg'] = "Check mode passed"
module.exit_json(**result)
# We are no ready to run the workflow
try:
result['job_info'] = tower_cli.get_resource('workflow_job').launch(
workflow_job_template=workflow['id'],
monitor=False,
wait=wait,
timeout=timeout,
extra_vars=extra_vars
)
if wait:
# If we were waiting for a result we will fail if the workflow failed
if result['job_info']['failed']:
result['msg'] = "Workflow execution failed"
module.fail_json(**result)
else:
module.exit_json(**result)
# We were not waiting and there should be no way we can make it here without the workflow fired off so we can return a success
module.exit_json(**result)
except TowerCLIError as e:
result['msg'] = "Failed to execute workflow: {0}".format(e)
module.fail_json(**result)
if __name__ == '__main__':
main()

@ -1,203 +0,0 @@
#!/usr/bin/python
# coding: utf-8 -*-
# Copyright: (c) 2018, Adrien Fleury <fleu42@gmail.com>
# 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': ['preview'],
'supported_by': 'community',
'metadata_version': '1.1'}
DOCUMENTATION = '''
---
module: tower_workflow_template
author: "Adrien Fleury (@fleu42)"
version_added: "2.7"
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
ask_extra_vars:
description:
- Prompt user for (extra_vars) on launch.
type: bool
version_added: "2.9"
ask_inventory:
description:
- Prompt user for inventory on launch.
type: bool
version_added: "2.9"
description:
description:
- The description to use for the workflow.
extra_vars:
description:
- Extra variables used by Ansible in YAML or key=value format.
inventory:
description:
- Name of the inventory to use for the job template.
version_added: "2.9"
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 Workflow Template
organization: My optional Organization
schema: "{{ lookup('file', 'my_workflow.json') }}"
- tower_workflow_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
)
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(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),
inventory=dict(required=False),
ask_inventory=dict(type='bool', required=False),
ask_extra_vars=dict(type='bool', required=False),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerModule(
argument_spec=argument_spec,
supports_check_mode=False
)
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', 'extra_vars', 'inventory',
'survey_enabled', 'description'):
if module.params.get(key):
params[key] = module.params.get(key)
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'], 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()

@ -1,46 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2017, Wayne Witzel III <wayne@riotousliving.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
class ModuleDocFragment(object):
# Ansible Tower documentation fragment
DOCUMENTATION = r'''
options:
tower_host:
description:
- URL to your Tower instance.
type: str
tower_username:
description:
- Username for your Tower instance.
type: str
tower_password:
description:
- Password for your Tower instance.
type: str
validate_certs:
description:
- Whether to 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.
type: bool
aliases: [ tower_verify_ssl ]
tower_config_file:
description:
- Path to the Tower config file.
type: path
requirements:
- 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
'''

@ -1,221 +0,0 @@
# Copyright (c) 2018 Ansible Project
# 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 = '''
name: tower
plugin_type: inventory
author:
- Matthew Jones (@matburt)
- Yunfan Zhang (@YunfanZhang42)
short_description: Ansible dynamic inventory plugin for Ansible Tower.
version_added: "2.7"
description:
- Reads inventories from Ansible Tower.
- Supports reading configuration from both YAML config file and environment variables.
- If reading from the YAML file, the file name must end with tower.(yml|yaml) or tower_inventory.(yml|yaml),
the path in the command would be /path/to/tower_inventory.(yml|yaml). If some arguments in the config file
are missing, this plugin will try to fill in missing arguments by reading from environment variables.
- If reading configurations from environment variables, the path in the command must be @tower_inventory.
options:
plugin:
description: the name of this plugin, it should always be set to 'tower'
for this plugin to recognize it as it's own.
env:
- name: ANSIBLE_INVENTORY_ENABLED
required: True
choices: ['tower']
host:
description: The network address of your Ansible Tower host.
type: string
env:
- name: TOWER_HOST
required: True
username:
description: The user that you plan to use to access inventories on Ansible Tower.
type: string
env:
- name: TOWER_USERNAME
required: True
password:
description: The password for your Ansible Tower user.
type: string
env:
- name: TOWER_PASSWORD
required: True
inventory_id:
description:
- The ID of the Ansible Tower inventory that you wish to import.
- This is allowed to be either the inventory primary key or its named URL slug.
- Primary key values will be accepted as strings or integers, and URL slugs must be strings.
- Named URL slugs follow the syntax of "inventory_name++organization_name".
type: raw
env:
- name: TOWER_INVENTORY
required: True
validate_certs:
description: Specify whether Ansible should verify the SSL certificate of Ansible Tower host.
type: bool
default: True
env:
- name: TOWER_VERIFY_SSL
required: False
aliases: [ verify_ssl ]
include_metadata:
description: Make extra requests to provide all group vars with metadata about the source Ansible Tower host.
type: bool
default: False
version_added: "2.8"
'''
EXAMPLES = '''
# Before you execute the following commands, you should make sure this file is in your plugin path,
# and you enabled this plugin.
# Example for using tower_inventory.yml file
plugin: tower
host: your_ansible_tower_server_network_address
username: your_ansible_tower_username
password: your_ansible_tower_password
inventory_id: the_ID_of_targeted_ansible_tower_inventory
# Then you can run the following command.
# If some of the arguments are missing, Ansible will attempt to read them from environment variables.
# ansible-inventory -i /path/to/tower_inventory.yml --list
# Example for reading from environment variables:
# Set environment variables:
# export TOWER_HOST=YOUR_TOWER_HOST_ADDRESS
# export TOWER_USERNAME=YOUR_TOWER_USERNAME
# export TOWER_PASSWORD=YOUR_TOWER_PASSWORD
# export TOWER_INVENTORY=THE_ID_OF_TARGETED_INVENTORY
# Read the inventory specified in TOWER_INVENTORY from Ansible Tower, and list them.
# The inventory path must always be @tower_inventory if you are reading all settings from environment variables.
# ansible-inventory -i @tower_inventory --list
'''
import re
import os
import json
from ansible.module_utils import six
from ansible.module_utils.urls import Request, urllib_error, ConnectionError, socket, httplib
from ansible.module_utils._text import to_text, to_native
from ansible.errors import AnsibleParserError, AnsibleOptionsError
from ansible.plugins.inventory import BaseInventoryPlugin
from ansible.config.manager import ensure_type
# Python 2/3 Compatibility
try:
from urlparse import urljoin
except ImportError:
from urllib.parse import urljoin
class InventoryModule(BaseInventoryPlugin):
NAME = 'tower'
# Stays backward compatible with tower inventory script.
# If the user supplies '@tower_inventory' as path, the plugin will read from environment variables.
no_config_file_supplied = False
def make_request(self, request_handler, tower_url):
"""Makes the request to given URL, handles errors, returns JSON
"""
try:
response = request_handler.get(tower_url)
except (ConnectionError, urllib_error.URLError, socket.error, httplib.HTTPException) as e:
n_error_msg = 'Connection to remote host failed: {err}'.format(err=to_native(e))
# If Tower gives a readable error message, display that message to the user.
if callable(getattr(e, 'read', None)):
n_error_msg += ' with message: {err_msg}'.format(err_msg=to_native(e.read()))
raise AnsibleParserError(n_error_msg)
# Attempt to parse JSON.
try:
return json.loads(response.read())
except (ValueError, TypeError) as e:
# If the JSON parse fails, print the ValueError
raise AnsibleParserError('Failed to parse json from host: {err}'.format(err=to_native(e)))
def verify_file(self, path):
if path.endswith('@tower_inventory'):
self.no_config_file_supplied = True
return True
elif super(InventoryModule, self).verify_file(path):
return path.endswith(('tower_inventory.yml', 'tower_inventory.yaml', 'tower.yml', 'tower.yaml'))
else:
return False
def parse(self, inventory, loader, path, cache=True):
super(InventoryModule, self).parse(inventory, loader, path)
if not self.no_config_file_supplied and os.path.isfile(path):
self._read_config_data(path)
# Read inventory from tower server.
# Note the environment variables will be handled automatically by InventoryManager.
tower_host = self.get_option('host')
if not re.match('(?:http|https)://', tower_host):
tower_host = 'https://{tower_host}'.format(tower_host=tower_host)
request_handler = Request(url_username=self.get_option('username'),
url_password=self.get_option('password'),
force_basic_auth=True,
validate_certs=self.get_option('validate_certs'))
# validate type of inventory_id because we allow two types as special case
inventory_id = self.get_option('inventory_id')
if isinstance(inventory_id, int):
inventory_id = to_text(inventory_id, nonstring='simplerepr')
else:
try:
inventory_id = ensure_type(inventory_id, 'str')
except ValueError as e:
raise AnsibleOptionsError(
'Invalid type for configuration option inventory_id, '
'not integer, and cannot convert to string: {err}'.format(err=to_native(e))
)
inventory_id = inventory_id.replace('/', '')
inventory_url = '/api/v2/inventories/{inv_id}/script/?hostvars=1&towervars=1&all=1'.format(inv_id=inventory_id)
inventory_url = urljoin(tower_host, inventory_url)
inventory = self.make_request(request_handler, inventory_url)
# To start with, create all the groups.
for group_name in inventory:
if group_name != '_meta':
self.inventory.add_group(group_name)
# Then, create all hosts and add the host vars.
all_hosts = inventory['_meta']['hostvars']
for host_name, host_vars in six.iteritems(all_hosts):
self.inventory.add_host(host_name)
for var_name, var_value in six.iteritems(host_vars):
self.inventory.set_variable(host_name, var_name, var_value)
# Lastly, create to group-host and group-group relationships, and set group vars.
for group_name, group_content in six.iteritems(inventory):
if group_name != 'all' and group_name != '_meta':
# First add hosts to groups
for host_name in group_content.get('hosts', []):
self.inventory.add_host(host_name, group_name)
# Then add the parent-children group relationships.
for child_group_name in group_content.get('children', []):
self.inventory.add_child(group_name, child_group_name)
# Set the group vars. Note we should set group var for 'all', but not '_meta'.
if group_name != '_meta':
for var_name, var_value in six.iteritems(group_content.get('vars', {})):
self.inventory.set_variable(group_name, var_name, var_value)
# Fetch extra variables if told to do so
if self.get_option('include_metadata'):
config_url = urljoin(tower_host, '/api/v2/config/')
config_data = self.make_request(request_handler, config_url)
server_data = {}
server_data['license_type'] = config_data.get('license_info', {}).get('license_type', 'unknown')
for key in ('version', 'ansible_version'):
server_data[key] = config_data.get(key, 'unknown')
self.inventory.set_variable('all', 'tower_metadata', server_data)
# Clean up the inventory.
self.inventory.reconcile_inventory()

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,540 +0,0 @@
- name: create a tempdir for an SSH key
shell: mktemp -d
delegate_to: localhost
register: tempdir
- name: Generate a local SSH key
shell: "ssh-keygen -b 2048 -t rsa -f {{ tempdir.stdout }}/id_rsa -q -N 'passphrase'"
delegate_to: localhost
- name: Read the generated key
set_fact:
ssh_key_data: "{{ lookup('file', tempdir.stdout + '/id_rsa') }}"
- name: Create a User-specific credential
tower_credential:
name: SSH Credential
organization: Default
user: admin
state: present
kind: ssh
register: result
- assert:
that:
- "result is changed"
- name: Delete a User-specific credential
tower_credential:
name: SSH Credential
organization: Default
user: admin
state: absent
kind: ssh
register: result
- assert:
that:
- "result is changed"
- name: Create a valid SSH credential
tower_credential:
name: SSH Credential
organization: Default
state: present
kind: ssh
description: An example SSH credential
username: joe
password: secret
become_method: sudo
become_username: superuser
become_password: supersecret
ssh_key_data: "{{ ssh_key_data }}"
ssh_key_unlock: "passphrase"
register: result
- assert:
that:
- "result is changed"
- name: Create a valid SSH credential from lookup source
tower_credential:
name: SSH Credential from lookup source
organization: Default
state: present
kind: ssh
description: An example SSH credential from lookup source
username: joe
password: secret
become_method: sudo
become_username: superuser
become_password: supersecret
ssh_key_data: "{{ lookup('file', tempdir.stdout + '/id_rsa') }}"
ssh_key_unlock: "passphrase"
register: result
- assert:
that:
- "result is changed"
- name: Create a valid SSH credential from file source
tower_credential:
name: SSH Credential from file source
organization: Default
state: present
kind: ssh
description: An example SSH credential from file source
username: joe
password: secret
become_method: sudo
become_username: superuser
become_password: supersecret
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
ssh_key_unlock: "passphrase"
register: result
- assert:
that:
- "result is changed"
- "result is not failed"
- "'ssh_key_data should be a string, not a path to a file.' in result.deprecations[0].msg"
- name: Create an invalid SSH credential (passphrase required)
tower_credential:
name: SSH Credential
organization: Default
state: present
kind: ssh
username: joe
ssh_key_data: "{{ ssh_key_data }}"
ignore_errors: yes
register: result
- assert:
that:
- "result is failed"
- "'must be set when SSH key is encrypted' in result.msg"
- name: Create an invalid SSH credential (Organization not found)
tower_credential:
name: SSH Credential
organization: Missing Organization
state: present
kind: ssh
username: joe
ignore_errors: yes
register: result
- assert:
that:
- "result is failed"
- "'The requested object could not be found' in result.msg"
- name: Delete an SSH credential
tower_credential:
name: SSH Credential
organization: Default
state: absent
kind: ssh
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Vault credential
tower_credential:
name: Vault Credential
organization: Default
state: present
kind: vault
description: An example Vault credential
vault_password: secret-vault
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Vault credential w/ kind=ssh (deprecated)
tower_credential:
name: Vault Credential
organization: Default
state: present
kind: ssh
description: An example Vault credential
vault_password: secret-vault
register: result
- assert:
that:
- "result is changed"
- name: Delete a Vault credential
tower_credential:
name: Vault Credential
organization: Default
state: absent
kind: vault
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Network credential
tower_credential:
name: Network Credential
organization: Default
state: present
kind: net
username: joe
password: secret
authorize: true
authorize_password: authorize-me
register: result
- assert:
that:
- "result is changed"
- name: Delete a Network credential
tower_credential:
name: Network Credential
organization: Default
state: absent
kind: net
register: result
- assert:
that:
- "result is changed"
- name: Create a valid SCM credential
tower_credential:
name: SCM Credential
organization: Default
state: present
kind: scm
username: joe
password: secret
ssh_key_data: "{{ ssh_key_data }}"
ssh_key_unlock: "passphrase"
register: result
- assert:
that:
- "result is changed"
- name: Delete an SCM credential
tower_credential:
name: SCM Credential
organization: Default
state: absent
kind: scm
register: result
- assert:
that:
- "result is changed"
- name: Create a valid AWS credential
tower_credential:
name: AWS Credential
organization: Default
state: present
kind: aws
username: joe
password: secret
security_token: aws-token
register: result
- assert:
that:
- "result is changed"
- name: Delete an AWS credential
tower_credential:
name: AWS Credential
organization: Default
state: absent
kind: aws
register: result
- assert:
that:
- "result is changed"
- name: Create a valid VMware credential
tower_credential:
name: VMware Credential
organization: Default
state: present
kind: vmware
host: https://example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete an VMware credential
tower_credential:
name: VMware Credential
organization: Default
state: absent
kind: vmware
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Satellite6 credential
tower_credential:
name: Satellite6 Credential
organization: Default
state: present
kind: satellite6
host: https://example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete a Satellite6 credential
tower_credential:
name: Satellite6 Credential
organization: Default
state: absent
kind: satellite6
register: result
- assert:
that:
- "result is changed"
- name: Create a valid CloudForms credential
tower_credential:
name: CloudForms Credential
organization: Default
state: present
kind: cloudforms
host: https://example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete a CloudForms credential
tower_credential:
name: CloudForms Credential
organization: Default
state: absent
kind: cloudforms
register: result
- assert:
that:
- "result is changed"
- name: Create a valid GCE credential
tower_credential:
name: GCE Credential
organization: Default
state: present
kind: gce
username: joe
project: ABC123
ssh_key_data: "{{ ssh_key_data }}"
register: result
- assert:
that:
- "result is changed"
- name: Delete a GCE credential
tower_credential:
name: GCE Credential
organization: Default
state: absent
kind: gce
register: result
- assert:
that:
- "result is changed"
- name: Create a valid AzureRM credential
tower_credential:
name: AzureRM Credential
organization: Default
state: present
kind: azure_rm
username: joe
password: secret
subscription: some-subscription
register: result
- assert:
that:
- "result is changed"
- name: Create a valid AzureRM credential with a tenant
tower_credential:
name: AzureRM Credential
organization: Default
state: present
kind: azure_rm
client: some-client
secret: some-secret
tenant: some-tenant
subscription: some-subscription
register: result
- assert:
that:
- "result is changed"
- name: Delete an AzureRM credential
tower_credential:
name: AzureRM Credential
organization: Default
state: absent
kind: azure_rm
register: result
- assert:
that:
- "result is changed"
- name: Create a valid OpenStack credential
tower_credential:
name: OpenStack Credential
organization: Default
state: present
kind: openstack
host: https://keystone.example.org
username: joe
password: secret
project: tenant123
domain: some-domain
register: result
- assert:
that:
- "result is changed"
- name: Delete a OpenStack credential
tower_credential:
name: OpenStack Credential
organization: Default
state: absent
kind: openstack
register: result
- assert:
that:
- "result is changed"
- name: Create a valid RHV credential
tower_credential:
name: RHV Credential
organization: Default
state: present
kind: rhv
host: https://example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete an RHV credential
tower_credential:
name: RHV Credential
organization: Default
state: absent
kind: rhv
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Insights credential
tower_credential:
name: Insights Credential
organization: Default
state: present
kind: insights
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete an Insights credential
tower_credential:
name: Insights Credential
organization: Default
state: absent
kind: insights
register: result
- assert:
that:
- "result is changed"
- name: Create a valid Tower-to-Tower credential
tower_credential:
name: Tower Credential
organization: Default
state: present
kind: tower
host: https://tower.example.org
username: joe
password: secret
register: result
- assert:
that:
- "result is changed"
- name: Delete a Tower-to-Tower credential
tower_credential:
name: Tower Credential
organization: Default
state: absent
kind: tower
register: result
- assert:
that:
- "result is changed"
- name: Check module fails with correct msg
tower_credential:
name: test-credential
description: Credential Description
kind: ssh
organization: test-non-existing-org
state: present
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Failed to update credential, organization not found: The requested object could not be found.'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,23 +0,0 @@
---
- name: Add Tower credential type
tower_credential_type:
description: Credential type for Test
name: test-credential-type
kind: cloud
inputs: '{"fields": [{"type": "string", "id": "username", "label": "Username"}, {"secret": True, "type": "string", "id": "password", "label": "Password"}], "required": ["username", "password"]}'
injectors: '{"extra_vars": {"test": "foo"}}'
register: result
- assert:
that:
- "result is changed"
- name: Remove a Tower credential type
tower_credential_type:
name: test-credential-type
state: absent
register: result
- assert:
that:
- "result is changed"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,46 +0,0 @@
- name: create a tempdir for hostvars
shell: mktemp -d
register: tempdir
- name: write a file w/ hostvars
lineinfile:
dest: "{{ tempdir.stdout }}/vars"
line: '{"foo": "bar"}'
create: true
- name: Create a Group
tower_group:
name: Some Group
inventory: Demo Inventory
state: present
source: ec2
variables: "@{{ tempdir.stdout }}/vars"
register: result
- assert:
that:
- "result is changed"
- name: Delete a Group
tower_group:
name: Some Group
inventory: Demo Inventory
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Check module fails with correct msg
tower_group:
name: test-group
description: Group Description
inventory: test-non-existing-inventory
state: present
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Failed to update the group, inventory not found: The requested object could not be found.'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,45 +0,0 @@
- name: create a tempdir for hostvars
shell: mktemp -d
register: tempdir
- name: write a file w/ hostvars
lineinfile:
dest: "{{ tempdir.stdout }}/vars"
line: '{"foo": "bar"}'
create: true
- name: Create a Host
tower_host:
name: "some-host"
inventory: "Demo Inventory"
state: present
variables: "@{{ tempdir.stdout }}/vars"
register: result
- assert:
that:
- "result is changed"
- name: Delete a Host
tower_host:
name: "some-host"
inventory: "Demo Inventory"
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Check module fails with correct msg
tower_host:
name: test-host
description: Host Description
inventory: test-non-existing-inventory
state: present
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Failed to update host, inventory not found: The requested object could not be found.'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,34 +0,0 @@
- name: Create an Inventory
tower_inventory:
name: my-inventory
organization: Default
state: present
register: result
- assert:
that:
- "result is changed"
- name: Delete an Inventory
tower_inventory:
name: my-inventory
organization: Default
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Check module fails with correct msg
tower_inventory:
name: test-inventory
description: Inventory Description
organization: test-non-existing-org
state: present
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Failed to update inventory, organization not found: The requested object could not be found.'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,34 +0,0 @@
---
- name: Add a Tower credential
tower_credential:
description: Credentials for Openstack Test project
name: openstack-test-credential
kind: openstack
organization: Default
project: Test
username: admin
host: https://example.org:5000
password: passw0rd
domain: test
- name: Add a Tower inventory
tower_inventory:
description: Test inventory
name: openstack-test-inventory
organization: Default
- name: Create a source inventory
tower_inventory_source:
name: source-test-inventory
description: Source for Test inventory
inventory: openstack-test-inventory
credential: openstack-test-credential
overwrite: True
update_on_launch: True
source_vars: "---\nprivate: false"
source: openstack
register: result
- assert:
that:
- "result is changed"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,25 +0,0 @@
- name: Launch a Job Template
tower_job_launch:
job_template: "Demo Job Template"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: job
- assert:
that:
- "job is changed"
- "job.status == 'pending'"
- name: Cancel the job
tower_job_cancel:
job_id: "{{ job.id }}"
- name: Check module fails with correct msg
tower_job_cancel:
job_id: 9999999999
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Unable to cancel job_id/9999999999: The requested object could not be found.'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,58 +0,0 @@
- name: Launch a Job Template
tower_job_launch:
job_template: "Demo Job Template"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: result
- assert:
that:
- "result is changed"
- "result.status == 'pending'"
- name: Wait for a job template to complete
tower_job_wait:
job_id: "{{ result.id }}"
max_interval: 10
timeout: 120
register: result
- assert:
that:
- "result is not changed"
- "result.status == 'successful'"
- name: Check module fails with correct msg
tower_job_launch:
job_template: "Non Existing Job Template"
inventory: "Test Inventory"
credential: "Test Credential"
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Unable to launch job, job_template/Non Existing Job Template was not found: The requested object could not be found.'"
- name: Create a Job Template for testing prompt on launch
tower_job_template:
name: "Demo Job Template - ask inventory and credential"
project: Demo Project
playbook: hello_world.yml
job_type: run
ask_credential: yes
ask_inventory: yes
state: present
register: result
- name: Launch job template with inventory and credential for prompt on launch
tower_job_launch:
job_template: "Demo Job Template - ask inventory and credential"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: result
- assert:
that:
- "result is changed"
- "result.status == 'pending'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,20 +0,0 @@
- name: Launch a Job Template
tower_job_launch:
job_template: "Demo Job Template"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: job
- assert:
that:
- "job is changed"
- "job.status == 'pending'"
- name: List jobs w/ a matching primary key
tower_job_list:
query: {"id": "{{ job.id }}"}
register: matching_jobs
- assert:
that:
- "{{ matching_jobs.count }} == 1"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,54 +0,0 @@
- name: Create an SCM Credential
tower_credential:
name: SCM Credential for JT
organization: Default
kind: scm
- name: Create a Demo Project
tower_project:
name: Job Template Test Project
organization: Default
state: present
scm_type: git
scm_url: https://github.com/ansible/ansible-tower-samples.git
scm_credential: SCM Credential for JT
register: result
- name: Update the project (to clone the git repo)
uri:
url: "https://{{ tower_host }}/api/v2/projects/{{ result.id }}/update/"
method: POST
user: "{{ tower_username }}"
password: "{{ tower_password }}"
validate_certs: false
status_code: 202
force_basic_auth: true
- name: Wait for the project to be status=successful
uri:
url: "https://{{ tower_host }}/api/v2/projects/{{ result.id }}/"
method: GET
user: "{{ tower_username }}"
password: "{{ tower_password }}"
validate_certs: false
force_basic_auth: true
return_content: true
register: result
until: result.json.status == "successful"
retries: 60
delay: 1
- name: Create a Job Template
tower_job_template:
name: hello-world
project: Job Template Test Project
inventory: Demo Inventory
playbook: hello_world.yml
credential: Demo Credential
job_type: run
state: present
register: result
- assert:
that:
- "result is changed"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,26 +0,0 @@
- name: Launch a Job Template
tower_job_launch:
job_template: "Demo Job Template"
inventory: "Demo Inventory"
credential: "Demo Credential"
register: job
- assert:
that:
- "job is changed"
- "job.status == 'pending'"
- name: Wait for the Job to finish
tower_job_wait:
job_id: "{{ job.id }}"
timeout: 60
- name: Check module fails with correct msg
tower_job_wait:
job_id: "99999999"
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Unable to wait, no job_id 99999999 found: The requested object could not be found.'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,19 +0,0 @@
- name: Create a Label
tower_label:
name: important
organization: Default
state: present
- name: Check module fails with correct msg
tower_label:
name: "Test Label"
organization: "Non existing org"
state: present
register: result
ignore_errors: true
- assert:
that:
- "result.msg == 'Failed to update label, organization not found: The requested object could not be found.'"
# TODO: Deleting labels doesn't seem to work currently

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,191 +0,0 @@
- name: Create Slack notification
tower_notification:
name: notification1
notification_type: slack
token: a_token
channels:
- general
state: present
register: result
- assert:
that:
- result is changed
- name: Delete Slack notification
tower_notification:
name: notification1
notification_type: slack
state: absent
register: result
- assert:
that:
- result is changed
- name: Add webhook notification
tower_notification:
name: notification2
notification_type: webhook
url: http://www.example.com/hook
headers:
X-Custom-Header: value123
state: present
register: result
- assert:
that:
- result is changed
- name: Delete webhook notification
tower_notification:
name: notification2
notification_type: webhook
state: absent
register: result
- assert:
that:
- result is changed
- name: Add email notification
tower_notification:
name: notification3
notification_type: email
username: user
password: s3cr3t
sender: tower@example.com
recipients:
- user1@example.com
host: smtp.example.com
port: 25
use_tls: no
use_ssl: no
state: present
register: result
- assert:
that:
- result is changed
- name: Delete email notification
tower_notification:
name: notification3
notification_type: email
state: absent
register: result
- assert:
that:
- result is changed
- name: Add twilio notification
tower_notification:
name: notification4
notification_type: twilio
account_token: a_token
account_sid: a_sid
from_number: '+15551112222'
to_numbers:
- '+15553334444'
state: present
register: result
- assert:
that:
- result is changed
- name: Delete twilio notification
tower_notification:
name: notification4
notification_type: twilio
state: absent
register: result
- assert:
that:
- result is changed
- name: Add PagerDuty notification
tower_notification:
name: notification5
notification_type: pagerduty
token: a_token
subdomain: sub
client_name: client
service_key: a_key
state: present
register: result
- assert:
that:
- result is changed
- name: Delete PagerDuty notification
tower_notification:
name: notification5
notification_type: pagerduty
state: absent
register: result
- assert:
that:
- result is changed
- name: Add HipChat notification
tower_notification:
name: notification6
notification_type: hipchat
token: a_token
message_from: user1
api_url: https://hipchat.example.com
color: red
rooms:
- room-A
notify: yes
state: present
register: result
- assert:
that:
- result is changed
- name: Delete HipChat notification
tower_notification:
name: notification6
notification_type: hipchat
state: absent
register: result
- assert:
that:
- result is changed
- name: Add IRC notification
tower_notification:
name: notification7
notification_type: irc
nickname: tower
password: s3cr3t
targets:
- user1
port: 8080
server: irc.example.com
use_ssl: no
state: present
register: result
- assert:
that:
- result is changed
- name: Delete IRC notification
tower_notification:
name: notification7
notification_type: irc
state: absent
register: result
- assert:
that:
- result is changed

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,44 +0,0 @@
- name: confirm Tower version w/ check mode
tower_organization:
name: Default
check_mode: yes
register: result
- assert:
that:
- "result.tower_version == '{{ tower_version }}'"
- name: Make sure the default Default organization exists
tower_organization:
name: Default
- name: Check that SSL is available
tower_organization:
name: Default
register: result
- name: Check we haven't changed anything
assert:
that: result is not changed
- name: Check that SSL is available and verify_ssl is enabled (task must fail)
tower_organization:
name: Default
environment:
TOWER_CERTIFICATE: /dev/null # force check failure
ignore_errors: true
register: check_ssl_is_used
- name: Disable verify_ssl in ~/.tower_cli.cfg
copy:
dest: ~/.tower_cli.cfg
content: |
[general]
verify_ssl = False
force: false # ensure remote file doesn't exist
- name: Check that verify_ssl is disabled (task must not fail)
tower_organization:
name: Default
environment:
TOWER_CERTIFICATE: /dev/null # should not fail because verify_ssl is disabled

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,45 +0,0 @@
- name: Fetch project_base_dir
uri:
url: "https://{{ tower_host}}/api/v2/config/"
user: "{{ tower_username }}"
password: "{{ tower_password }}"
validate_certs: false
return_content: true
force_basic_auth: true
register: awx_config
- tower_inventory:
name: localhost
organization: Default
- tower_host:
name: localhost
inventory: localhost
variables:
ansible_connection: local
- name: create an unused SSH / Machine credential
tower_credential:
name: dummy
kind: ssh
ssh_key_data: |
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIUl6R1xgzR6siIUArz4XBPtGZ09aetma2eWf1v3uYymoAoGCCqGSM49
AwEHoUQDQgAENJNjgeZDAh/+BY860s0yqrLDprXJflY0GvHIr7lX3ieCtrzOMCVU
QWzw35pc5tvuP34SSi0ZE1E+7cVMDDOF3w==
-----END EC PRIVATE KEY-----
organization: Default
- name: Disable bubblewrap
command: tower-cli setting modify AWX_PROOT_ENABLED false
- block:
- name: Create a directory for manual project
vars:
project_base_dir: "{{ awx_config.json.project_base_dir }}"
command: tower-cli ad_hoc launch --monitor --inventory localhost
--credential dummy --module-name command
--module-args "mkdir {{ project_base_dir }}/manual_test_project"
always:
- name: enable bubblewrap
command: tower-cli setting modify AWX_PROOT_ENABLED true

@ -1,106 +0,0 @@
- name: Create an SCM Credential
tower_credential:
name: SCM Credential for Project
organization: Default
kind: scm
- name: Create a Project
tower_project:
name: my-project
organization: Default
state: present
scm_credential: SCM Credential for Project
register: result
- assert:
that:
- "result is changed"
- name: Delete a Project
tower_project:
name: my-project
state: absent
register: result
- assert:
that:
- "result is changed"
- name: create a project directory for manual project
import_tasks: create_project_dir.yml
- name: Create a manual project
tower_project:
name: manual project
organization: Default
scm_type: manual
local_path: "manual_test_project"
register: result
- assert:
that:
- "result is changed"
- name: Create a git project without credentials
tower_project:
name: git project
organization: Default
scm_type: git
scm_url: https://github.com/ansible/ansible
- name: "Create {{ item }}"
tower_organization:
name: "{{ item }}"
loop:
- TestOrg1
- TestOrg2
- name: "Create credential"
tower_credential:
kind: scm
name: TestCred1
organization: "{{ item }}"
loop:
- TestOrg2
- TestOrg1
- name: Create project TestProject
tower_project:
name: TestProject
organization: TestOrg1
scm_type: git
scm_url: "https://github.com/ansible/ansible"
scm_credential: TestCred1
register: multi_org_cred_project
- assert:
that:
- "multi_org_cred_project is changed"
- name: Check module fails with correct msg
tower_project:
name: TestProject
organization: Non Existing Org
scm_type: git
scm_url: "https://github.com/ansible/ansible"
scm_credential: TestCred1
register: result
ignore_errors: true
- assert:
that:
- "result.msg == 'Failed to update project, organization not found: Non Existing Org'"
- name: Check module fails with correct msg
tower_project:
name: TestProject
organization: TestOrg1
scm_type: git
scm_url: "https://github.com/ansible/ansible"
scm_credential: Non Existing Credential
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Failed to update project, credential not found: Non Existing Credential'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,17 +0,0 @@
- name: Export all Tower assets
tower_receive:
all: True
register: result
- assert:
that:
- "result is successful"
- name: Extract names from output
set_fact:
object_names: "{{ result.assets | map(attribute='name') | list }}"
- assert:
that:
- "result is successful"
- "'Default' in object_names"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,39 +0,0 @@
- name: Create a User
tower_user:
first_name: Joe
last_name: User
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
register: result
- assert:
that:
- "result is changed"
- name: Add Joe to the update role of the default Project
tower_role:
user: joe
role: update
project: Demo Project
state: "{{ item }}"
register: result
with_items:
- "present"
- "absent"
- assert:
that:
- "result is changed"
- name: Delete a User
tower_user:
username: joe
email: joe@example.org
state: absent
register: result
- assert:
that:
- "result is changed"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,75 +0,0 @@
- name: Test no parameters
tower_send:
register: result
ignore_errors: yes
- assert:
that:
- "result is failed"
- name: Create user json
set_fact:
user:
- username: "jowestco"
first_name: "John"
last_name: "Westcott"
asset_type: "user"
email: "john.westcott.iv@redhat.com"
- name: Test a new import of asset
tower_send:
assets: "{{ user | to_json() }}"
register: result
- assert:
that:
- "result is changed"
- name: Test an existing import of asset
tower_send:
assets: "{{ user | to_json() }}"
register: result
- assert:
that:
- "result is successful"
- "result is not changed"
- name: Change an existing asset
tower_send:
assets: "{{ user | combine({'last_name': 'Westcott IV'}) | to_json() }}"
register: result
- assert:
that:
- "result is changed"
- name: Create organization json
set_fact:
organization:
- asset_type: organization
name: "Red Hat"
- name: Create temp file
tempfile:
state: file
register: my_temp_file
- name: Drop down a file to import
copy:
dest: "{{ my_temp_file.path }}"
content: "{{ organization | to_nice_json() }}"
- name: Create org via files
tower_send:
files: "{{ my_temp_file.path }}"
register: result
- assert:
that:
- "result is changed"
- name: Remove Temp File
file:
path: "{{ my_temp_file.path }}"
state: absent

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,19 +0,0 @@
- name: Set the value of AWX_PROOT_SHOW_PATHS
tower_settings:
name: "AWX_PROOT_SHOW_PATHS"
value: "'/var/lib/awx/projects/', '/tmp'"
register: result
- assert:
that:
- "result is changed"
- name: Set the value of AWX_PROOT_BASE_PATH
tower_settings:
name: AWX_PROOT_BASE_PATH
value: "/tmp"
register: result
- assert:
that:
- "result.value == '/tmp'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,45 +0,0 @@
- name: Attempt to add a Tower team to a non-existant Organization
tower_team:
name: Test Team
organization: Missing Organization
state: present
register: result
ignore_errors: yes
- name: Assert a meaningful error was provided for the failed Tower team creation
assert:
that:
- "'The requested object could not be found.' in result.msg"
- name: Create a Tower team
tower_team:
name: Test Team
organization: Default
register: result
- assert:
that:
- "result is changed"
- name: Delete a Tower team
tower_team:
name: Test Team
organization: Default
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Check module fails with correct msg
tower_team:
name: Test Team
organization: Non Existing Org
state: present
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Failed to update team, organization not found: The requested object could not be found.'"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,93 +0,0 @@
- name: Create a User
tower_user:
first_name: Joe
last_name: User
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
register: result
- assert:
that:
- "result is changed"
- name: Delete a User
tower_user:
username: joe
email: joe@example.org
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Create an Auditor
tower_user:
first_name: Joe
last_name: Auditor
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
auditor: true
register: result
- assert:
that:
- "result is changed"
- name: Delete an Auditor
tower_user:
username: joe
email: joe@example.org
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Create a Superuser
tower_user:
first_name: Joe
last_name: Super
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
superuser: true
register: result
- assert:
that:
- "result is changed"
- name: Delete a Superuser
tower_user:
username: joe
email: joe@example.org
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Test tower SSL parameter
tower_user:
first_name: Joe
last_name: User
username: joe
password: "{{ 65535 | random | to_uuid }}"
email: joe@example.org
state: present
validate_certs: true
tower_host: http://foo.invalid
ignore_errors: true
register: result
- assert:
that:
- "'not verify ssl with non-https protocol' in (result.module_stdout + result.module_stderr)"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,46 +0,0 @@
[
{
"asset_relation": {
"workflow_nodes": [
{
"name": "node0",
"unified_job_type": "job",
"success_nodes": [
"node1"
],
"failure_nodes": [],
"unified_job_name": "Demo Job Template",
"always_nodes": []
},
{
"name": "node1",
"unified_job_type": "job",
"success_nodes": [],
"failure_nodes": [],
"unified_job_name": "Demo Job Template",
"always_nodes": []
}
],
"roles": [
{
"team": [],
"name": "Execute",
"user": []
},
{
"team": [],
"name": "Admin",
"user": []
},
{
"team": [],
"name": "Read",
"user": []
}
],
"survey_spec": {}
},
"asset_type": "workflow",
"name": "Success Workflow"
},
]

@ -1,83 +0,0 @@
- name: Get unified job template ID for Demo Job Template"
uri:
url: "https://{{ tower_host }}/api/v2/unified_job_templates/?name=Demo+Job+Template"
method: GET
password: "{{ tower_password }}"
user: "{{ tower_username }}"
validate_certs: False
force_basic_auth: true
register: unified_job
- name: Build workflow
uri:
url: "https://{{ tower_host }}/api/v2/workflow_job_templates/"
body:
name: "Success Template"
variables: "---"
extra_vars: ""
body_format: 'json'
method: 'POST'
password: "{{ tower_password }}"
status_code: 201
user: "{{ tower_username }}"
validate_certs: False
force_basic_auth: true
register: workflow
- name: Add a node
uri:
url: "https://{{ tower_host }}/api/v2/workflow_job_templates/{{ workflow.json.id }}/workflow_nodes/"
body:
credential: null
diff_mode: null
extra_data: {}
inventory: null
job_tags: null
job_type: null
limit: null
skip_tags: null
unified_job_template: "{{ unified_job.json.results[0].id }}"
verbosity: null
body_format: 'json'
method: 'POST'
password: "{{ tower_password }}"
status_code: 201
user: "{{ tower_username }}"
validate_certs: False
force_basic_auth: true
register: node1
- name: Add a node
uri:
url: "https://{{ tower_host }}/api/v2/workflow_job_templates/{{ workflow.json.id }}/workflow_nodes/"
body:
credential: null
diff_mode: null
extra_data: {}
inventory: null
job_tags: null
job_type: null
limit: null
skip_tags: null
unified_job_template: "{{ unified_job.json.results[0].id }}"
verbosity: null
body_format: 'json'
method: 'POST'
password: "{{ tower_password }}"
status_code: 201
user: "{{ tower_username }}"
validate_certs: False
force_basic_auth: true
register: node2
- name: "Link nodes {{ node2.json.id }} to {{ node1.json.id }}"
uri:
url: "https://{{ tower_host }}/api/v2/workflow_job_template_nodes/{{ node1.json.id }}/success_nodes/"
body: '{ "id": {{ node2.json.id }} }'
body_format: 'json'
method: 'POST'
password: "{{ tower_password }}"
status_code: 204
user: "{{ tower_username }}"
validate_certs: False
force_basic_auth: true

@ -1,99 +0,0 @@
- name: Run a workflow with no parameters
tower_workflow_launch:
validate_certs: False
ignore_errors: true
register: result1
- assert:
that:
- result1.failed
- "'missing required arguments' in result1.msg"
- name: Fail no connect to Tower server
tower_workflow_launch:
tower_host: 127.0.0.1:22
validate_certs: False
workflow_template: "Here"
ignore_errors: True
register: result2
- assert:
that:
- result2.failed
- "'Failed to reach Tower' in result2.msg"
- name: Connect to Tower server but request an invalid workflow
tower_workflow_launch:
validate_certs: False
workflow_template: "Does Not Exist"
ignore_errors: true
register: result3
- assert:
that:
- result3.failed
- "'The requested object could not be found' in result3.msg"
- name: Connect to Tower in check_mode with a valid workflow name
tower_workflow_launch:
validate_certs: False
workflow_template: "Success Workflow"
check_mode: True
ignore_errors: true
register: result4
- assert:
that:
- not result4.failed
- "'Check mode passed' in result4.msg"
- name: Connect to Tower in check_mode with a valid workflow id
tower_workflow_launch:
validate_certs: False
workflow_template: 9999999
check_mode: True
ignore_errors: true
register: result5
- assert:
that:
- result5.failed
- "'The requested object could not be found' in result5.msg"
- name: Run the workflow without waiting (this should just give us back a job ID)
tower_workflow_launch:
validate_certs: False
workflow_template: "Success Workflow"
wait: False
ignore_errors: True
register: result6
- assert:
that:
- not result6.failed
- "'id' in result6['job_info']"
- name: Kick off a workflow and wait for it
tower_workflow_launch:
validate_certs: False
workflow_template: "Success Workflow"
ignore_errors: True
register: result7
- assert:
that:
- not result7.failed
- "'id' in result7['job_info']"
- name: Kick off a workflow and wait for it, but only for a second
tower_workflow_launch:
validate_certs: False
workflow_template: "Success Workflow"
timeout: 1
ignore_errors: True
register: result8
- assert:
that:
- result8.failed
- "'Monitoring aborted due to timeout' in result8.msg"

@ -1,2 +0,0 @@
cloud/tower
shippable/tower/group1

@ -1,105 +0,0 @@
---
- name: Create an SCM Credential
tower_credential:
name: SCM Credential for JT
organization: Default
kind: scm
- name: Create a Demo Project
tower_project:
name: Job Template Test Project
organization: Default
state: present
scm_type: git
scm_url: https://github.com/ansible/ansible-tower-samples.git
scm_credential: SCM Credential for JT
register: result
- name: Update the project (to clone the git repo)
uri:
url: "https://{{ tower_host }}/api/v2/projects/{{ result.id }}/update/"
method: POST
user: "{{ tower_username }}"
password: "{{ tower_password }}"
validate_certs: false
status_code: 202
force_basic_auth: true
- name: Wait for the project to be status=successful
uri:
url: "https://{{ tower_host }}/api/v2/projects/{{ result.id }}/"
method: GET
user: "{{ tower_username }}"
password: "{{ tower_password }}"
validate_certs: false
force_basic_auth: true
return_content: true
register: result
until: result.json.status == "successful"
retries: 60
delay: 1
- name: Create a Job Template
tower_job_template:
name: my-job-1
project: Job Template Test Project
inventory: Demo Inventory
playbook: hello_world.yml
credential: Demo Credential
job_type: run
state: present
- name: Create a second Job Template
tower_job_template:
name: my-job-2
project: Job Template Test Project
inventory: Demo Inventory
playbook: hello_world.yml
credential: Demo Credential
job_type: run
state: present
- name: Add a Survey to second Job Template
tower_job_template:
name: my-job-2
project: Job Template Test Project
inventory: Demo Inventory
playbook: hello_world.yml
credential: Demo Credential
job_type: run
state: present
survey_enabled: yes
survey_spec: '{"spec": [{"index": 0, "question_name": "my question?", "default": "mydef", "variable": "myvar", "type": "text", "required": false}], "description": "test", "name": "test"}'
- name: Create a workflow job template
tower_workflow_template:
name: my-workflow
schema: '[{"success": [{"job_template": "my-job-1"}], "job_template": "my-job-2"}]'
register: result
- assert:
that:
- "result is changed"
- name: Delete a workflow job template
tower_workflow_template:
name: my-workflow
state: absent
register: result
- assert:
that:
- "result is changed"
- name: Check module fails with correct msg
tower_workflow_template:
name: my-workflow
organization: Non Existing Organization
schema: '[{"success": [{"job_template": "my-job-1"}], "job_template": "my-job-2"}]'
register: result
ignore_errors: true
- assert:
that:
- "result.msg =='Failed to update organization source,organization not found: The requested object could not be found.'"

@ -55,8 +55,6 @@ lib/ansible/executor/powershell/exec_wrapper.ps1 pslint:PSCustomUseLiteralPath
lib/ansible/executor/task_queue_manager.py pylint:blacklisted-name
lib/ansible/module_utils/_text.py future-import-boilerplate
lib/ansible/module_utils/_text.py metaclass-boilerplate
lib/ansible/module_utils/ansible_tower.py future-import-boilerplate
lib/ansible/module_utils/ansible_tower.py metaclass-boilerplate
lib/ansible/module_utils/api.py future-import-boilerplate
lib/ansible/module_utils/api.py metaclass-boilerplate
lib/ansible/module_utils/azure_rm_common.py future-import-boilerplate
@ -1634,53 +1632,6 @@ lib/ansible/modules/utilities/logic/async_wrapper.py ansible-doc!skip # not an
lib/ansible/modules/utilities/logic/async_wrapper.py pylint:ansible-bad-function
lib/ansible/modules/utilities/logic/async_wrapper.py use-argspec-type-path
lib/ansible/modules/utilities/logic/wait_for.py validate-modules:parameter-list-no-elements
lib/ansible/modules/web_infrastructure/ansible_tower/tower_credential.py validate-modules:doc-choices-do-not-match-spec
lib/ansible/modules/web_infrastructure/ansible_tower/tower_credential.py validate-modules:invalid-ansiblemodule-schema
lib/ansible/modules/web_infrastructure/ansible_tower/tower_credential_type.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_credential_type.py validate-modules:invalid-ansiblemodule-schema
lib/ansible/modules/web_infrastructure/ansible_tower/tower_credential_type.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_group.py use-argspec-type-path
lib/ansible/modules/web_infrastructure/ansible_tower/tower_group.py validate-modules:doc-default-does-not-match-spec
lib/ansible/modules/web_infrastructure/ansible_tower/tower_group.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_host.py use-argspec-type-path
lib/ansible/modules/web_infrastructure/ansible_tower/tower_host.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_inventory.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_inventory_source.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_inventory_source.py validate-modules:invalid-ansiblemodule-schema
lib/ansible/modules/web_infrastructure/ansible_tower/tower_inventory_source.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_cancel.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_launch.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_launch.py validate-modules:nonexistent-parameter-documented
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_launch.py validate-modules:parameter-list-no-elements
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_launch.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_list.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_list.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_template.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_template.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_template.py validate-modules:undocumented-parameter
lib/ansible/modules/web_infrastructure/ansible_tower/tower_job_wait.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_label.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_notification.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_notification.py validate-modules:parameter-list-no-elements
lib/ansible/modules/web_infrastructure/ansible_tower/tower_notification.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_organization.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_project.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_project.py validate-modules:doc-required-mismatch
lib/ansible/modules/web_infrastructure/ansible_tower/tower_project.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_receive.py validate-modules:parameter-list-no-elements
lib/ansible/modules/web_infrastructure/ansible_tower/tower_receive.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_role.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_role.py validate-modules:doc-required-mismatch
lib/ansible/modules/web_infrastructure/ansible_tower/tower_send.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_send.py validate-modules:parameter-list-no-elements
lib/ansible/modules/web_infrastructure/ansible_tower/tower_send.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_settings.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_team.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_team.py validate-modules:undocumented-parameter
lib/ansible/modules/web_infrastructure/ansible_tower/tower_user.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_workflow_launch.py validate-modules:doc-missing-type
lib/ansible/modules/web_infrastructure/ansible_tower/tower_workflow_launch.py validate-modules:parameter-type-not-in-doc
lib/ansible/modules/web_infrastructure/ansible_tower/tower_workflow_template.py validate-modules:doc-missing-type
lib/ansible/parsing/vault/__init__.py pylint:blacklisted-name
lib/ansible/playbook/base.py pylint:blacklisted-name
lib/ansible/playbook/collectionsearch.py required-and-default-attributes # https://github.com/ansible/ansible/issues/61460
@ -1728,8 +1679,6 @@ lib/ansible/plugins/doc_fragments/shell_windows.py future-import-boilerplate
lib/ansible/plugins/doc_fragments/shell_windows.py metaclass-boilerplate
lib/ansible/plugins/doc_fragments/skydive.py future-import-boilerplate
lib/ansible/plugins/doc_fragments/skydive.py metaclass-boilerplate
lib/ansible/plugins/doc_fragments/tower.py future-import-boilerplate
lib/ansible/plugins/doc_fragments/tower.py metaclass-boilerplate
lib/ansible/plugins/doc_fragments/url.py future-import-boilerplate
lib/ansible/plugins/doc_fragments/url.py metaclass-boilerplate
lib/ansible/plugins/doc_fragments/validate.py future-import-boilerplate

Loading…
Cancel
Save