Merge pull request #9980 from fosterseth/fix_t4958_rename_collection

Rename awx_collection modules
This commit is contained in:
Shane McDonald
2021-06-08 15:12:04 -04:00
committed by GitHub
137 changed files with 1784 additions and 2327 deletions

View File

@@ -8,7 +8,7 @@ short_description: gather all maintenance plan playbooks for an insights account
description: description:
- Supply insights Credentials to download all playbooks for all maintenance plans. - Supply insights Credentials to download all playbooks for all maintenance plans.
The totality of the plans are versioned based on the http ETag response. The totality of the plans are versioned based on the http ETag response.
version_added: "2.3" version_added: "2.3.0"
options: options:
insights_url: insights_url:
description: description:

View File

@@ -9,7 +9,7 @@ description:
- Unpacks an archive that contains a project, in order to support handling versioned - Unpacks an archive that contains a project, in order to support handling versioned
artifacts from (for example) GitHub Releases or Artifactory builds. artifacts from (for example) GitHub Releases or Artifactory builds.
- Handles projects in the archive root, or in a single base directory of the archive. - Handles projects in the archive root, or in a single base directory of the archive.
version_added: "2.9" version_added: "2.9.0"
options: options:
src: src:
description: description:

View File

@@ -71,9 +71,8 @@ Notable releases of the `awx.awx` collection:
The following notes are changes that may require changes to playbooks: The following notes are changes that may require changes to playbooks:
- The module tower_notification was renamed tower_notification_template. In ansible >= 2.10 there is a seemless redirect. Ansible 2.9 does not respect the redirect.
- When a project is created, it will wait for the update/sync to finish by default; this can be turned off with the `wait` parameter, if desired. - When a project is created, it will wait for the update/sync to finish by default; this can be turned off with the `wait` parameter, if desired.
- When using the wait parameter with project update, if the project did not undergo a revision update, the result will be
'not changed'
- Creating a "scan" type job template is no longer supported. - Creating a "scan" type job template is no longer supported.
- Specifying a custom certificate via the `TOWER_CERTIFICATE` environment variable no longer works. - Specifying a custom certificate via the `TOWER_CERTIFICATE` environment variable no longer works.
- Type changes of variable fields: - Type changes of variable fields:
@@ -118,7 +117,7 @@ py.test awx_collection/test/awx/
## Running Integration Tests ## Running Integration Tests
The integration tests require a virtualenv with `ansible` >= 2.9 and `tower_cli`. The integration tests require a virtualenv with `ansible` >= 2.9 and `awxkit`.
The collection must first be installed, which can be done using `make install_collection`. The collection must first be installed, which can be done using `make install_collection`.
You also need a configuration file, as described in the running section. You also need a configuration file, as described in the running section.

View File

@@ -7,12 +7,13 @@ When trying to fix a bug, it is best to replicate its behavior within a test wit
## Unit Tests ## Unit Tests
The unit tests are stored in the `test/awx` directory and, where possible, test interactions between the collections modules and the AWX database. This is achieved by using a Python testing suite and having a mocked layer which emulates interactions with the Tower API. You do not need a server to run these unit tests. The depth of testing is not fixed and can change from module to module. The unit tests are stored in the `test/awx` directory and, where possible, test interactions between the collections modules and the AWX database. This is achieved by using a Python testing suite and having a mocked layer which emulates interactions with the API. You do not need a server to run these unit tests. The depth of testing is not fixed and can change from module to module.
Let's take a closer look at the `test_token.py` file (which tests the `tower_token` module): Let's take a closer look at the `test_token.py` file (which tests the `token` module):
``` ```
from __future__ import (absolute_import, division, print_function) from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
import pytest import pytest
@@ -27,15 +28,15 @@ def test_create_token(run_module, admin_user):
'description': 'barfoo', 'description': 'barfoo',
'state': 'present', 'state': 'present',
'scope': 'read', 'scope': 'read',
'tower_host': None, 'controller_host': None,
'tower_username': None, 'controller_username': None,
'tower_password': None, 'controller_password': None,
'validate_certs': None, 'validate_certs': None,
'tower_oauthtoken': None, 'controller_oauthtoken': None,
'tower_config_file': None, 'controller_config_file': None,
} }
result = run_module('tower_token', module_args, admin_user) result = run_module('token', module_args, admin_user)
assert result.get('changed'), result assert result.get('changed'), result
tokens = OAuth2AccessToken.objects.filter(description='barfoo') tokens = OAuth2AccessToken.objects.filter(description='barfoo')
@@ -43,7 +44,7 @@ def test_create_token(run_module, admin_user):
assert tokens[0].scope == 'read', 'Token was not given read access' assert tokens[0].scope == 'read', 'Token was not given read access'
``` ```
This test has a single test called `test_create_token`. It creates a `module_args` section which is what will be passed into our module. We then call `run_module`, asking it to run the `tower_token` module with the `module_args` we created and give us back the results. After that, we run an assertion to validate that our module did in fact report a change to the system. We will then use Python objects to look up the token that has a description of `barfoo` (which was in our arguments to the module). We want to validate that we only got back one token (the one we created) and that the scope of the token we created was read. This test has a single test called `test_create_token`. It creates a `module_args` section which is what will be passed into our module. We then call `run_module`, asking it to run the `token` module with the `module_args` we created and give us back the results. After that, we run an assertion to validate that our module did in fact report a change to the system. We will then use Python objects to look up the token that has a description of `barfoo` (which was in our arguments to the module). We want to validate that we only got back one token (the one we created) and that the scope of the token we created was read.
### Completion Test ### Completion Test
@@ -70,7 +71,7 @@ Inside the `/tests` directory, there are two folders:
In the `/sanity` folder are file directives for specific Ansible versions which contain information about which tests to skip for specific files. There are a number of reasons you may need to skip a sanity test. See the [`ansible-test` documentation](https://docs.ansible.com/ansible/latest/dev_guide/testing_running_locally.html) for more details about how and why you might want to skip a test. In the `/sanity` folder are file directives for specific Ansible versions which contain information about which tests to skip for specific files. There are a number of reasons you may need to skip a sanity test. See the [`ansible-test` documentation](https://docs.ansible.com/ansible/latest/dev_guide/testing_running_locally.html) for more details about how and why you might want to skip a test.
In the `integration/targets` folder you will see directories (which act as roles) for all of the different modules and plugins. When the collection is tested, an instance of Ansible Tower (or AWX) will be spun up and these roles will be applied to the target server to validate the functionality of the modules. Since these are really roles, each directory will contain a tasks folder under it with a `main.yml` file as an entry point. In the `integration/targets` folder you will see directories (which act as roles) for all of the different modules and plugins. When the collection is tested, an instance of Automation Platform Controller (or AWX) will be spun up and these roles will be applied to the target server to validate the functionality of the modules. Since these are really roles, each directory will contain a tasks folder under it with a `main.yml` file as an entry point.
While not strictly followed, the general flow of a test should be: While not strictly followed, the general flow of a test should be:
@@ -87,17 +88,17 @@ While not strictly followed, the general flow of a test should be:
``` ```
- name: Generate names - name: Generate names
set_fact: set_fact:
group_name1: "AWX-Collection-tests-tower_instance_group-group1-{{ test_id }}" group_name1: "AWX-Collection-tests-instance_group-group1-{{ test_id }}"
group_name2: "AWX-Collection-tests-tower_instance_group-group2-{{ test_id }}" group_name2: "AWX-Collection-tests-instance_group-group2-{{ test_id }}"
cred_name1: "AWX-Collection-tests-tower_instance_group-cred1-{{ test_id }}" cred_name1: "AWX-Collection-tests-instance_group-cred1-{{ test_id }}"
``` ```
- **Non-creating tests (i.e. test for specific error conditions, etc), with assertion** - **Non-creating tests (i.e. test for specific error conditions, etc), with assertion**
``` ```
- name: Try to use a token as a dict which is missing the token parameter - name: Try to use a token as a dict which is missing the token parameter
tower_job_list: job_list:
tower_oauthtoken: controller_oauthtoken:
not_token: "This has no token entry" not_token: "This has no token entry"
register: results register: results
ignore_errors: true ignore_errors: true
@@ -105,14 +106,14 @@ While not strictly followed, the general flow of a test should be:
- assert: - assert:
that: that:
- results is failed - results is failed
- '"The provided dict in tower_oauthtoken did not properly contain the token entry" == results.msg' - '"The provided dict in controller_oauthtoken did not properly contain the token entry" == results.msg'
``` ```
- **`Block:`** - **`Block:`**
- Run test which creates/modifies/deletes object(s) - Run test which creates/modifies/deletes object(s)
``` ```
- name: Create a container group - name: Create a container group
tower_instance_group: instance_group:
name: "{{ group_name2 }}" name: "{{ group_name2 }}"
credential: "{{ cred_result.id }}" credential: "{{ cred_result.id }}"
register: result register: result
@@ -128,14 +129,14 @@ While not strictly followed, the general flow of a test should be:
- Cleanup created objects - Cleanup created objects
``` ```
- name: Delete the credential - name: Delete the credential
tower_credential: credential:
name: "{{ cred_name1 }}" name: "{{ cred_name1 }}"
organization: "Default" organization: "Default"
credential_type: "OpenShift or Kubernetes API Bearer Token" credential_type: "OpenShift or Kubernetes API Bearer Token"
``` ```
- Assert cleanup worked properly (if needed) - Assert cleanup worked properly (if needed)
When writing an integration test, a test of asset type A does not need to make assertions for asset type B. For example, if you are writing an integration test for a credential and you create a custom credential type, you do not need to assert that the `tower_credential_type` call properly worked, you can assume it will. In addition, when cleaning up and deleting the `tower_credential_type`, you do not need to assert that it properly deleted the credential type. When writing an integration test, a test of asset type A does not need to make assertions for asset type B. For example, if you are writing an integration test for a credential and you create a custom credential type, you do not need to assert that the `credential_type` call properly worked, you can assume it will. In addition, when cleaning up and deleting the `credential_type`, you do not need to assert that it properly deleted the credential type.
## Running Unit Tests ## Running Unit Tests
@@ -176,7 +177,7 @@ FAILED awx_collection/test/awx/test_module_utils.py::test_type_warning - SystemE
make: *** [Makefile:382: test_collection] Error 1 make: *** [Makefile:382: test_collection] Error 1
``` ```
In addition to running all of the tests, you can also specify specific tests to run. This is useful when developing a single module. In this example, we will run the tests for the `tower_token` module: In addition to running all of the tests, you can also specify specific tests to run. This is useful when developing a single module. In this example, we will run the tests for the `token` module:
``` ```
$ pytest awx_collection/test/awx/test_token.py $ pytest awx_collection/test/awx/test_token.py
@@ -195,7 +196,7 @@ awx_collection/test/awx/test_token.py . [100%]
## Running Integration Tests ## Running Integration Tests
For integration tests, you will need an existing AWX or Ansible Tower instance to run the test playbooks against. You can write a simple `run_it.yml` playbook to invoke the main method: For integration tests, you will need an existing AWX or Automation Platform Controller instance to run the test playbooks against. You can write a simple `run_it.yml` playbook to invoke the main method:
``` ```
--- ---
@@ -215,7 +216,7 @@ For integration tests, you will need an existing AWX or Ansible Tower instance t
- include_tasks: main.yml - include_tasks: main.yml
``` ```
Place this file in the `/tasks` directory of the test playbook you'd like to run (i.e., `awx/awx_collection/tests/integration/targets/tower_ad_hoc_command_cancel/tasks/`; a test playbook named `main.yml` must be in the same directory). Place this file in the `/tasks` directory of the test playbook you'd like to run (i.e., `awx/awx_collection/tests/integration/targets/ad_hoc_command_cancel/tasks/`; a test playbook named `main.yml` must be in the same directory).
The `run_it.yml` playbook will set up your connection parameters via environment variables and then invoke the `main.yml` play of the role. The `run_it.yml` playbook will set up your connection parameters via environment variables and then invoke the `main.yml` play of the role.

View File

@@ -13,7 +13,7 @@
authors: authors:
- AWX Project Contributors <awx-project@googlegroups.com> - AWX Project Contributors <awx-project@googlegroups.com>
dependencies: {} dependencies: {}
description: Ansible content that interacts with the AWX or Ansible Tower API. description: Ansible content that interacts with the AWX or Automation Platform Controller API.
documentation: https://github.com/ansible/awx/blob/devel/awx_collection/README.md documentation: https://github.com/ansible/awx/blob/devel/awx_collection/README.md
homepage: https://www.ansible.com/ homepage: https://www.ansible.com/
issues: https://github.com/ansible/awx/issues?q=is%3Aissue+label%3Acomponent%3Aawx_collection issues: https://github.com/ansible/awx/issues?q=is%3Aissue+label%3Acomponent%3Aawx_collection

View File

@@ -1,46 +1,207 @@
--- ---
action_groups: action_groups:
tower: controller:
- tower_credential_input_source - credential_input_source
- tower_credential - credential
- tower_credential_type - credential_type
- tower_group - group
- tower_host - host
- tower_inventory - inventory
- tower_inventory_source - inventory_source
- tower_job_cancel - job_cancel
- tower_job_launch - job_launch
- tower_job_list - job_list
- tower_job_template - job_template
- tower_job_wait - job_wait
- tower_label - label
- tower_license - license
- tower_notification - notification
- tower_organization - organization
- tower_project - project
- tower_role - role
- tower_schedule - schedule
- tower_settings - settings
- tower_team - team
- tower_token - token
- tower_user - user
- tower_workflow_job_template_node - workflow_job_template_node
- tower_workflow_job_template - workflow_job_template
- tower_workflow_launch - workflow_launch
plugin_routing: plugin_routing:
inventory:
tower:
redirect: awx.awx.controller
awx.awx.tower:
redirect: awx.awx.controller
lookup:
tower_api:
redirect: awx.awx.controller_api
tower_schedule_rrule:
redirect: awx.awx.schedule_rrule
awx.awx.tower_api:
redirect: awx.awx.controller_api
awx.awx.tower_schedule_rrule:
redirect: awx.awx.tower_schedule_rrule
modules: modules:
tower_receive: # if playbook does not specify a FQCN
deprecation: tower_ad_hoc_command_cancel:
removal_date: TBD redirect: awx.awx.ad_hoc_command_cancel
warning_text: see plugin documentation for details tower_ad_hoc_command_wait:
tower_send: redirect: awx.awx.ad_hoc_command_wait
deprecation: tower_ad_hoc_command:
removal_date: TBD redirect: awx.awx.ad_hoc_command
warning_text: see plugin documentation for details tower_application:
tower_workflow_template: redirect: awx.awx.application
deprecation: tower_meta:
removal_date: TBD redirect: awx.awx.controller_meta
warning_text: see plugin documentation for details tower_credential_input_source:
redirect: awx.awx.credential_input_source
tower_credential_type:
redirect: awx.awx.credential_type
tower_credential:
redirect: awx.awx.credential
tower_execution_environment:
redirect: awx.awx.execution_environment
tower_export:
redirect: awx.awx.export
tower_group:
redirect: awx.awx.group
tower_host:
redirect: awx.awx.host
tower_import:
redirect: awx.awx.import
tower_instance_group:
redirect: awx.awx.instance_group
tower_inventory_source_update:
redirect: awx.awx.inventory_source_update
tower_inventory_source:
redirect: awx.awx.inventory_source
tower_inventory:
redirect: awx.awx.inventory
tower_job_cancel:
redirect: awx.awx.job_cancel
tower_job_launch:
redirect: awx.awx.job_launch
tower_job_list:
redirect: awx.awx.job_list
tower_job_template:
redirect: awx.awx.job_template
tower_job_wait:
redirect: awx.awx.job_wait
tower_label:
redirect: awx.awx.label
tower_license:
redirect: awx.awx.license
tower_notification_template:
redirect: awx.awx.notification_template
tower_notification: tower_notification:
redirect: tower_notification_template redirect: awx.awx.notification_template
tower_organization:
redirect: awx.awx.organization
tower_project_update:
redirect: awx.awx.project_update
tower_project:
redirect: awx.awx.project
tower_role:
redirect: awx.awx.role
tower_schedule:
redirect: awx.awx.schedule
tower_settings:
redirect: awx.awx.settings
tower_team:
redirect: awx.awx.team
tower_token:
redirect: awx.awx.token
tower_user:
redirect: awx.awx.user
tower_workflow_approval:
redirect: awx.awx.workflow_approval
tower_workflow_job_template_node:
redirect: awx.awx.workflow_job_template_node
tower_workflow_job_template:
redirect: awx.awx.workflow_job_template
tower_workflow_launch:
redirect: awx.awx.workflow_launch
tower_workflow_node_wait:
redirect: awx.awx.workflow_node_wait
# if playbook specifies a FQCN
awx.awx.tower_ad_hoc_command_cancel:
redirect: awx.awx.ad_hoc_command_cancel
awx.awx.tower_ad_hoc_command_wait:
redirect: awx.awx.ad_hoc_command_wait
awx.awx.tower_ad_hoc_command:
redirect: awx.awx.ad_hoc_command
awx.awx.tower_application:
redirect: awx.awx.application
awx.awx.tower_meta:
redirect: awx.awx.controller_meta
awx.awx.tower_credential_input_source:
redirect: awx.awx.credential_input_source
awx.awx.tower_credential_type:
redirect: awx.awx.credential_type
awx.awx.tower_credential:
redirect: awx.awx.credential
awx.awx.tower_execution_environment:
redirect: awx.awx.execution_environment
awx.awx.tower_export:
redirect: awx.awx.export
awx.awx.tower_group:
redirect: awx.awx.group
awx.awx.tower_host:
redirect: awx.awx.host
awx.awx.tower_import:
redirect: awx.awx.import
awx.awx.tower_instance_group:
redirect: awx.awx.instance_group
awx.awx.tower_inventory_source_update:
redirect: awx.awx.inventory_source_update
awx.awx.tower_inventory_source:
redirect: awx.awx.inventory_source
awx.awx.tower_inventory:
redirect: awx.awx.inventory
awx.awx.tower_job_cancel:
redirect: awx.awx.job_cancel
awx.awx.tower_job_launch:
redirect: awx.awx.job_launch
awx.awx.tower_job_list:
redirect: awx.awx.job_list
awx.awx.tower_job_template:
redirect: awx.awx.job_template
awx.awx.tower_job_wait:
redirect: awx.awx.job_wait
awx.awx.tower_label:
redirect: awx.awx.label
awx.awx.tower_license:
redirect: awx.awx.license
awx.awx.tower_notification_template:
redirect: awx.awx.notification_template
awx.awx.tower_notification:
redirect: awx.awx.notification_template
awx.awx.tower_organization:
redirect: awx.awx.organization
awx.awx.tower_project_update:
redirect: awx.awx.project_update
awx.awx.tower_project:
redirect: awx.awx.project
awx.awx.tower_role:
redirect: awx.awx.role
awx.awx.tower_schedule:
redirect: awx.awx.schedule
awx.awx.tower_settings:
redirect: awx.awx.settings
awx.awx.tower_team:
redirect: awx.awx.team
awx.awx.tower_token:
redirect: awx.awx.token
awx.awx.tower_user:
redirect: awx.awx.user
awx.awx.tower_workflow_approval:
redirect: awx.awx.workflow_approval
awx.awx.tower_workflow_job_template_node:
redirect: awx.awx.workflow_job_template_node
awx.awx.tower_workflow_job_template:
redirect: awx.awx.workflow_job_template
awx.awx.tower_workflow_launch:
redirect: awx.awx.workflow_launch
awx.awx.tower_workflow_node_wait:
redirect: awx.awx.workflow_node_wait

View File

@@ -10,52 +10,57 @@ __metaclass__ = type
class ModuleDocFragment(object): class ModuleDocFragment(object):
# Ansible Tower documentation fragment # Automation Platform Controller documentation fragment
DOCUMENTATION = r''' DOCUMENTATION = r'''
options: options:
tower_host: controller_host:
description: description:
- URL to your Tower or AWX instance. - URL to your Automation Platform Controller instance.
- If value not set, will try environment variable C(TOWER_HOST) and then config files - If value not set, will try environment variable C(CONTROLLER_HOST) and then config files
- If value not specified by any means, the value of C(127.0.0.1) will be used - If value not specified by any means, the value of C(127.0.0.1) will be used
type: str type: str
tower_username: aliases: [ tower_host ]
controller_username:
description: description:
- Username for your Tower or AWX instance. - Username for your controller instance.
- If value not set, will try environment variable C(TOWER_USERNAME) and then config files - If value not set, will try environment variable C(CONTROLLER_USERNAME) and then config files
type: str type: str
tower_password: aliases: [ tower_username ]
controller_password:
description: description:
- Password for your Tower or AWX instance. - Password for your controller instance.
- If value not set, will try environment variable C(TOWER_PASSWORD) and then config files - If value not set, will try environment variable C(CONTROLLER_PASSWORD) and then config files
type: str type: str
tower_oauthtoken: aliases: [ tower_password ]
controller_oauthtoken:
description: description:
- The Tower OAuth token to use. - The OAuth token to use.
- This value can be in one of two formats. - This value can be in one of two formats.
- A string which is the token itself. (i.e. bqV5txm97wqJqtkxlMkhQz0pKhRMMX) - A string which is the token itself. (i.e. bqV5txm97wqJqtkxlMkhQz0pKhRMMX)
- A dictionary structure as returned by the tower_token module. - A dictionary structure as returned by the token module.
- If value not set, will try environment variable C(TOWER_OAUTH_TOKEN) and then config files - If value not set, will try environment variable C(CONTROLLER_OAUTH_TOKEN) and then config files
type: raw type: raw
version_added: "3.7" version_added: "3.7.0"
aliases: [ tower_oauthtoken ]
validate_certs: validate_certs:
description: description:
- Whether to allow insecure connections to Tower or AWX. - Whether to allow insecure connections to AWX.
- If C(no), SSL certificates will not be validated. - If C(no), SSL certificates will not be validated.
- This should only be used on personally controlled sites using self-signed certificates. - This should only be used on personally controlled sites using self-signed certificates.
- If value not set, will try environment variable C(TOWER_VERIFY_SSL) and then config files - If value not set, will try environment variable C(CONTROLLER_VERIFY_SSL) and then config files
type: bool type: bool
aliases: [ tower_verify_ssl ] aliases: [ tower_verify_ssl ]
tower_config_file: controller_config_file:
description: description:
- Path to the Tower or AWX config file. - Path to the controller config file.
- If provided, the other locations for config files will not be considered. - If provided, the other locations for config files will not be considered.
type: path type: path
aliases: [tower_config_file]
notes: notes:
- If no I(config_file) is provided we will attempt to use the tower-cli library - If no I(config_file) is provided we will attempt to use the tower-cli library
defaults to find your Tower host information. defaults to find your host information.
- I(config_file) should contain Tower configuration in the following format - I(config_file) should be in the following format
host=hostname host=hostname
username=username username=username
password=password password=password

View File

@@ -10,39 +10,54 @@ __metaclass__ = type
class ModuleDocFragment(object): class ModuleDocFragment(object):
# Ansible Tower documentation fragment # Automation Platform Controller documentation fragment
DOCUMENTATION = r''' DOCUMENTATION = r'''
options: options:
host: host:
description: The network address of your Ansible Tower host. description: The network address of your Automation Platform Controller host.
env: env:
- name: CONTROLLER_HOST
- name: TOWER_HOST - name: TOWER_HOST
deprecated:
alternatives: 'CONTROLLER_HOST'
username: username:
description: The user that you plan to use to access inventories on Ansible Tower. description: The user that you plan to use to access inventories on the controller.
env: env:
- name: CONTROLLER_USERNAME
- name: TOWER_USERNAME - name: TOWER_USERNAME
deprecated:
alternatives: 'CONTROLLER_USERNAME'
password: password:
description: The password for your Ansible Tower user. description: The password for your controller user.
env: env:
- name: CONTROLLER_PASSWORD
- name: TOWER_PASSWORD - name: TOWER_PASSWORD
deprecated:
alternatives: 'CONTROLLER_PASSWORD'
oauth_token: oauth_token:
description: description:
- The Tower OAuth token to use. - The OAuth token to use.
env: env:
- name: CONTROLLER_OAUTH_TOKEN
- name: TOWER_OAUTH_TOKEN - name: TOWER_OAUTH_TOKEN
deprecated:
alternatives: 'CONTROLLER_OAUTH_TOKEN'
verify_ssl: verify_ssl:
description: description:
- Specify whether Ansible should verify the SSL certificate of Ansible Tower host. - Specify whether Ansible should verify the SSL certificate of the controller host.
- Defaults to True, but this is handled by the shared module_utils code - Defaults to True, but this is handled by the shared module_utils code
type: bool type: bool
env: env:
- name: CONTROLLER_VERIFY_SSL
- name: TOWER_VERIFY_SSL - name: TOWER_VERIFY_SSL
deprecated:
alternatives: 'CONTROLLER_VERIFY_SSL'
aliases: [ validate_certs ] aliases: [ validate_certs ]
notes: notes:
- If no I(config_file) is provided we will attempt to use the tower-cli library - If no I(config_file) is provided we will attempt to use the tower-cli library
defaults to find your Tower host information. defaults to find your host information.
- I(config_file) should contain Tower configuration in the following format - I(config_file) should be in the following format
host=hostname host=hostname
username=username username=username
password=password password=password

View File

@@ -6,33 +6,33 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = ''' DOCUMENTATION = '''
name: tower name: controller
plugin_type: inventory plugin_type: inventory
author: author:
- Matthew Jones (@matburt) - Matthew Jones (@matburt)
- Yunfan Zhang (@YunfanZhang42) - Yunfan Zhang (@YunfanZhang42)
short_description: Ansible dynamic inventory plugin for Ansible Tower. short_description: Ansible dynamic inventory plugin for the Automation Platform Controller.
description: description:
- Reads inventories from Ansible Tower. - Reads inventories from the Automation Platform Controller.
- Supports reading configuration from both YAML config file and environment variables. - 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), - If reading from the YAML file, the file name must end with controller.(yml|yaml) or controller_inventory.(yml|yaml),
the path in the command would be /path/to/tower_inventory.(yml|yaml). If some arguments in the config file the path in the command would be /path/to/controller_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. 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. - If reading configurations from environment variables, the path in the command must be @controller_inventory.
extends_documentation_fragment: awx.awx.auth_plugin extends_documentation_fragment: awx.awx.auth_plugin
options: options:
inventory_id: inventory_id:
description: description:
- The ID of the Ansible Tower inventory that you wish to import. - The ID of the inventory that you wish to import.
- This is allowed to be either the inventory primary key or its named URL slug. - 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. - 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". - Named URL slugs follow the syntax of "inventory_name++organization_name".
type: raw type: raw
env: env:
- name: TOWER_INVENTORY - name: CONTROLLER_INVENTORY
required: True required: True
include_metadata: include_metadata:
description: Make extra requests to provide all group vars with metadata about the source Ansible Tower host. description: Make extra requests to provide all group vars with metadata about the source host.
type: bool type: bool
default: False default: False
''' '''
@@ -41,27 +41,27 @@ EXAMPLES = '''
# Before you execute the following commands, you should make sure this file is in your plugin path, # Before you execute the following commands, you should make sure this file is in your plugin path,
# and you enabled this plugin. # and you enabled this plugin.
# Example for using tower_inventory.yml file # Example for using controller_inventory.yml file
plugin: awx.awx.tower plugin: awx.awx.controller
host: your_ansible_tower_server_network_address host: your_automation_controller_server_network_address
username: your_ansible_tower_username username: your_automation_controller_username
password: your_ansible_tower_password password: your_automation_controller_password
inventory_id: the_ID_of_targeted_ansible_tower_inventory inventory_id: the_ID_of_targeted_automation_controller_inventory
# Then you can run the following command. # Then you can run the following command.
# If some of the arguments are missing, Ansible will attempt to read them from environment variables. # 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 # ansible-inventory -i /path/to/controller_inventory.yml --list
# Example for reading from environment variables: # Example for reading from environment variables:
# Set environment variables: # Set environment variables:
# export TOWER_HOST=YOUR_TOWER_HOST_ADDRESS # export CONTROLLER_HOST=YOUR_AUTOMATION_PLATFORM_CONTROLLER_HOST_ADDRESS
# export TOWER_USERNAME=YOUR_TOWER_USERNAME # export CONTROLLER_USERNAME=YOUR_CONTROLLER_USERNAME
# export TOWER_PASSWORD=YOUR_TOWER_PASSWORD # export CONTROLLER_PASSWORD=YOUR_CONTROLLER_PASSWORD
# export TOWER_INVENTORY=THE_ID_OF_TARGETED_INVENTORY # export CONTROLLER_INVENTORY=THE_ID_OF_TARGETED_INVENTORY
# Read the inventory specified in TOWER_INVENTORY from Ansible Tower, and list them. # Read the inventory specified in CONTROLLER_INVENTORY from the controller, and list them.
# The inventory path must always be @tower_inventory if you are reading all settings from environment variables. # The inventory path must always be @controller_inventory if you are reading all settings from environment variables.
# ansible-inventory -i @tower_inventory --list # ansible-inventory -i @controller_inventory --list
''' '''
import os import os
@@ -72,7 +72,7 @@ from ansible.errors import AnsibleParserError, AnsibleOptionsError
from ansible.plugins.inventory import BaseInventoryPlugin from ansible.plugins.inventory import BaseInventoryPlugin
from ansible.config.manager import ensure_type from ansible.config.manager import ensure_type
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def handle_error(**kwargs): def handle_error(**kwargs):
@@ -80,17 +80,28 @@ def handle_error(**kwargs):
class InventoryModule(BaseInventoryPlugin): class InventoryModule(BaseInventoryPlugin):
NAME = 'awx.awx.tower' # REPLACE NAME = 'awx.awx.controller' # REPLACE
# Stays backward compatible with tower inventory script. # Stays backward compatible with the inventory script.
# If the user supplies '@tower_inventory' as path, the plugin will read from environment variables. # If the user supplies '@controller_inventory' as path, the plugin will read from environment variables.
no_config_file_supplied = False no_config_file_supplied = False
def verify_file(self, path): def verify_file(self, path):
if path.endswith('@tower_inventory'): if path.endswith('@controller_inventory') or path.endswith('@tower_inventory'):
self.no_config_file_supplied = True self.no_config_file_supplied = True
return True return True
elif super(InventoryModule, self).verify_file(path): elif super().verify_file(path):
return path.endswith(('tower_inventory.yml', 'tower_inventory.yaml', 'tower.yml', 'tower.yaml')) return path.endswith(
(
'controller_inventory.yml',
'controller_inventory.yaml',
'controller.yml',
'controller.yaml',
'tower_inventory.yml',
'tower_inventory.yaml',
'tower.yml',
'tower.yaml',
)
)
else: else:
return False return False
@@ -98,18 +109,18 @@ class InventoryModule(BaseInventoryPlugin):
self.display.warning(warning) self.display.warning(warning)
def parse(self, inventory, loader, path, cache=True): def parse(self, inventory, loader, path, cache=True):
super(InventoryModule, self).parse(inventory, loader, path) super().parse(inventory, loader, path)
if not self.no_config_file_supplied and os.path.isfile(path): if not self.no_config_file_supplied and os.path.isfile(path):
self._read_config_data(path) self._read_config_data(path)
# Defer processing of params to logic shared with the modules # Defer processing of params to logic shared with the modules
module_params = {} module_params = {}
for plugin_param, module_param in TowerAPIModule.short_params.items(): for plugin_param, module_param in ControllerAPIModule.short_params.items():
opt_val = self.get_option(plugin_param) opt_val = self.get_option(plugin_param)
if opt_val is not None: if opt_val is not None:
module_params[module_param] = opt_val module_params[module_param] = opt_val
module = TowerAPIModule(argument_spec={}, direct_params=module_params, error_callback=handle_error, warn_callback=self.warn_callback) module = ControllerAPIModule(argument_spec={}, direct_params=module_params, error_callback=handle_error, warn_callback=self.warn_callback)
# validate type of inventory_id because we allow two types as special case # validate type of inventory_id because we allow two types as special case
inventory_id = self.get_option('inventory_id') inventory_id = self.get_option('inventory_id')
@@ -121,7 +132,7 @@ class InventoryModule(BaseInventoryPlugin):
except ValueError as e: except ValueError as e:
raise AnsibleOptionsError( raise AnsibleOptionsError(
'Invalid type for configuration option inventory_id, ' 'not integer, and cannot convert to string: {err}'.format(err=to_native(e)) 'Invalid type for configuration option inventory_id, ' 'not integer, and cannot convert to string: {err}'.format(err=to_native(e))
) ) from e
inventory_id = inventory_id.replace('/', '') inventory_id = inventory_id.replace('/', '')
inventory_url = '/api/v2/inventories/{inv_id}/script/'.format(inv_id=inventory_id) inventory_url = '/api/v2/inventories/{inv_id}/script/'.format(inv_id=inventory_id)

View File

@@ -5,16 +5,16 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = """ DOCUMENTATION = """
lookup: tower_api lookup: controller_api
author: John Westcott IV (@john-westcott-iv) author: John Westcott IV (@john-westcott-iv)
short_description: Search the API for objects short_description: Search the API for objects
requirements: requirements:
- None - None
description: description:
- Returns GET requests from the Ansible Tower API. See - Returns GET requests from the Automation Platform Controller API. See
U(https://docs.ansible.com/ansible-tower/latest/html/towerapi/index.html) for API usage. U(https://docs.ansible.com/ansible-tower/latest/html/towerapi/index.html) for API usage.
- For use that is cross-compatible between the awx.awx and ansible.tower collection - For use that is cross-compatible between the awx.awx and ansible.controller collection
see the tower_meta module see the controller_meta module
extends_documentation_fragment: awx.awx.auth_plugin extends_documentation_fragment: awx.awx.auth_plugin
options: options:
_terms: _terms:
@@ -71,37 +71,38 @@ notes:
EXAMPLES = """ EXAMPLES = """
- name: Load the UI settings - name: Load the UI settings
set_fact: set_fact:
tower_settings: "{{ lookup('awx.awx.tower_api', 'settings/ui') }}" controller_settings: "{{ lookup('awx.awx.controller_api', 'settings/ui') }}"
- name: Load the UI settings specifying the connection info - name: Load the UI settings specifying the connection info
set_fact: set_fact:
tower_settings: "{{ lookup('awx.awx.tower_api', 'settings/ui' host='tower.example.com', username='admin', password=my_pass_var, verify_ssl=False) }}" controller_settings: "{{ lookup('awx.awx.controller_api', 'settings/ui' host='controller.example.com',
username='admin', password=my_pass_var, verify_ssl=False) }}"
- name: Report the usernames of all users with admin privs - name: Report the usernames of all users with admin privs
debug: debug:
msg: "Admin users: {{ query('awx.awx.tower_api', 'users', query_params={ 'is_superuser': true }) | map(attribute='username') | join(', ') }}" msg: "Admin users: {{ query('awx.awx.controller_api', 'users', query_params={ 'is_superuser': true }) | map(attribute='username') | join(', ') }}"
- name: debug all organizations in a loop # use query to return a list - name: debug all organizations in a loop # use query to return a list
debug: debug:
msg: "Organization description={{ item['description'] }} id={{ item['id'] }}" msg: "Organization description={{ item['description'] }} id={{ item['id'] }}"
loop: "{{ query('awx.awx.tower_api', 'organizations') }}" loop: "{{ query('awx.awx.controller_api', 'organizations') }}"
loop_control: loop_control:
label: "{{ item['name'] }}" label: "{{ item['name'] }}"
- name: Make sure user 'john' is an org admin of the default org if the user exists - name: Make sure user 'john' is an org admin of the default org if the user exists
tower_role: role:
organization: Default organization: Default
role: admin role: admin
user: john user: john
when: "lookup('awx.awx.tower_api', 'users', query_params={ 'username': 'john' }) | length == 1" when: "lookup('awx.awx.controller_api', 'users', query_params={ 'username': 'john' }) | length == 1"
- name: Create an inventory group with all 'foo' hosts - name: Create an inventory group with all 'foo' hosts
tower_group: group:
name: "Foo Group" name: "Foo Group"
inventory: "Demo Inventory" inventory: "Demo Inventory"
hosts: >- hosts: >-
{{ query( {{ query(
'awx.awx.tower_api', 'awx.awx.controller_api',
'hosts', 'hosts',
query_params={ 'name__startswith' : 'foo', }, query_params={ 'name__startswith' : 'foo', },
) | map(attribute='name') | list }} ) | map(attribute='name') | list }}
@@ -120,7 +121,7 @@ from ansible.plugins.lookup import LookupBase
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from ansible.module_utils._text import to_native from ansible.module_utils._text import to_native
from ansible.utils.display import Display from ansible.utils.display import Display
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
class LookupModule(LookupBase): class LookupModule(LookupBase):
@@ -140,13 +141,13 @@ class LookupModule(LookupBase):
# Defer processing of params to logic shared with the modules # Defer processing of params to logic shared with the modules
module_params = {} module_params = {}
for plugin_param, module_param in TowerAPIModule.short_params.items(): for plugin_param, module_param in ControllerAPIModule.short_params.items():
opt_val = self.get_option(plugin_param) opt_val = self.get_option(plugin_param)
if opt_val is not None: if opt_val is not None:
module_params[module_param] = opt_val module_params[module_param] = opt_val
# Create our module # Create our module
module = TowerAPIModule(argument_spec={}, direct_params=module_params, error_callback=self.handle_error, warn_callback=self.warn_callback) module = ControllerAPIModule(argument_spec={}, direct_params=module_params, error_callback=self.handle_error, warn_callback=self.warn_callback)
response = module.get_endpoint(terms[0], data=self.get_option('query_params', {})) response = module.get_endpoint(terms[0], data=self.get_option('query_params', {}))

View File

@@ -5,12 +5,12 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
DOCUMENTATION = """ DOCUMENTATION = """
lookup: tower_schedule_rrule lookup: schedule_rrule
author: John Westcott IV (@john-westcott-iv) author: John Westcott IV (@john-westcott-iv)
short_description: Generate an rrule string which can be used for Tower Schedules short_description: Generate an rrule string which can be used for Schedules
requirements: requirements:
- pytz - pytz
- python.dateutil >= 2.7.0 - python-dateutil >= 2.7.0
description: description:
- Returns a string based on criteria which represents an rrule - Returns a string based on criteria which represents an rrule
options: options:
@@ -75,7 +75,7 @@ DOCUMENTATION = """
EXAMPLES = """ EXAMPLES = """
- name: Create a string for a schedule - name: Create a string for a schedule
debug: debug:
msg: "{{ query('awx.awx.tower_schedule_rrule', 'none', start_date='1979-09-13 03:45:07') }}" msg: "{{ query('awx.awx.schedule_rrule', 'none', start_date='1979-09-13 03:45:07') }}"
""" """
RETURN = """ RETURN = """
@@ -84,35 +84,22 @@ _raw:
- String in the rrule format - String in the rrule format
type: string type: string
""" """
import re
from ansible.module_utils.six import raise_from
from ansible.plugins.lookup import LookupBase from ansible.plugins.lookup import LookupBase
from ansible.errors import AnsibleError from ansible.errors import AnsibleError
from datetime import datetime from datetime import datetime
import re from dateutil import rrule
from distutils.version import LooseVersion from distutils.version import LooseVersion
missing_modules = []
try: try:
import pytz import pytz
except ImportError:
missing_modules.append('pytz')
try:
from dateutil import rrule from dateutil import rrule
except ImportError: except ImportError as imp_exc:
missing_modules.append('python.dateutil') LIBRARY_IMPORT_ERROR = imp_exc
else:
# Validate the version of python.dateutil LIBRARY_IMPORT_ERROR = None
try:
import dateutil
if LooseVersion(dateutil.__version__) < LooseVersion("2.7.0"):
raise Exception
except Exception:
missing_modules.append('python.dateutil>=2.7.0')
if len(missing_modules) > 0:
raise AnsibleError('You are missing the modules {0}'.format(', '.join(missing_modules)))
class LookupModule(LookupBase): class LookupModule(LookupBase):
@@ -143,6 +130,15 @@ class LookupModule(LookupBase):
'last': -1, 'last': -1,
} }
# plugin constructor
def __init__(self, *args, **kwargs):
if LIBRARY_IMPORT_ERROR:
raise_from(
AnsibleError('{0}'.format(LIBRARY_IMPORT_ERROR)),
LIBRARY_IMPORT_ERROR
)
super().__init__(*args, **kwargs)
@staticmethod @staticmethod
def parse_date_time(date_string): def parse_date_time(date_string):
try: try:
@@ -173,8 +169,8 @@ class LookupModule(LookupBase):
if 'start_date' in kwargs: if 'start_date' in kwargs:
try: try:
rrule_kwargs['dtstart'] = LookupModule.parse_date_time(kwargs['start_date']) rrule_kwargs['dtstart'] = LookupModule.parse_date_time(kwargs['start_date'])
except Exception: except Exception as e:
raise AnsibleError('Parameter start_date must be in the format YYYY-MM-DD [HH:MM:SS]') raise AnsibleError('Parameter start_date must be in the format YYYY-MM-DD [HH:MM:SS]') from e
# If we are a none frequency we don't need anything else # If we are a none frequency we don't need anything else
if frequency == 'none': if frequency == 'none':
@@ -188,8 +184,8 @@ class LookupModule(LookupBase):
else: else:
try: try:
rrule_kwargs['until'] = LookupModule.parse_date_time(end_on) rrule_kwargs['until'] = LookupModule.parse_date_time(end_on)
except Exception: except Exception as e:
raise AnsibleError('Parameter end_on must either be an integer or in the format YYYY-MM-DD [HH:MM:SS]') raise AnsibleError('Parameter end_on must either be an integer or in the format YYYY-MM-DD [HH:MM:SS]') from e
# A week-based frequency can also take the on_days parameter # A week-based frequency can also take the on_days parameter
if frequency == 'week' and 'on_days' in kwargs: if frequency == 'week' and 'on_days' in kwargs:
@@ -212,16 +208,16 @@ class LookupModule(LookupBase):
my_month_day = int(kwargs['month_day_number']) my_month_day = int(kwargs['month_day_number'])
if my_month_day < 1 or my_month_day > 31: if my_month_day < 1 or my_month_day > 31:
raise Exception() raise Exception()
except Exception: except Exception as e:
raise AnsibleError('month_day_number must be between 1 and 31') raise AnsibleError('month_day_number must be between 1 and 31') from e
rrule_kwargs['bymonthday'] = my_month_day rrule_kwargs['bymonthday'] = my_month_day
if 'on_the' in kwargs: if 'on_the' in kwargs:
try: try:
(occurance, weekday) = kwargs['on_the'].split(' ') (occurance, weekday) = kwargs['on_the'].split(' ')
except Exception: except Exception as e:
raise AnsibleError('on_the parameter must be two words separated by a space') raise AnsibleError('on_the parameter must be two words separated by a space') from e
if weekday not in LookupModule.weekdays: if weekday not in LookupModule.weekdays:
raise AnsibleError('Weekday portion of on_the parameter is not valid') raise AnsibleError('Weekday portion of on_the parameter is not valid')
@@ -233,7 +229,7 @@ class LookupModule(LookupBase):
my_rule = rrule.rrule(**rrule_kwargs) my_rule = rrule.rrule(**rrule_kwargs)
# All frequencies can use a timezone but rrule can't support the format that Tower uses. # All frequencies can use a timezone but rrule can't support the format that AWX uses.
# So we will do a string manip here if we need to # So we will do a string manip here if we need to
timezone = 'America/New_York' timezone = 'America/New_York'
if 'timezone' in kwargs: if 'timezone' in kwargs:
@@ -243,7 +239,7 @@ class LookupModule(LookupBase):
# rrule puts a \n in the rule instad of a space and can't handle timezones # rrule puts a \n in the rule instad of a space and can't handle timezones
return_rrule = str(my_rule).replace('\n', ' ').replace('DTSTART:', 'DTSTART;TZID={0}:'.format(timezone)) return_rrule = str(my_rule).replace('\n', ' ').replace('DTSTART:', 'DTSTART;TZID={0}:'.format(timezone))
# Tower requires an interval. rrule will not add interval if it's set to 1 # AWX requires an interval. rrule will not add interval if it's set to 1
if kwargs.get('every', 1) == 1: if kwargs.get('every', 1) == 1:
return_rrule = "{0};INTERVAL=1".format(return_rrule) return_rrule = "{0};INTERVAL=1".format(return_rrule)

View File

@@ -2,7 +2,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
from .tower_module import TowerModule from .controller_module import ControllerModule
from ansible.module_utils.basic import missing_required_lib from ansible.module_utils.basic import missing_required_lib
try: try:
@@ -15,14 +15,14 @@ except ImportError:
HAS_AWX_KIT = False HAS_AWX_KIT = False
class TowerAWXKitModule(TowerModule): class ControllerAWXKitModule(ControllerModule):
connection = None connection = None
apiV2Ref = None apiV2Ref = None
def __init__(self, argument_spec, **kwargs): def __init__(self, argument_spec, **kwargs):
kwargs['supports_check_mode'] = False kwargs['supports_check_mode'] = False
super(TowerAWXKitModule, self).__init__(argument_spec=argument_spec, **kwargs) super().__init__(argument_spec=argument_spec, **kwargs)
# Die if we don't have AWX_KIT installed # Die if we don't have AWX_KIT installed
if not HAS_AWX_KIT: if not HAS_AWX_KIT:

View File

@@ -2,7 +2,7 @@ from __future__ import absolute_import, division, print_function
__metaclass__ = type __metaclass__ = type
from .tower_module import TowerModule from .controller_module import ControllerModule
from ansible.module_utils.urls import Request, SSLValidationError, ConnectionError from ansible.module_utils.urls import Request, SSLValidationError, ConnectionError
from ansible.module_utils.six import PY2 from ansible.module_utils.six import PY2
from ansible.module_utils.six.moves.urllib.error import HTTPError from ansible.module_utils.six.moves.urllib.error import HTTPError
@@ -12,8 +12,8 @@ import time
from json import loads, dumps from json import loads, dumps
class TowerAPIModule(TowerModule): class ControllerAPIModule(ControllerModule):
# TODO: Move the collection version check into tower_module.py # TODO: Move the collection version check into controller_module.py
# This gets set by the make process so whatever is in here is irrelevant # This gets set by the make process so whatever is in here is irrelevant
_COLLECTION_VERSION = "0.0.1-devel" _COLLECTION_VERSION = "0.0.1-devel"
_COLLECTION_TYPE = "awx" _COLLECTION_TYPE = "awx"
@@ -21,7 +21,7 @@ class TowerAPIModule(TowerModule):
# Those values can be found in awx/api/generics.py line 204 # Those values can be found in awx/api/generics.py line 204
collection_to_version = { collection_to_version = {
'awx': 'AWX', 'awx': 'AWX',
'tower': 'Red Hat Ansible Tower', 'controller': 'Red Hat Automation Platform Controller',
} }
session = None session = None
IDENTITY_FIELDS = {'users': 'username', 'workflow_job_template_nodes': 'identifier', 'instances': 'hostname'} IDENTITY_FIELDS = {'users': 'username', 'workflow_job_template_nodes': 'identifier', 'instances': 'hostname'}
@@ -30,7 +30,7 @@ class TowerAPIModule(TowerModule):
def __init__(self, argument_spec, direct_params=None, error_callback=None, warn_callback=None, **kwargs): def __init__(self, argument_spec, direct_params=None, error_callback=None, warn_callback=None, **kwargs):
kwargs['supports_check_mode'] = True kwargs['supports_check_mode'] = True
super(TowerAPIModule, self).__init__( super().__init__(
argument_spec=argument_spec, direct_params=direct_params, error_callback=error_callback, warn_callback=warn_callback, **kwargs argument_spec=argument_spec, direct_params=direct_params, error_callback=error_callback, warn_callback=warn_callback, **kwargs
) )
self.session = Request(cookies=CookieJar(), validate_certs=self.verify_ssl) self.session = Request(cookies=CookieJar(), validate_certs=self.verify_ssl)
@@ -47,14 +47,14 @@ class TowerAPIModule(TowerModule):
@staticmethod @staticmethod
def get_name_field_from_endpoint(endpoint): def get_name_field_from_endpoint(endpoint):
return TowerAPIModule.IDENTITY_FIELDS.get(endpoint, 'name') return ControllerAPIModule.IDENTITY_FIELDS.get(endpoint, 'name')
def get_item_name(self, item, allow_unknown=False): def get_item_name(self, item, allow_unknown=False):
if item: if item:
if 'name' in item: if 'name' in item:
return item['name'] return item['name']
for field_name in TowerAPIModule.IDENTITY_FIELDS.values(): for field_name in ControllerAPIModule.IDENTITY_FIELDS.values():
if field_name in item: if field_name in item:
return item[field_name] return item[field_name]
@@ -163,7 +163,7 @@ class TowerAPIModule(TowerModule):
if len(sample['json']['results']) > 1: if len(sample['json']['results']) > 1:
sample['json']['results'] = sample['json']['results'][:2] + ['...more results snipped...'] sample['json']['results'] = sample['json']['results'][:2] + ['...more results snipped...']
url = self.build_url(endpoint, query_params) url = self.build_url(endpoint, query_params)
display_endpoint = url.geturl()[len(self.host) :] # truncate to not include the base URL display_endpoint = url.geturl()[len(self.host):] # truncate to not include the base URL
self.fail_json( self.fail_json(
msg="Request to {0} returned {1} items, expected 1".format(display_endpoint, response['json']['count']), msg="Request to {0} returned {1} items, expected 1".format(display_endpoint, response['json']['count']),
query=query_params, query=query_params,
@@ -190,7 +190,7 @@ class TowerAPIModule(TowerModule):
# Extract the headers, this will be used in a couple of places # Extract the headers, this will be used in a couple of places
headers = kwargs.get('headers', {}) headers = kwargs.get('headers', {})
# Authenticate to Tower (if we don't have a token and if not already done so) # Authenticate to AWX (if we don't have a token and if not already done so)
if not self.oauth_token and not self.authenticated: if not self.oauth_token and not self.authenticated:
# This method will set a cookie in the cookie jar for us and also an oauth_token # This method will set a cookie in the cookie jar for us and also an oauth_token
self.authenticate(**kwargs) self.authenticate(**kwargs)
@@ -218,7 +218,7 @@ class TowerAPIModule(TowerModule):
self.fail_json(msg='The host sent back a server error ({1}): {0}. Please check the logs and try again later'.format(url.path, he)) self.fail_json(msg='The host sent back a server error ({1}): {0}. Please check the logs and try again later'.format(url.path, he))
# Sanity check: Did we fail to authenticate properly? If so, fail out now; this is always a failure. # Sanity check: Did we fail to authenticate properly? If so, fail out now; this is always a failure.
elif he.code == 401: elif he.code == 401:
self.fail_json(msg='Invalid Tower authentication credentials for {0} (HTTP 401).'.format(url.path)) self.fail_json(msg='Invalid authentication credentials for {0} (HTTP 401).'.format(url.path))
# Sanity check: Did we get a forbidden response, which means that the user isn't allowed to do this? Report that. # Sanity check: Did we get a forbidden response, which means that the user isn't allowed to do this? Report that.
elif he.code == 403: elif he.code == 403:
self.fail_json(msg="You don't have permission to {1} to {0} (HTTP 403).".format(url.path, method)) self.fail_json(msg="You don't have permission to {1} to {0} (HTTP 403).".format(url.path, method))
@@ -232,7 +232,7 @@ class TowerAPIModule(TowerModule):
# A 405 means we used a method that isn't allowed. Usually this is a bad request, but it requires special treatment because the # A 405 means we used a method that isn't allowed. Usually this is a bad request, but it requires special treatment because the
# API sends it as a logic error in a few situations (e.g. trying to cancel a job that isn't running). # API sends it as a logic error in a few situations (e.g. trying to cancel a job that isn't running).
elif he.code == 405: elif he.code == 405:
self.fail_json(msg="The Tower server says you can't make a request with the {0} method to this endpoint {1}".format(method, url.path)) self.fail_json(msg="Cannot make a request with the {0} method to this endpoint {1}".format(method, url.path))
# Sanity check: Did we get some other kind of error? If so, write an appropriate error message. # Sanity check: Did we get some other kind of error? If so, write an appropriate error message.
elif he.code >= 400: elif he.code >= 400:
# We are going to return a 400 so the module can decide what to do with it # We are going to return a 400 so the module can decide what to do with it
@@ -254,26 +254,28 @@ class TowerAPIModule(TowerModule):
# In PY2 we get back an HTTPResponse object but PY2 is returning an addinfourl # In PY2 we get back an HTTPResponse object but PY2 is returning an addinfourl
# First try to get the headers in PY3 format and then drop down to PY2. # First try to get the headers in PY3 format and then drop down to PY2.
try: try:
tower_type = response.getheader('X-API-Product-Name', None) controller_type = response.getheader('X-API-Product-Name', None)
tower_version = response.getheader('X-API-Product-Version', None) controller_version = response.getheader('X-API-Product-Version', None)
except Exception: except Exception:
tower_type = response.info().getheader('X-API-Product-Name', None) controller_type = response.info().getheader('X-API-Product-Name', None)
tower_version = response.info().getheader('X-API-Product-Version', None) controller_version = response.info().getheader('X-API-Product-Version', None)
parsed_collection_version = Version(self._COLLECTION_VERSION).version parsed_collection_version = Version(self._COLLECTION_VERSION).version
parsed_tower_version = Version(tower_version).version parsed_controller_version = Version(controller_version).version
if tower_type == 'AWX': if controller_type == 'AWX':
collection_compare_ver = parsed_collection_version[0] collection_compare_ver = parsed_collection_version[0]
tower_compare_ver = parsed_tower_version[0] controller_compare_ver = parsed_controller_version[0]
else: else:
collection_compare_ver = "{0}.{1}".format(parsed_collection_version[0], parsed_collection_version[1]) collection_compare_ver = "{0}.{1}".format(parsed_collection_version[0], parsed_collection_version[1])
tower_compare_ver = '{0}.{1}'.format(parsed_tower_version[0], parsed_tower_version[1]) controller_compare_ver = '{0}.{1}'.format(parsed_controller_version[0], parsed_controller_version[1])
if self._COLLECTION_TYPE not in self.collection_to_version or self.collection_to_version[self._COLLECTION_TYPE] != tower_type: if self._COLLECTION_TYPE not in self.collection_to_version or self.collection_to_version[self._COLLECTION_TYPE] != controller_type:
self.warn("You are using the {0} version of this collection but connecting to {1}".format(self._COLLECTION_TYPE, tower_type)) self.warn("You are using the {0} version of this collection but connecting to {1}".format(self._COLLECTION_TYPE, controller_type))
elif collection_compare_ver != tower_compare_ver: elif collection_compare_ver != controller_compare_ver:
self.warn( self.warn(
"You are running collection version {0} but connecting to {2} version {1}".format(self._COLLECTION_VERSION, tower_version, tower_type) "You are running collection version {0} but connecting to {2} version {1}".format(
self._COLLECTION_VERSION, controller_version, controller_type
)
) )
self.version_checked = True self.version_checked = True
@@ -302,7 +304,7 @@ class TowerAPIModule(TowerModule):
# Attempt to get a token from /api/v2/tokens/ by giving it our username/password combo # Attempt to get a token from /api/v2/tokens/ by giving it our username/password combo
# If we have a username and password, we need to get a session cookie # If we have a username and password, we need to get a session cookie
login_data = { login_data = {
"description": "Ansible Tower Module Token", "description": "Automation Platform Controller Module Token",
"application": None, "application": None,
"scope": "write", "scope": "write",
} }
@@ -349,8 +351,8 @@ class TowerAPIModule(TowerModule):
# the on_delete parameter will be called as a method pasing in this object and the json from the response # the on_delete parameter will be called as a method pasing in this object and the json from the response
# This will return one of two things: # This will return one of two things:
# 1. None if the existing_item is not defined (so no delete needs to happen) # 1. None if the existing_item is not defined (so no delete needs to happen)
# 2. The response from Tower from calling the delete on the endpont. It's up to you to process the response and exit from the module # 2. The response from AWX from calling the delete on the endpont. It's up to you to process the response and exit from the module
# Note: common error codes from the Tower API can cause the module to fail # Note: common error codes from the AWX API can cause the module to fail
if existing_item: if existing_item:
# If we have an item, we can try to delete it # If we have an item, we can try to delete it
try: try:
@@ -472,8 +474,8 @@ class TowerAPIModule(TowerModule):
# the on_create parameter will be called as a method pasing in this object and the json from the response # the on_create parameter will be called as a method pasing in this object and the json from the response
# This will return one of two things: # This will return one of two things:
# 1. None if the existing_item is already defined (so no create needs to happen) # 1. None if the existing_item is already defined (so no create needs to happen)
# 2. The response from Tower from calling the patch on the endpont. It's up to you to process the response and exit from the module # 2. The response from AWX from calling the patch on the endpont. It's up to you to process the response and exit from the module
# Note: common error codes from the Tower API can cause the module to fail # Note: common error codes from the AWX API can cause the module to fail
response = None response = None
if not endpoint: if not endpoint:
self.fail_json(msg="Unable to create new {0} due to missing endpoint".format(item_type)) self.fail_json(msg="Unable to create new {0} due to missing endpoint".format(item_type))
@@ -544,13 +546,13 @@ class TowerAPIModule(TowerModule):
""" """
if isinstance(obj, dict): if isinstance(obj, dict):
for val in obj.values(): for val in obj.values():
if TowerAPIModule.has_encrypted_values(val): if ControllerAPIModule.has_encrypted_values(val):
return True return True
elif isinstance(obj, list): elif isinstance(obj, list):
for val in obj: for val in obj:
if TowerAPIModule.has_encrypted_values(val): if ControllerAPIModule.has_encrypted_values(val):
return True return True
elif obj == TowerAPIModule.ENCRYPTED_STRING: elif obj == ControllerAPIModule.ENCRYPTED_STRING:
return True return True
return False return False
@@ -565,11 +567,11 @@ class TowerAPIModule(TowerModule):
if set(old_field.keys()) != set(new_field.keys()): if set(old_field.keys()) != set(new_field.keys()):
return False return False
for key in new_field.keys(): for key in new_field.keys():
if not TowerAPIModule.fields_could_be_same(old_field[key], new_field[key]): if not ControllerAPIModule.fields_could_be_same(old_field[key], new_field[key]):
return False return False
return True # all sub-fields are either equal or could be equal return True # all sub-fields are either equal or could be equal
else: else:
if old_field == TowerAPIModule.ENCRYPTED_STRING: if old_field == ControllerAPIModule.ENCRYPTED_STRING:
return True return True
return bool(new_field == old_field) return bool(new_field == old_field)
@@ -595,8 +597,8 @@ class TowerAPIModule(TowerModule):
# the on_update parameter will be called as a method pasing in this object and the json from the response # the on_update parameter will be called as a method pasing in this object and the json from the response
# This will return one of two things: # This will return one of two things:
# 1. None if the existing_item does not need to be updated # 1. None if the existing_item does not need to be updated
# 2. The response from Tower from patching to the endpoint. It's up to you to process the response and exit from the module. # 2. The response from AWX from patching to the endpoint. It's up to you to process the response and exit from the module.
# Note: common error codes from the Tower API can cause the module to fail # Note: common error codes from the AWX API can cause the module to fail
response = None response = None
if existing_item: if existing_item:
@@ -694,10 +696,10 @@ class TowerAPIModule(TowerModule):
resp = he.read() resp = he.read()
except Exception as e: except Exception as e:
resp = 'unknown {0}'.format(e) resp = 'unknown {0}'.format(e)
self.warn('Failed to release tower token: {0}, response: {1}'.format(he, resp)) self.warn('Failed to release token: {0}, response: {1}'.format(he, resp))
except (Exception) as e: except (Exception) as e:
# Sanity check: Did the server send back some kind of internal error? # Sanity check: Did the server send back some kind of internal error?
self.warn('Failed to release tower token {0}: {1}'.format(self.oauth_token_id, e)) self.warn('Failed to release token {0}: {1}'.format(self.oauth_token_id, e))
def is_job_done(self, job_status): def is_job_done(self, job_status):
if job_status in ['new', 'pending', 'waiting', 'running']: if job_status in ['new', 'pending', 'waiting', 'running']:

View File

@@ -29,22 +29,45 @@ class ItemNotDefined(Exception):
pass pass
class TowerModule(AnsibleModule): class ControllerModule(AnsibleModule):
url = None url = None
AUTH_ARGSPEC = dict( AUTH_ARGSPEC = dict(
tower_host=dict(required=False, fallback=(env_fallback, ['TOWER_HOST'])), controller_host=dict(
tower_username=dict(required=False, fallback=(env_fallback, ['TOWER_USERNAME'])), required=False,
tower_password=dict(no_log=True, required=False, fallback=(env_fallback, ['TOWER_PASSWORD'])), aliases=['tower_host'],
validate_certs=dict(type='bool', aliases=['tower_verify_ssl'], required=False, fallback=(env_fallback, ['TOWER_VERIFY_SSL'])), fallback=(env_fallback, ['CONTROLLER_HOST', 'TOWER_HOST'])),
tower_oauthtoken=dict(type='raw', no_log=True, required=False, fallback=(env_fallback, ['TOWER_OAUTH_TOKEN'])), controller_username=dict(
tower_config_file=dict(type='path', required=False, default=None), required=False,
aliases=['tower_username'],
fallback=(env_fallback, ['CONTROLLER_USERNAME', 'TOWER_USERNAME'])),
controller_password=dict(
no_log=True,
aliases=['tower_password'],
required=False,
fallback=(env_fallback, ['CONTROLLER_PASSWORD', 'TOWER_PASSWORD'])),
validate_certs=dict(
type='bool',
aliases=['tower_verify_ssl'],
required=False,
fallback=(env_fallback, ['CONTROLLER_VERIFY_SSL', 'TOWER_VERIFY_SSL'])),
controller_oauthtoken=dict(
type='raw',
no_log=True,
aliases=['tower_oauthtoken'],
required=False,
fallback=(env_fallback, ['CONTROLLER_OAUTH_TOKEN', 'TOWER_OAUTH_TOKEN'])),
controller_config_file=dict(
type='path',
aliases=['tower_config_file'],
required=False,
default=None),
) )
short_params = { short_params = {
'host': 'tower_host', 'host': 'controller_host',
'username': 'tower_username', 'username': 'controller_username',
'password': 'tower_password', 'password': 'controller_password',
'verify_ssl': 'validate_certs', 'verify_ssl': 'validate_certs',
'oauth_token': 'tower_oauthtoken', 'oauth_token': 'controller_oauthtoken',
} }
host = '127.0.0.1' host = '127.0.0.1'
username = None username = None
@@ -60,7 +83,7 @@ class TowerModule(AnsibleModule):
def __init__(self, argument_spec=None, direct_params=None, error_callback=None, warn_callback=None, **kwargs): def __init__(self, argument_spec=None, direct_params=None, error_callback=None, warn_callback=None, **kwargs):
full_argspec = {} full_argspec = {}
full_argspec.update(TowerModule.AUTH_ARGSPEC) full_argspec.update(ControllerModule.AUTH_ARGSPEC)
full_argspec.update(argument_spec) full_argspec.update(argument_spec)
kwargs['supports_check_mode'] = True kwargs['supports_check_mode'] = True
@@ -72,7 +95,7 @@ class TowerModule(AnsibleModule):
if direct_params is not None: if direct_params is not None:
self.params = direct_params self.params = direct_params
else: else:
super(TowerModule, self).__init__(argument_spec=full_argspec, **kwargs) super().__init__(argument_spec=full_argspec, **kwargs)
self.load_config_files() self.load_config_files()
@@ -82,18 +105,18 @@ class TowerModule(AnsibleModule):
if direct_value is not None: if direct_value is not None:
setattr(self, short_param, direct_value) setattr(self, short_param, direct_value)
# Perform magic depending on whether tower_oauthtoken is a string or a dict # Perform magic depending on whether controller_oauthtoken is a string or a dict
if self.params.get('tower_oauthtoken'): if self.params.get('controller_oauthtoken'):
token_param = self.params.get('tower_oauthtoken') token_param = self.params.get('controller_oauthtoken')
if type(token_param) is dict: if type(token_param) is dict:
if 'token' in token_param: if 'token' in token_param:
self.oauth_token = self.params.get('tower_oauthtoken')['token'] self.oauth_token = self.params.get('controller_oauthtoken')['token']
else: else:
self.fail_json(msg="The provided dict in tower_oauthtoken did not properly contain the token entry") self.fail_json(msg="The provided dict in controller_oauthtoken did not properly contain the token entry")
elif isinstance(token_param, string_types): elif isinstance(token_param, string_types):
self.oauth_token = self.params.get('tower_oauthtoken') self.oauth_token = self.params.get('controller_oauthtoken')
else: else:
error_msg = "The provided tower_oauthtoken type was not valid ({0}). Valid options are str or dict.".format(type(token_param).__name__) error_msg = "The provided controller_oauthtoken type was not valid ({0}). Valid options are str or dict.".format(type(token_param).__name__)
self.fail_json(msg=error_msg) self.fail_json(msg=error_msg)
# Perform some basic validation # Perform some basic validation
@@ -104,14 +127,14 @@ class TowerModule(AnsibleModule):
try: try:
self.url = urlparse(self.host) self.url = urlparse(self.host)
except Exception as e: except Exception as e:
self.fail_json(msg="Unable to parse tower_host as a URL ({1}): {0}".format(self.host, e)) self.fail_json(msg="Unable to parse controller_host as a URL ({1}): {0}".format(self.host, e))
# Try to resolve the hostname # Try to resolve the hostname
hostname = self.url.netloc.split(':')[0] hostname = self.url.netloc.split(':')[0]
try: try:
gethostbyname(hostname) gethostbyname(hostname)
except Exception as e: except Exception as e:
self.fail_json(msg="Unable to resolve tower_host ({1}): {0}".format(hostname, e)) self.fail_json(msg="Unable to resolve controller_host ({1}): {0}".format(hostname, e))
def build_url(self, endpoint, query_params=None): def build_url(self, endpoint, query_params=None):
# Make sure we start with /api/vX # Make sure we start with /api/vX
@@ -140,18 +163,18 @@ class TowerModule(AnsibleModule):
config_files.insert(2, join(local_dir, ".{0}".format(self.config_name))) config_files.insert(2, join(local_dir, ".{0}".format(self.config_name)))
# If we have a specified tower config, load it # If we have a specified tower config, load it
if self.params.get('tower_config_file'): if self.params.get('controller_config_file'):
duplicated_params = [fn for fn in self.AUTH_ARGSPEC if fn != 'tower_config_file' and self.params.get(fn) is not None] duplicated_params = [fn for fn in self.AUTH_ARGSPEC if fn != 'controller_config_file' and self.params.get(fn) is not None]
if duplicated_params: if duplicated_params:
self.warn( self.warn(
( (
'The parameter(s) {0} were provided at the same time as tower_config_file. ' 'The parameter(s) {0} were provided at the same time as controller_config_file. '
'Precedence may be unstable, we suggest either using config file or params.' 'Precedence may be unstable, we suggest either using config file or params.'
).format(', '.join(duplicated_params)) ).format(', '.join(duplicated_params))
) )
try: try:
# TODO: warn if there are conflicts with other params # TODO: warn if there are conflicts with other params
self.load_config(self.params.get('tower_config_file')) self.load_config(self.params.get('controller_config_file'))
except ConfigFileException as cfe: except ConfigFileException as cfe:
# Since we were told specifically to load this we want it to fail if we have an error # Since we were told specifically to load this we want it to fail if we have an error
self.fail_json(msg=cfe) self.fail_json(msg=cfe)
@@ -215,10 +238,10 @@ class TowerModule(AnsibleModule):
pass pass
except Exception as e: except Exception as e:
raise ConfigFileException("An unknown exception occured trying to ini load config file: {0}".format(e)) raise ConfigFileException("An unknown exception occured trying to ini load config file: {0}".format(e)) from e
except Exception as e: except Exception as e:
raise ConfigFileException("An unknown exception occured trying to load config file: {0}".format(e)) raise ConfigFileException("An unknown exception occured trying to load config file: {0}".format(e)) from e
# If we made it here, we have a dict which has values in it from our config, any final settings logic can be performed here # If we made it here, we have a dict which has values in it from our config, any final settings logic can be performed here
for honorred_setting in self.short_params: for honorred_setting in self.short_params:
@@ -242,15 +265,15 @@ class TowerModule(AnsibleModule):
if self.error_callback: if self.error_callback:
self.error_callback(**kwargs) self.error_callback(**kwargs)
else: else:
super(TowerModule, self).fail_json(**kwargs) super().fail_json(**kwargs)
def exit_json(self, **kwargs): def exit_json(self, **kwargs):
# Try to log out if we are authenticated # Try to log out if we are authenticated
self.logout() self.logout()
super(TowerModule, self).exit_json(**kwargs) super().exit_json(**kwargs)
def warn(self, warning): def warn(self, warning):
if self.warn_callback is not None: if self.warn_callback is not None:
self.warn_callback(warning) self.warn_callback(warning)
else: else:
super(TowerModule, self).warn(warning) super().warn(warning)

View File

@@ -113,7 +113,7 @@ class TowerLegacyModule(AnsibleModule):
) )
) )
super(TowerLegacyModule, self).__init__(argument_spec=args, **kwargs) super().__init__(argument_spec=args, **kwargs)
if not HAS_TOWER_CLI: if not HAS_TOWER_CLI:
self.fail_json(msg=missing_required_lib('ansible-tower-cli'), exception=TOWER_CLI_IMP_ERR) self.fail_json(msg=missing_required_lib('ansible-tower-cli'), exception=TOWER_CLI_IMP_ERR)

View File

@@ -14,12 +14,12 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_ad_hoc_command module: ad_hoc_command
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
version_added: "4.0" version_added: "4.0.0"
short_description: create, update, or destroy Ansible Tower ad hoc commands. short_description: create, update, or destroy Automation Platform Controller ad hoc commands.
description: description:
- Create, update, or destroy Ansible Tower ad hoc commands. See - Create, update, or destroy Automation Platform Controller ad hoc commands. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
job_type: job_type:
@@ -84,7 +84,7 @@ options:
type: bool type: bool
interval: interval:
description: description:
- The interval to request an update from Tower. - The interval to request an update from the controller.
default: 1 default: 1
type: float type: float
timeout: timeout:
@@ -111,7 +111,7 @@ status:
sample: pending sample: pending
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -135,7 +135,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
inventory = module.params.get('inventory') inventory = module.params.get('inventory')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_ad_hoc_command_cancel module: ad_hoc_command_cancel
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
short_description: Cancel an Ansible Tower Ad Hoc Command. short_description: Cancel an Ad Hoc Command.
description: description:
- Cancel Ansible Tower ad hoc command. See - Cancel ad hoc command. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
command_id: command_id:
@@ -33,21 +33,21 @@ options:
type: bool type: bool
interval: interval:
description: description:
- The interval in seconds, to request an update from Tower. - The interval in seconds, to request an update from .
required: False required: False
default: 1 default: 1
type: float type: float
timeout: timeout:
description: description:
- Maximum time in seconds to wait for a job to finish. - Maximum time in seconds to wait for a job to finish.
- Not specifying means the task will wait until Tower cancels the command. - Not specifying means the task will wait until the controller cancels the command.
type: int type: int
extends_documentation_fragment: awx.awx.auth extends_documentation_fragment: awx.awx.auth
''' '''
EXAMPLES = ''' EXAMPLES = '''
- name: Cancel command - name: Cancel command
tower_ad_hoc_command_cancel: ad_hoc_command_cancel:
command_id: command.id command_id: command.id
''' '''
@@ -62,7 +62,7 @@ id:
import time import time
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -75,7 +75,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
command_id = module.params.get('command_id') command_id = module.params.get('command_id')
@@ -98,7 +98,7 @@ def main():
cancel_page = module.get_endpoint(command['related']['cancel']) cancel_page = module.get_endpoint(command['related']['cancel'])
if 'json' not in cancel_page or 'can_cancel' not in cancel_page['json']: if 'json' not in cancel_page or 'can_cancel' not in cancel_page['json']:
module.fail_json(msg="Failed to cancel command, got unexpected response from tower", **{'response': cancel_page}) module.fail_json(msg="Failed to cancel command, got unexpected response", **{'response': cancel_page})
if not cancel_page['json']['can_cancel']: if not cancel_page['json']['can_cancel']:
if fail_if_not_running: if fail_if_not_running:

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_ad_hoc_command_wait module: ad_hoc_command_wait
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
short_description: Wait for Ansible Tower Ad Hoc Command to finish. short_description: Wait for Automation Platform Controller Ad Hoc Command to finish.
description: description:
- Wait for Ansible Tower ad hoc command to finish and report success or failure. See - Wait for Automation Platform Controller ad hoc command to finish and report success or failure. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
command_id: command_id:
@@ -28,7 +28,7 @@ options:
type: int type: int
interval: interval:
description: description:
- The interval in sections, to request an update from Tower. - The interval in sections, to request an update from the controller.
required: False required: False
default: 1 default: 1
type: float type: float
@@ -41,14 +41,14 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Launch an ad hoc command - name: Launch an ad hoc command
tower_ad_hoc_command: ad_hoc_command:
inventory: "Demo Inventory" inventory: "Demo Inventory"
credential: "Demo Credential" credential: "Demo Credential"
wait: false wait: false
register: command register: command
- name: Wait for ad joc command max 120s - name: Wait for ad joc command max 120s
tower_ad_hoc_command_wait: ad_hoc_command_wait:
command_id: "{{ command.id }}" command_id: "{{ command.id }}"
timeout: 120 timeout: 120
''' '''
@@ -82,7 +82,7 @@ status:
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -94,7 +94,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
command_id = module.params.get('command_id') command_id = module.params.get('command_id')
@@ -112,7 +112,7 @@ def main():
) )
if command is None: if command is None:
module.fail_json(msg='Unable to wait on ad hoc command {0}; that ID does not exist in Tower.'.format(command_id)) module.fail_json(msg='Unable to wait on ad hoc command {0}; that ID does not exist.'.format(command_id))
# Invoke wait function # Invoke wait function
module.wait_on_url(url=command['url'], object_name=command_id, object_type='ad hoc command', timeout=timeout, interval=interval) module.wait_on_url(url=command['url'], object_name=command_id, object_type='ad hoc command', timeout=timeout, interval=interval)

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_application module: application
author: "Geoffrey Bacheot (@jffz)" author: "Geoffrey Bacheot (@jffz)"
short_description: create, update, or destroy Ansible Tower applications short_description: create, update, or destroy Automation Platform Controller applications
description: description:
- Create, update, or destroy Ansible Tower applications. See - Create, update, or destroy Automation Platform Controller applications. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -69,7 +69,7 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add Foo application - name: Add Foo application
tower_application: application:
name: "Foo" name: "Foo"
description: "Foo bar application" description: "Foo bar application"
organization: "test" organization: "test"
@@ -78,7 +78,7 @@ EXAMPLES = '''
client-type: public client-type: public
- name: Add Foo application - name: Add Foo application
tower_application: application:
name: "Foo" name: "Foo"
description: "Foo bar application" description: "Foo bar application"
organization: "test" organization: "test"
@@ -91,7 +91,7 @@ EXAMPLES = '''
import time import time
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -108,7 +108,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -13,7 +13,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_meta module: controller_meta
author: "Alan Rominger (@alancoding)" author: "Alan Rominger (@alancoding)"
short_description: Returns metadata about the collection this module lives in. short_description: Returns metadata about the collection this module lives in.
description: description:
@@ -49,7 +49,7 @@ version:
EXAMPLES = ''' EXAMPLES = '''
- tower_meta: - controller_meta:
register: result register: result
- name: Show details about the collection - name: Show details about the collection
@@ -57,16 +57,16 @@ EXAMPLES = '''
- name: Load the UI setting without hard-coding the collection name - name: Load the UI setting without hard-coding the collection name
debug: debug:
msg: "{{ lookup(result.prefix + '.tower_api', 'settings/ui') }}" msg: "{{ lookup(result.prefix + '.controller_api', 'settings/ui') }}"
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
module = TowerAPIModule(argument_spec={}) module = ControllerAPIModule(argument_spec={})
namespace = {'awx': 'awx', 'tower': 'ansible'}.get(module._COLLECTION_TYPE, 'unknown') namespace = {'awx': 'awx', 'controller': 'ansible'}.get(module._COLLECTION_TYPE, 'unknown')
namespace_name = '{0}.{1}'.format(namespace, module._COLLECTION_TYPE) namespace_name = '{0}.{1}'.format(namespace, module._COLLECTION_TYPE)
module.exit_json(prefix=namespace_name, name=module._COLLECTION_TYPE, namespace=namespace, version=module._COLLECTION_VERSION) module.exit_json(prefix=namespace_name, name=module._COLLECTION_TYPE, namespace=namespace, version=module._COLLECTION_VERSION)

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_credential module: credential
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower credential. short_description: create, update, or destroy Automation Platform Controller credential.
description: description:
- Create, update, or destroy Ansible Tower credentials. See - Create, update, or destroy Automation Platform Controller credentials. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -56,7 +56,7 @@ options:
description: description:
- >- - >-
Credential inputs where the keys are var names used in templating. Credential inputs where the keys are var names used in templating.
Refer to the Ansible Tower documentation for example syntax. Refer to the Automation Platform Controller documentation for example syntax.
- Any fields in this dict will take prescedence over any fields mentioned below (i.e. host, username, etc) - Any fields in this dict will take prescedence over any fields mentioned below (i.e. host, username, etc)
type: dict type: dict
update_secrets: update_secrets:
@@ -96,7 +96,7 @@ options:
password: password:
description: description:
- Password for this credential. ``secret_key`` for AWS. ``api_key`` for RAX. - Password for this credential. ``secret_key`` for AWS. ``api_key`` for RAX.
- Use "ASK" and launch in Tower to be prompted. - Use "ASK" and launch job to be prompted.
- Deprecated, please use inputs - Deprecated, please use inputs
type: str type: str
project: project:
@@ -112,7 +112,7 @@ options:
ssh_key_unlock: ssh_key_unlock:
description: description:
- Unlock password for ssh_key. - Unlock password for ssh_key.
- Use "ASK" and launch in Tower to be prompted. - Use "ASK" and launch job to be prompted.
- Deprecated, please use inputs - Deprecated, please use inputs
type: str type: str
authorize: authorize:
@@ -120,7 +120,6 @@ options:
- Should use authorize for net type. - Should use authorize for net type.
- Deprecated, please use inputs - Deprecated, please use inputs
type: bool type: bool
default: 'no'
authorize_password: authorize_password:
description: description:
- Password for net credentials that require authorize. - Password for net credentials that require authorize.
@@ -166,19 +165,19 @@ options:
become_username: become_username:
description: description:
- Become username. - Become username.
- Use "ASK" and launch in Tower to be prompted. - Use "ASK" and launch job to be prompted.
- Deprecated, please use inputs - Deprecated, please use inputs
type: str type: str
become_password: become_password:
description: description:
- Become password. - Become password.
- Use "ASK" and launch in Tower to be prompted. - Use "ASK" and launch job to be prompted.
- Deprecated, please use inputs - Deprecated, please use inputs
type: str type: str
vault_password: vault_password:
description: description:
- Vault password. - Vault password.
- Use "ASK" and launch in Tower to be prompted. - Use "ASK" and launch job to be prompted.
- Deprecated, please use inputs - Deprecated, please use inputs
type: str type: str
vault_id: vault_id:
@@ -203,17 +202,17 @@ notes:
EXAMPLES = ''' EXAMPLES = '''
- name: Add tower machine credential - name: Add machine credential
tower_credential: credential:
name: Team Name name: Team Name
description: Team Description description: Team Description
organization: test-org organization: test-org
credential_type: Machine credential_type: Machine
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Create a valid SCM credential from a private_key file - name: Create a valid SCM credential from a private_key file
tower_credential: credential:
name: SCM Credential name: SCM Credential
organization: Default organization: Default
state: present state: present
@@ -229,8 +228,8 @@ EXAMPLES = '''
src: '$HOME/.ssh/aws-private.pem' src: '$HOME/.ssh/aws-private.pem'
register: aws_ssh_key register: aws_ssh_key
- name: Add Credential Into Tower - name: Add Credential
tower_credential: credential:
name: Workshop Credential name: Workshop Credential
credential_type: Machine credential_type: Machine
organization: Default organization: Default
@@ -240,16 +239,16 @@ EXAMPLES = '''
delegate_to: localhost delegate_to: localhost
- name: Add Credential with Custom Credential Type - name: Add Credential with Custom Credential Type
tower_credential: credential:
name: Workshop Credential name: Workshop Credential
credential_type: MyCloudCredential credential_type: MyCloudCredential
organization: Default organization: Default
tower_username: admin controller_username: admin
tower_password: ansible controller_password: ansible
tower_host: https://localhost controller_host: https://localhost
- name: Create a Vaiult credential (example for notes) - name: Create a Vaiult credential (example for notes)
tower_credential: credential:
name: Example password name: Example password
credential_type: Vault credential_type: Vault
organization: Default organization: Default
@@ -258,7 +257,7 @@ EXAMPLES = '''
vault_id: 'My ID' vault_id: 'My ID'
- name: Bad password update (will replace vault_id) - name: Bad password update (will replace vault_id)
tower_credential: credential:
name: Example password name: Example password
credential_type: Vault credential_type: Vault
organization: Default organization: Default
@@ -266,14 +265,14 @@ EXAMPLES = '''
vault_password: 'new_password' vault_password: 'new_password'
- name: Another bad password update (will replace vault_id) - name: Another bad password update (will replace vault_id)
tower_credential: credential:
name: Example password name: Example password
credential_type: Vault credential_type: Vault
organization: Default organization: Default
vault_password: 'new_password' vault_password: 'new_password'
- name: A safe way to update a password and keep vault_id - name: A safe way to update a password and keep vault_id
tower_credential: credential:
name: Example password name: Example password
credential_type: Vault credential_type: Vault
organization: Default organization: Default
@@ -282,14 +281,14 @@ EXAMPLES = '''
vault_id: 'My ID' vault_id: 'My ID'
- name: Copy Credential - name: Copy Credential
tower_credential: credential:
name: Copy password name: Copy password
copy_from: Example password copy_from: Example password
credential_type: Vault credential_type: Vault
organization: Foo organization: Foo
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
KIND_CHOICES = { KIND_CHOICES = {
'aws': 'Amazon Web Services', 'aws': 'Amazon Web Services',
@@ -363,7 +362,7 @@ def main():
authorize=dict(type='bool'), authorize=dict(type='bool'),
authorize_password=dict(no_log=True), authorize_password=dict(no_log=True),
client=dict(), client=dict(),
security_token=dict(), security_token=dict(no_log=False),
secret=dict(no_log=True), secret=dict(no_log=True),
subscription=dict(), subscription=dict(),
tenant=dict(), tenant=dict(),
@@ -378,7 +377,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec, required_one_of=[['kind', 'credential_type']]) module = ControllerAPIModule(argument_spec=argument_spec, required_one_of=[['kind', 'credential_type']])
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')
@@ -395,12 +394,18 @@ def main():
# End backwards compatability # End backwards compatability
state = module.params.get('state') state = module.params.get('state')
# Deprication warnings # Deprecation warnings
for legacy_input in OLD_INPUT_NAMES: for legacy_input in OLD_INPUT_NAMES:
if module.params.get(legacy_input) is not None: if module.params.get(legacy_input) is not None:
module.deprecate(msg='{0} parameter has been deprecated, please use inputs instead'.format(legacy_input), version="ansible.tower:4.0.0") module.deprecate(
collection_name="awx.awx",
msg='{0} parameter has been deprecated, please use inputs instead'.format(legacy_input),
version="4.0.0")
if kind: if kind:
module.deprecate(msg='The kind parameter has been deprecated, please use credential_type instead', version="ansible.tower:4.0.0") module.deprecate(
collection_name="awx.awx",
msg='The kind parameter has been deprecated, please use credential_type instead',
version="4.0.0")
cred_type_id = module.resolve_name_to_id('credential_types', credential_type if credential_type else KIND_CHOICES[kind]) cred_type_id = module.resolve_name_to_id('credential_types', credential_type if credential_type else KIND_CHOICES[kind])
if organization: if organization:

View File

@@ -14,12 +14,12 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_credential_input_source module: credential_input_source
author: "Tom Page (@Tompage1994)" author: "Tom Page (@Tompage1994)"
version_added: "2.3" version_added: "2.3.0"
short_description: create, update, or destroy Ansible Tower credential input sources. short_description: create, update, or destroy Automation Platform Controller credential input sources.
description: description:
- Create, update, or destroy Ansible Tower credential input sources. See - Create, update, or destroy Automation Platform Controller credential input sources. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
description: description:
@@ -58,7 +58,7 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Use CyberArk Lookup credential as password source - name: Use CyberArk Lookup credential as password source
tower_credential_input_source: credential_input_source:
input_field_name: password input_field_name: password
target_credential: new_cred target_credential: new_cred
source_credential: cyberark_lookup source_credential: cyberark_lookup
@@ -69,7 +69,7 @@ EXAMPLES = '''
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -84,7 +84,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
description = module.params.get('description') description = module.params.get('description')

View File

@@ -15,11 +15,11 @@ ANSIBLE_METADATA = {'status': ['preview'], 'supported_by': 'community', 'metadat
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_credential_type module: credential_type
author: "Adrien Fleury (@fleu42)" author: "Adrien Fleury (@fleu42)"
short_description: Create, update, or destroy custom Ansible Tower credential type. short_description: Create, update, or destroy custom Automation Platform Controller credential type.
description: description:
- Create, update, or destroy Ansible Tower credential type. See - Create, update, or destroy Automation Platform Controller credential type. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -42,14 +42,14 @@ options:
inputs: inputs:
description: description:
- >- - >-
Enter inputs using either JSON or YAML syntax. Refer to the Ansible Enter inputs using either JSON or YAML syntax. Refer to the
Tower documentation for example syntax. Automation Platform Controler documentation for example syntax.
type: dict type: dict
injectors: injectors:
description: description:
- >- - >-
Enter injectors using either JSON or YAML syntax. Refer to the Enter injectors using either JSON or YAML syntax. Refer to the
Ansible Tower documentation for example syntax. Automation Platform Controller documentation for example syntax.
type: dict type: dict
state: state:
description: description:
@@ -62,16 +62,16 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- tower_credential_type: - credential_type:
name: Nexus name: Nexus
description: Credentials type for Nexus description: Credentials type for Nexus
kind: cloud kind: cloud
inputs: "{{ lookup('file', 'tower_credential_inputs_nexus.json') }}" inputs: "{{ lookup('file', 'credential_inputs_nexus.json') }}"
injectors: {'extra_vars': {'nexus_credential': 'test' }} injectors: {'extra_vars': {'nexus_credential': 'test' }}
state: present state: present
validate_certs: false validate_certs: false
- tower_credential_type: - credential_type:
name: Nexus name: Nexus
state: absent state: absent
''' '''
@@ -80,7 +80,7 @@ EXAMPLES = '''
RETURN = ''' # ''' RETURN = ''' # '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
KIND_CHOICES = {'ssh': 'Machine', 'vault': 'Ansible Vault', 'net': 'Network', 'scm': 'Source Control', 'cloud': 'Lots of others', 'insights': 'Insights'} KIND_CHOICES = {'ssh': 'Machine', 'vault': 'Ansible Vault', 'net': 'Network', 'scm': 'Source Control', 'cloud': 'Lots of others', 'insights': 'Insights'}
@@ -97,7 +97,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_execution_environment module: execution_environment
author: "Shane McDonald (@shanemcd)" author: "Shane McDonald (@shanemcd)"
short_description: create, update, or destroy Execution Environments in Ansible Tower. short_description: create, update, or destroy Execution Environments in Automation Platform Controller.
description: description:
- Create, update, or destroy Execution Environments in Ansible Tower. See - Create, update, or destroy Execution Environments in Automation Platform Controller. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -60,14 +60,14 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add EE to Tower - name: Add EE to the controller instance
tower_execution_environment: execution_environment:
name: "My EE" name: "My EE"
image: quay.io/ansible/awx-ee image: quay.io/ansible/awx-ee
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import json import json
@@ -84,7 +84,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,12 +14,12 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_export module: export
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
version_added: "3.7" version_added: "3.7.0"
short_description: export resources from Ansible Tower. short_description: export resources from Automation Platform Controller.
description: description:
- Export assets from Ansible Tower. - Export assets from Automation Platform Controller.
options: options:
all: all:
description: description:
@@ -82,16 +82,16 @@ extends_documentation_fragment: awx.awx.auth
''' '''
EXAMPLES = ''' EXAMPLES = '''
- name: Export all tower assets - name: Export all assets
tower_export: export:
all: True all: True
- name: Export all inventories - name: Export all inventories
tower_export: export:
inventory: 'all' inventory: 'all'
- name: Export a job template named "My Template" and all Credentials - name: Export a job template named "My Template" and all Credentials
tower_export: export:
job_template: "My Template" job_template: "My Template"
credential: 'all' credential: 'all'
''' '''
@@ -99,7 +99,7 @@ EXAMPLES = '''
from os import environ from os import environ
import logging import logging
from ansible.module_utils.six.moves import StringIO from ansible.module_utils.six.moves import StringIO
from ..module_utils.tower_awxkit import TowerAWXKitModule from ..module_utils.awxkit import ControllerAWXKitModule
try: try:
from awxkit.api.pages.api import EXPORTABLE_RESOURCES from awxkit.api.pages.api import EXPORTABLE_RESOURCES
@@ -112,19 +112,31 @@ except ImportError:
def main(): def main():
argument_spec = dict( argument_spec = dict(
all=dict(type='bool', default=False), all=dict(type='bool', default=False),
credential_types=dict(type='str'),
credentials=dict(type='str'),
execution_environments=dict(type='str'),
inventory=dict(type='str'),
inventory_sources=dict(type='str'),
job_templates=dict(type='str'),
notification_templates=dict(type='str'),
organizations=dict(type='str'),
projects=dict(type='str'),
teams=dict(type='str'),
users=dict(type='str'),
workflow_job_templates=dict(type='str'),
) )
# We are not going to raise an error here because the __init__ method of TowerAWXKitModule will do that for us # We are not going to raise an error here because the __init__ method of ControllerAWXKitModule will do that for us
if HAS_EXPORTABLE_RESOURCES: if HAS_EXPORTABLE_RESOURCES:
for resource in EXPORTABLE_RESOURCES: for resource in EXPORTABLE_RESOURCES:
argument_spec[resource] = dict(type='str') argument_spec[resource] = dict(type='str')
module = TowerAWXKitModule(argument_spec=argument_spec) module = ControllerAWXKitModule(argument_spec=argument_spec)
if not HAS_EXPORTABLE_RESOURCES: if not HAS_EXPORTABLE_RESOURCES:
module.fail_json(msg="Your version of awxkit does not have import/export") module.fail_json(msg="Your version of awxkit does not have import/export")
# The export process will never change a Tower system # The export process will never change the AWX system
module.json_output['changed'] = False module.json_output['changed'] = False
# The exporter code currently works like the following: # The exporter code currently works like the following:

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_group module: group
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower group. short_description: create, update, or destroy Automation Platform Controller group.
description: description:
- Create, update, or destroy Ansible Tower groups. See - Create, update, or destroy Automation Platform Controller groups. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -53,12 +53,12 @@ options:
- groups - groups
preserve_existing_hosts: preserve_existing_hosts:
description: description:
- Provide option (False by default) to preserves existing hosts in an existing group in tower. - Provide option (False by default) to preserves existing hosts in an existing group.
default: False default: False
type: bool type: bool
preserve_existing_children: preserve_existing_children:
description: description:
- Provide option (False by default) to preserves existing children in an existing group in tower. - Provide option (False by default) to preserves existing children in an existing group.
default: False default: False
type: bool type: bool
aliases: aliases:
@@ -78,16 +78,16 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add tower group - name: Add group
tower_group: group:
name: localhost name: localhost
description: "Local Host Group" description: "Local Host Group"
inventory: "Local Inventory" inventory: "Local Inventory"
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add tower group - name: Add group
tower_group: group:
name: Cities name: Cities
description: "Local Host Group" description: "Local Host Group"
inventory: Default Inventory inventory: Default Inventory
@@ -99,7 +99,7 @@ EXAMPLES = '''
preserve_existing_children: True preserve_existing_children: True
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import json import json
@@ -119,7 +119,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_host module: host
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower host. short_description: create, update, or destroy Automation Platform Controller host.
description: description:
- Create, update, or destroy Ansible Tower hosts. See - Create, update, or destroy Automation Platform Controller hosts. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -59,19 +59,19 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add tower host - name: Add host
tower_host: host:
name: localhost name: localhost
description: "Local Host Group" description: "Local Host Group"
inventory: "Local Inventory" inventory: "Local Inventory"
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
variables: variables:
example_var: 123 example_var: 123
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import json import json
@@ -88,7 +88,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,18 +14,18 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_import module: import
author: "John Westcott (@john-westcott-iv)" author: "John Westcott (@john-westcott-iv)"
version_added: "3.7" version_added: "3.7.0"
short_description: import resources into Ansible Tower. short_description: import resources into Automation Platform Controller.
description: description:
- Import assets into Ansible Tower. See - Import assets into Automation Platform Controller. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
assets: assets:
description: description:
- The assets to import. - The assets to import.
- This can be the output of tower_export or loaded from a file - This can be the output of the export module or loaded from a file
required: True required: True
type: dict type: dict
requirements: requirements:
@@ -35,20 +35,20 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Export all assets - name: Export all assets
tower_export: export:
all: True all: True
register: export_output register: export_output
- name: Import all tower assets from our export - name: Import all assets from our export
tower_import: import:
assets: "{{ export_output.assets }}" assets: "{{ export_output.assets }}"
- name: Load data from a json file created by a command like awx export --organization Default - name: Load data from a json file created by a command like awx export --organization Default
tower_import: import:
assets: "{{ lookup('file', 'org.json') | from_json() }}" assets: "{{ lookup('file', 'org.json') | from_json() }}"
''' '''
from ..module_utils.tower_awxkit import TowerAWXKitModule from ..module_utils.awxkit import ControllerAWXKitModule
# These two lines are not needed if awxkit changes to do programatic notifications on issues # These two lines are not needed if awxkit changes to do programatic notifications on issues
from ansible.module_utils.six.moves import StringIO from ansible.module_utils.six.moves import StringIO
@@ -66,7 +66,7 @@ except ImportError:
def main(): def main():
argument_spec = dict(assets=dict(type='dict', required=True)) argument_spec = dict(assets=dict(type='dict', required=True))
module = TowerAWXKitModule(argument_spec=argument_spec, supports_check_mode=False) module = ControllerAWXKitModule(argument_spec=argument_spec, supports_check_mode=False)
assets = module.params.get('assets') assets = module.params.get('assets')

View File

@@ -14,12 +14,12 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_instance_group module: instance_group
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
version_added: "4.0" version_added: "4.0.0"
short_description: create, update, or destroy Ansible Tower instance groups. short_description: create, update, or destroy Automation Platform Controller instance groups.
description: description:
- Create, update, or destroy Ansible Tower instance groups. See - Create, update, or destroy Automation Platform Controller instance groups. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -41,6 +41,7 @@ options:
- Signifies that this InstanceGroup should act as a ContainerGroup. If no credential is specified, the underlying Pod's ServiceAccount will be used. - Signifies that this InstanceGroup should act as a ContainerGroup. If no credential is specified, the underlying Pod's ServiceAccount will be used.
required: False required: False
type: bool type: bool
default: False
policy_instance_percentage: policy_instance_percentage:
description: description:
- Minimum percentage of all instances that will be automatically assigned to this group when new instances come online. - Minimum percentage of all instances that will be automatically assigned to this group when new instances come online.
@@ -58,6 +59,7 @@ options:
- List of exact-match Instances that will be assigned to this group - List of exact-match Instances that will be assigned to this group
required: False required: False
type: list type: list
elements: str
pod_spec_override: pod_spec_override:
description: description:
- A custom Kubernetes or OpenShift Pod specification. - A custom Kubernetes or OpenShift Pod specification.
@@ -68,6 +70,7 @@ options:
- The instances associated with this instance_group - The instances associated with this instance_group
required: False required: False
type: list type: list
elements: str
state: state:
description: description:
- Desired state of the resource. - Desired state of the resource.
@@ -80,7 +83,7 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -92,14 +95,14 @@ def main():
is_container_group=dict(type='bool', default=False), is_container_group=dict(type='bool', default=False),
policy_instance_percentage=dict(type='int', default='0'), policy_instance_percentage=dict(type='int', default='0'),
policy_instance_minimum=dict(type='int', default='0'), policy_instance_minimum=dict(type='int', default='0'),
policy_instance_list=dict(type='list'), policy_instance_list=dict(type='list', elements='str'),
pod_spec_override=dict(), pod_spec_override=dict(),
instances=dict(required=False, type="list", default=None), instances=dict(required=False, type="list", elements='str', default=None),
state=dict(choices=['present', 'absent'], default='present'), state=dict(choices=['present', 'absent'], default='present'),
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_inventory module: inventory
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower inventory. short_description: create, update, or destroy Automation Platform Controller inventory.
description: description:
- Create, update, or destroy Ansible Tower inventories. See - Create, update, or destroy Automation Platform Controller inventories. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -77,16 +77,16 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add tower inventory - name: Add inventory
tower_inventory: inventory:
name: "Foo Inventory" name: "Foo Inventory"
description: "Our Foo Cloud Servers" description: "Our Foo Cloud Servers"
organization: "Bar Org" organization: "Bar Org"
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Copy tower inventory - name: Copy inventory
tower_inventory: inventory:
name: Copy Foo Inventory name: Copy Foo Inventory
copy_from: Default Inventory copy_from: Default Inventory
description: "Our Foo Cloud Servers" description: "Our Foo Cloud Servers"
@@ -95,7 +95,7 @@ EXAMPLES = '''
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import json import json
@@ -115,7 +115,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_inventory_source module: inventory_source
author: "Adrien Fleury (@fleu42)" author: "Adrien Fleury (@fleu42)"
short_description: create, update, or destroy Ansible Tower inventory source. short_description: create, update, or destroy Automation Platform Controller inventory source.
description: description:
- Create, update, or destroy Ansible Tower inventory source. See - Create, update, or destroy Automation Platform Controller inventory source. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -138,7 +138,7 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add an inventory source - name: Add an inventory source
tower_inventory_source: inventory_source:
name: "source-inventory" name: "source-inventory"
description: Source for inventory description: Source for inventory
inventory: previously-created-inventory inventory: previously-created-inventory
@@ -150,7 +150,7 @@ EXAMPLES = '''
private: false private: false
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
from json import dumps from json import dumps
@@ -162,7 +162,7 @@ def main():
description=dict(), description=dict(),
inventory=dict(required=True), inventory=dict(required=True),
# #
# How do we handle manual and file? Tower does not seem to be able to activate them # How do we handle manual and file? The controller does not seem to be able to activate them
# #
source=dict(choices=["scm", "ec2", "gce", "azure_rm", "vmware", "satellite6", "openstack", "rhv", "tower"]), source=dict(choices=["scm", "ec2", "gce", "azure_rm", "vmware", "satellite6", "openstack", "rhv", "tower"]),
source_path=dict(), source_path=dict(),
@@ -189,7 +189,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_inventory_source_update module: inventory_source_update
author: "Bianca Henderson (@beeankha)" author: "Bianca Henderson (@beeankha)"
short_description: Update inventory source(s). short_description: Update inventory source(s).
description: description:
- Update Ansible Tower inventory source(s). See - Update Automation Platform Controller inventory source(s). See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -44,7 +44,7 @@ options:
type: bool type: bool
interval: interval:
description: description:
- The interval to request an update from Tower. - The interval to request an update from the controller.
required: False required: False
default: 1 default: 1
type: float type: float
@@ -58,16 +58,16 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Update a single inventory source - name: Update a single inventory source
tower_inventory_source_update: inventory_source_update:
name: "Example Inventory Source" name: "Example Inventory Source"
inventory: "My Inventory" inventory: "My Inventory"
organization: Default organization: Default
- name: Update all inventory sources - name: Update all inventory sources
tower_inventory_source_update: inventory_source_update:
name: "{{ item }}" name: "{{ item }}"
inventory: "My Other Inventory" inventory: "My Other Inventory"
loop: "{{ query('awx.awx.tower_api', 'inventory_sources', query_params={ 'inventory': 30 }, return_ids=True ) }}" loop: "{{ query('awx.awx.controller_api', 'inventory_sources', query_params={ 'inventory': 30 }, return_ids=True ) }}"
''' '''
RETURN = ''' RETURN = '''
@@ -83,7 +83,7 @@ status:
sample: pending sample: pending
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -98,7 +98,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_job_cancel module: job_cancel
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: Cancel an Ansible Tower Job. short_description: Cancel an Automation Platform Controller Job.
description: description:
- Cancel Ansible Tower jobs. See - Cancel Automation Platform Controller jobs. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
job_id: job_id:
@@ -36,7 +36,7 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Cancel job - name: Cancel job
tower_job_cancel: job_cancel:
job_id: job.id job_id: job.id
''' '''
@@ -49,7 +49,7 @@ id:
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -60,7 +60,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
job_id = module.params.get('job_id') job_id = module.params.get('job_id')
@@ -81,7 +81,7 @@ def main():
cancel_page = module.get_endpoint(job['related']['cancel']) cancel_page = module.get_endpoint(job['related']['cancel'])
if 'json' not in cancel_page or 'can_cancel' not in cancel_page['json']: if 'json' not in cancel_page or 'can_cancel' not in cancel_page['json']:
module.fail_json(msg="Failed to cancel job, got unexpected response from tower", **{'response': cancel_page}) module.fail_json(msg="Failed to cancel job, got unexpected response from the controller", **{'response': cancel_page})
if not cancel_page['json']['can_cancel']: if not cancel_page['json']['can_cancel']:
if fail_if_not_running: if fail_if_not_running:

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_job_launch module: job_launch
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: Launch an Ansible Job. short_description: Launch an Ansible Job.
description: description:
- Launch an Ansible Tower jobs. See - Launch an Automation Platform Controller jobs. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -51,7 +51,7 @@ options:
extra_vars: extra_vars:
description: description:
- extra_vars to use for the Job Template. - extra_vars to use for the Job Template.
- ask_extra_vars needs to be set to True via tower_job_template module - ask_extra_vars needs to be set to True via job_template module
when creating the Job Template. when creating the Job Template.
type: dict type: dict
limit: limit:
@@ -93,7 +93,7 @@ options:
type: bool type: bool
interval: interval:
description: description:
- The interval to request an update from Tower. - The interval to request an update from the controller.
required: False required: False
default: 1 default: 1
type: float type: float
@@ -107,12 +107,12 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Launch a job - name: Launch a job
tower_job_launch: job_launch:
job_template: "My Job Template" job_template: "My Job Template"
register: job register: job
- name: Launch a job template with extra_vars on remote Tower instance - name: Launch a job template with extra_vars on remote controller instance
tower_job_launch: job_launch:
job_template: "My Job Template" job_template: "My Job Template"
extra_vars: extra_vars:
var1: "My First Variable" var1: "My First Variable"
@@ -121,13 +121,13 @@ EXAMPLES = '''
job_type: run job_type: run
- name: Launch a job with inventory and credential - name: Launch a job with inventory and credential
tower_job_launch: job_launch:
job_template: "My Job Template" job_template: "My Job Template"
inventory: "My Inventory" inventory: "My Inventory"
credential: "My Credential" credential: "My Credential"
register: job register: job
- name: Wait for job max 120s - name: Wait for job max 120s
tower_job_wait: job_wait:
job_id: "{{ job.id }}" job_id: "{{ job.id }}"
timeout: 120 timeout: 120
''' '''
@@ -145,7 +145,7 @@ status:
sample: pending sample: pending
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -164,14 +164,14 @@ def main():
skip_tags=dict(type='list', elements='str'), skip_tags=dict(type='list', elements='str'),
verbosity=dict(type='int', choices=[0, 1, 2, 3, 4, 5]), verbosity=dict(type='int', choices=[0, 1, 2, 3, 4, 5]),
diff_mode=dict(type='bool'), diff_mode=dict(type='bool'),
credential_passwords=dict(type='dict'), credential_passwords=dict(type='dict', no_log=False),
wait=dict(default=False, type='bool'), wait=dict(default=False, type='bool'),
interval=dict(default=1.0, type='float'), interval=dict(default=1.0, type='float'),
timeout=dict(default=None, type='int'), timeout=dict(default=None, type='int'),
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
optional_args = {} optional_args = {}
# Extract our parameters # Extract our parameters

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_job_list module: job_list
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: List Ansible Tower jobs. short_description: List Automation Platform Controller jobs.
description: description:
- List Ansible Tower jobs. See - List Automation Platform Controller jobs. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
status: status:
@@ -45,10 +45,10 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: List running jobs for the testing.yml playbook - name: List running jobs for the testing.yml playbook
tower_job_list: job_list:
status: running status: running
query: {"playbook": "testing.yml"} query: {"playbook": "testing.yml"}
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
register: testing_jobs register: testing_jobs
''' '''
@@ -79,7 +79,7 @@ results:
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -92,7 +92,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule( module = ControllerAPIModule(
argument_spec=argument_spec, argument_spec=argument_spec,
mutually_exclusive=[ mutually_exclusive=[
('page', 'all_pages'), ('page', 'all_pages'),

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_job_template module: job_template
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower job templates. short_description: create, update, or destroy Automation Platform Controller job templates.
description: description:
- Create, update, or destroy Ansible Tower job templates. See - Create, update, or destroy Automation Platform Controller job templates. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -57,7 +57,7 @@ options:
- Used to help lookup the object, cannot be modified using this module. - Used to help lookup the object, cannot be modified using this module.
- The Organization is inferred from the associated project - The Organization is inferred from the associated project
- If not provided, will lookup by name only, which does not work with duplicates. - If not provided, will lookup by name only, which does not work with duplicates.
- Requires Tower Version 3.7.0 or AWX 10.0.0 IS NOT backwards compatible with earlier versions. - Requires Automation Platform Version 3.7.0 or AWX 10.0.0 IS NOT backwards compatible with earlier versions.
type: str type: str
project: project:
description: description:
@@ -140,12 +140,10 @@ options:
type: bool type: bool
aliases: aliases:
- diff_mode_enabled - diff_mode_enabled
default: 'no'
use_fact_cache: use_fact_cache:
description: description:
- Enable use of fact caching for the job template. - Enable use of fact caching for the job template.
type: bool type: bool
default: 'no'
aliases: aliases:
- fact_caching_enabled - fact_caching_enabled
host_config_key: host_config_key:
@@ -156,75 +154,64 @@ options:
description: description:
- Prompt user for (scm branch) on launch. - Prompt user for (scm branch) on launch.
type: bool type: bool
default: 'False'
ask_diff_mode_on_launch: ask_diff_mode_on_launch:
description: description:
- Prompt user to enable diff mode (show changes) to files when supported by modules. - Prompt user to enable diff mode (show changes) to files when supported by modules.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_diff_mode - ask_diff_mode
ask_variables_on_launch: ask_variables_on_launch:
description: description:
- Prompt user for (extra_vars) on launch. - Prompt user for (extra_vars) on launch.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_extra_vars - ask_extra_vars
ask_limit_on_launch: ask_limit_on_launch:
description: description:
- Prompt user for a limit on launch. - Prompt user for a limit on launch.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_limit - ask_limit
ask_tags_on_launch: ask_tags_on_launch:
description: description:
- Prompt user for job tags on launch. - Prompt user for job tags on launch.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_tags - ask_tags
ask_skip_tags_on_launch: ask_skip_tags_on_launch:
description: description:
- Prompt user for job tags to skip on launch. - Prompt user for job tags to skip on launch.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_skip_tags - ask_skip_tags
ask_job_type_on_launch: ask_job_type_on_launch:
description: description:
- Prompt user for job type on launch. - Prompt user for job type on launch.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_job_type - ask_job_type
ask_verbosity_on_launch: ask_verbosity_on_launch:
description: description:
- Prompt user to choose a verbosity level on launch. - Prompt user to choose a verbosity level on launch.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_verbosity - ask_verbosity
ask_inventory_on_launch: ask_inventory_on_launch:
description: description:
- Prompt user for inventory on launch. - Prompt user for inventory on launch.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_inventory - ask_inventory
ask_credential_on_launch: ask_credential_on_launch:
description: description:
- Prompt user for credential on launch. - Prompt user for credential on launch.
type: bool type: bool
default: 'False'
aliases: aliases:
- ask_credential - ask_credential
survey_enabled: survey_enabled:
description: description:
- Enable a survey on the job template. - Enable a survey on the job template.
type: bool type: bool
default: 'no'
survey_spec: survey_spec:
description: description:
- JSON/YAML dict formatted survey definition. - JSON/YAML dict formatted survey definition.
@@ -233,12 +220,10 @@ options:
description: description:
- Activate privilege escalation. - Activate privilege escalation.
type: bool type: bool
default: 'no'
allow_simultaneous: allow_simultaneous:
description: description:
- Allow simultaneous runs of the job template. - Allow simultaneous runs of the job template.
type: bool type: bool
default: 'no'
aliases: aliases:
- concurrent_jobs_enabled - concurrent_jobs_enabled
timeout: timeout:
@@ -297,15 +282,15 @@ options:
extends_documentation_fragment: awx.awx.auth extends_documentation_fragment: awx.awx.auth
notes: notes:
- JSON for survey_spec can be found in Tower API Documentation. See - JSON for survey_spec can be found in the 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) 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. for POST operation payload example.
''' '''
EXAMPLES = ''' EXAMPLES = '''
- name: Create Tower Ping job template - name: Create Ping job template
tower_job_template: job_template:
name: "Ping" name: "Ping"
job_type: "run" job_type: "run"
organization: "Default" organization: "Default"
@@ -315,25 +300,25 @@ EXAMPLES = '''
credentials: credentials:
- "Local" - "Local"
state: "present" state: "present"
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
survey_enabled: yes survey_enabled: yes
survey_spec: "{{ lookup('file', 'my_survey.json') }}" survey_spec: "{{ lookup('file', 'my_survey.json') }}"
- name: Add start notification to Job Template - name: Add start notification to Job Template
tower_job_template: job_template:
name: "Ping" name: "Ping"
notification_templates_started: notification_templates_started:
- Notification1 - Notification1
- Notification2 - Notification2
- name: Remove Notification1 start notification from Job Template - name: Remove Notification1 start notification from Job Template
tower_job_template: job_template:
name: "Ping" name: "Ping"
notification_templates_started: notification_templates_started:
- Notification2 - Notification2
- name: Copy Job Template - name: Copy Job Template
tower_job_template: job_template:
name: copy job template name: copy job template
copy_from: test job template copy_from: test job template
job_type: "run" job_type: "run"
@@ -343,7 +328,7 @@ EXAMPLES = '''
state: "present" state: "present"
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import json import json
@@ -389,7 +374,7 @@ def main():
start_at_task=dict(), start_at_task=dict(),
timeout=dict(type='int', default=0), timeout=dict(type='int', default=0),
use_fact_cache=dict(type='bool', aliases=['fact_caching_enabled']), use_fact_cache=dict(type='bool', aliases=['fact_caching_enabled']),
host_config_key=dict(), host_config_key=dict(no_log=False),
ask_diff_mode_on_launch=dict(type='bool', aliases=['ask_diff_mode']), ask_diff_mode_on_launch=dict(type='bool', aliases=['ask_diff_mode']),
ask_variables_on_launch=dict(type='bool', aliases=['ask_extra_vars']), ask_variables_on_launch=dict(type='bool', aliases=['ask_extra_vars']),
ask_limit_on_launch=dict(type='bool', aliases=['ask_limit']), ask_limit_on_launch=dict(type='bool', aliases=['ask_limit']),
@@ -417,7 +402,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')
@@ -534,7 +519,7 @@ def main():
} }
) )
if project_data is None: if project_data is None:
module.fail_json(msg="The project {0} in organization {1} was not found on the Tower server".format(project, organization)) module.fail_json(msg="The project {0} in organization {1} was not found on the controller instance server".format(project, organization))
new_fields['project'] = project_data['id'] new_fields['project'] = project_data['id']
else: else:
new_fields['project'] = module.resolve_name_to_id('projects', project) new_fields['project'] = module.resolve_name_to_id('projects', project)

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_job_wait module: job_wait
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: Wait for Ansible Tower job to finish. short_description: Wait for Automation Platform Controller job to finish.
description: description:
- Wait for Ansible Tower job to finish and report success or failure. See - Wait for Automation Platform Controller job to finish and report success or failure. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
job_id: job_id:
@@ -28,19 +28,19 @@ options:
type: int type: int
interval: interval:
description: description:
- The interval in sections, to request an update from Tower. - The interval in sections, to request an update from the controller.
- For backwards compatibility if unset this will be set to the average of min and max intervals - For backwards compatibility if unset this will be set to the average of min and max intervals
required: False required: False
default: 1 default: 1
type: float type: float
min_interval: min_interval:
description: description:
- Minimum interval in seconds, to request an update from Tower. - Minimum interval in seconds, to request an update from the controller.
- deprecated, use interval instead - deprecated, use interval instead
type: float type: float
max_interval: max_interval:
description: description:
- Maximum interval in seconds, to request an update from Tower. - Maximum interval in seconds, to request an update from the controller.
- deprecated, use interval instead - deprecated, use interval instead
type: float type: float
timeout: timeout:
@@ -58,12 +58,12 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Launch a job - name: Launch a job
tower_job_launch: job_launch:
job_template: "My Job Template" job_template: "My Job Template"
register: job register: job
- name: Wait for job max 120s - name: Wait for job max 120s
tower_job_wait: job_wait:
job_id: "{{ job.id }}" job_id: "{{ job.id }}"
timeout: 120 timeout: 120
''' '''
@@ -97,7 +97,7 @@ status:
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -112,7 +112,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
job_id = module.params.get('job_id') job_id = module.params.get('job_id')
@@ -132,8 +132,9 @@ def main():
max_interval = 30 max_interval = 30
interval = abs((min_interval + max_interval) / 2) interval = abs((min_interval + max_interval) / 2)
module.deprecate( module.deprecate(
collection_name="awx.awx",
msg="Min and max interval have been deprecated, please use interval instead; interval will be set to {0}".format(interval), msg="Min and max interval have been deprecated, please use interval instead; interval will be set to {0}".format(interval),
version="ansible.tower:4.0.0", version="4.0.0",
) )
# Attempt to look up job based on the provided id # Attempt to look up job based on the provided id
@@ -147,7 +148,7 @@ def main():
) )
if job is None: if job is None:
module.fail_json(msg='Unable to wait on ' + job_type.rstrip("s") + ' {0}; that ID does not exist in Tower.'.format(job_id)) module.fail_json(msg='Unable to wait on ' + job_type.rstrip("s") + ' {0}; that ID does not exist.'.format(job_id))
# Invoke wait function # Invoke wait function
result = module.wait_on_url(url=job['url'], object_name=job_id, object_type='legacy_job_wait', timeout=timeout, interval=interval) result = module.wait_on_url(url=job['url'], object_name=job_id, object_type='legacy_job_wait', timeout=timeout, interval=interval)

View File

@@ -14,13 +14,13 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_label module: label
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower labels. short_description: create, update, or destroy Automation Platform Controller labels.
description: description:
- Create, update, or destroy Ansible Tower labels. See - Create, update, or destroy Automation Platform Controller labels. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
- Note, labels can only be created via the Tower API, they can not be deleted. - Note, labels can only be created via the API, they can not be deleted.
Once they are fully disassociated the API will clean them up on its own. Once they are fully disassociated the API will clean them up on its own.
options: options:
name: name:
@@ -47,13 +47,13 @@ extends_documentation_fragment: awx.awx.auth
''' '''
EXAMPLES = ''' EXAMPLES = '''
- name: Add label to tower organization - name: Add label to organization
tower_label: label:
name: Custom Label name: Custom Label
organization: My Organization organization: My Organization
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -66,7 +66,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -13,11 +13,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_license module: license
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
short_description: Set the license for Ansible Tower short_description: Set the license for Automation Platform Controller
description: description:
- Get or Set Ansible Tower license. See - Get or Set Automation Platform Controller license. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
manifest: manifest:
@@ -29,7 +29,6 @@ options:
description: description:
- By default, the license manifest will only be applied if Tower is currently - By default, the license manifest will only be applied if Tower is currently
unlicensed or trial licensed. When force=true, the license is always applied. unlicensed or trial licensed. When force=true, the license is always applied.
required: True
type: bool type: bool
default: 'False' default: 'False'
extends_documentation_fragment: awx.awx.auth extends_documentation_fragment: awx.awx.auth
@@ -39,20 +38,20 @@ RETURN = ''' # '''
EXAMPLES = ''' EXAMPLES = '''
- name: Set the license using a file - name: Set the license using a file
tower_license: license:
manifest: "/tmp/my_manifest.zip" manifest: "/tmp/my_manifest.zip"
''' '''
import base64 import base64
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
module = TowerAPIModule( module = ControllerAPIModule(
argument_spec=dict( argument_spec=dict(
manifest=dict(type='str', required=True), manifest=dict(type='str', required=True),
force=dict(type='bool', required=False), force=dict(type='bool', default=False),
), ),
) )

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_notification_template module: notification_template
author: "Samuel Carpentier (@samcarpentier)" author: "Samuel Carpentier (@samcarpentier)"
short_description: create, update, or destroy Ansible Tower notification. short_description: create, update, or destroy Automation Platform Controller notification.
description: description:
- Create, update, or destroy Ansible Tower notifications. See - Create, update, or destroy Automation Platform Controller notifications. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -210,7 +210,7 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add Slack notification with custom messages - name: Add Slack notification with custom messages
tower_notification_template: notification_template:
name: slack notification name: slack notification
organization: Default organization: Default
notification_type: slack notification_type: slack
@@ -226,10 +226,10 @@ EXAMPLES = '''
error: error:
message: "{{ '{{ job_friendly_name }} FAILED! Please look at {{ job.url }}' }}" message: "{{ '{{ job_friendly_name }} FAILED! Please look at {{ job.url }}' }}"
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add webhook notification - name: Add webhook notification
tower_notification_template: notification_template:
name: webhook notification name: webhook notification
notification_type: webhook notification_type: webhook
notification_configuration: notification_configuration:
@@ -237,16 +237,16 @@ EXAMPLES = '''
headers: headers:
X-Custom-Header: value123 X-Custom-Header: value123
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add email notification - name: Add email notification
tower_notification_template: notification_template:
name: email notification name: email notification
notification_type: email notification_type: email
notification_configuration: notification_configuration:
username: user username: user
password: s3cr3t password: s3cr3t
sender: tower@example.com sender: controller@example.com
recipients: recipients:
- user1@example.com - user1@example.com
host: smtp.example.com host: smtp.example.com
@@ -254,10 +254,10 @@ EXAMPLES = '''
use_tls: no use_tls: no
use_ssl: no use_ssl: no
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add twilio notification - name: Add twilio notification
tower_notification_template: notification_template:
name: twilio notification name: twilio notification
notification_type: twilio notification_type: twilio
notification_configuration: notification_configuration:
@@ -267,10 +267,10 @@ EXAMPLES = '''
to_numbers: to_numbers:
- '+15553334444' - '+15553334444'
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add PagerDuty notification - name: Add PagerDuty notification
tower_notification_template: notification_template:
name: pagerduty notification name: pagerduty notification
notification_type: pagerduty notification_type: pagerduty
notification_configuration: notification_configuration:
@@ -279,14 +279,14 @@ EXAMPLES = '''
client_name: client client_name: client
service_key: a_key service_key: a_key
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add IRC notification - name: Add IRC notification
tower_notification_template: notification_template:
name: irc notification name: irc notification
notification_type: irc notification_type: irc
notification_configuration: notification_configuration:
nickname: tower nickname: controller
password: s3cr3t password: s3cr3t
targets: targets:
- user1 - user1
@@ -294,16 +294,16 @@ EXAMPLES = '''
server: irc.example.com server: irc.example.com
use_ssl: no use_ssl: no
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Delete notification - name: Delete notification
tower_notification_template: notification_template:
name: old notification name: old notification
state: absent state: absent
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Copy webhook notification - name: Copy webhook notification
tower_notification_template: notification_template:
name: foo notification name: foo notification
copy_from: email notification copy_from: email notification
organization: Foo organization: Foo
@@ -313,7 +313,7 @@ EXAMPLES = '''
RETURN = ''' # ''' RETURN = ''' # '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
OLD_INPUT_NAMES = ( OLD_INPUT_NAMES = (
'username', 'username',
@@ -384,7 +384,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')
@@ -401,7 +401,9 @@ def main():
for legacy_input in OLD_INPUT_NAMES: for legacy_input in OLD_INPUT_NAMES:
if module.params.get(legacy_input) is not None: if module.params.get(legacy_input) is not None:
module.deprecate( module.deprecate(
msg='{0} parameter has been deprecated, please use notification_configuration instead'.format(legacy_input), version="ansible.tower:4.0.0" collection_name="awx.awx",
msg='{0} parameter has been deprecated, please use notification_configuration instead'.format(legacy_input),
version="4.0.0"
) )
# Attempt to look up the related items the user specified (these will fail the module if not found) # Attempt to look up the related items the user specified (these will fail the module if not found)

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_organization module: organization
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower organizations short_description: create, update, or destroy Automation Platform Controller organizations
description: description:
- Create, update, or destroy Ansible Tower organizations. See - Create, update, or destroy Automation Platform Controller organizations. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -86,30 +86,30 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Create tower organization - name: Create organization
tower_organization: organization:
name: "Foo" name: "Foo"
description: "Foo bar organization" description: "Foo bar organization"
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Create tower organization using 'foo-venv' as default Python virtualenv - name: Create organization using 'foo-venv' as default Python virtualenv
tower_organization: organization:
name: "Foo" name: "Foo"
description: "Foo bar organization using foo-venv" description: "Foo bar organization using foo-venv"
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Create tower organization that pulls content from galaxy.ansible.com - name: Create organization that pulls content from galaxy.ansible.com
tower_organization: organization:
name: "Foo" name: "Foo"
state: present state: present
galaxy_credentials: galaxy_credentials:
- Ansible Galaxy - Ansible Galaxy
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -130,7 +130,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_project module: project
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower projects short_description: create, update, or destroy Automation Platform Controller projects
description: description:
- Create, update, or destroy Ansible Tower projects. See - Create, update, or destroy Automation Platform Controller projects. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -160,7 +160,7 @@ options:
type: bool type: bool
interval: interval:
description: description:
- The interval to request an update from Tower. - The interval to request an update from the controller.
- Requires wait. - Requires wait.
required: False required: False
default: 1 default: 1
@@ -170,26 +170,26 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add tower project - name: Add project
tower_project: project:
name: "Foo" name: "Foo"
description: "Foo bar project" description: "Foo bar project"
organization: "test" organization: "test"
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add Tower Project with cache timeout - name: Add Project with cache timeout
tower_project: project:
name: "Foo" name: "Foo"
description: "Foo bar project" description: "Foo bar project"
organization: "test" organization: "test"
scm_update_on_launch: True scm_update_on_launch: True
scm_update_cache_timeout: 60 scm_update_cache_timeout: 60
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Copy tower project - name: Copy project
tower_project: project:
name: copy name: copy
copy_from: test copy_from: test
description: Foo copy project description: Foo copy project
@@ -199,7 +199,7 @@ EXAMPLES = '''
import time import time
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def wait_for_project_update(module, last_request): def wait_for_project_update(module, last_request):
@@ -280,7 +280,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -11,11 +11,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.0', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_project_update module: project_update
author: "Sean Sullivan (@sean-m-sullivan)" author: "Sean Sullivan (@sean-m-sullivan)"
short_description: Update a Project in Ansible Tower short_description: Update a Project in Automation Platform Controller
description: description:
- Update a Ansible Tower Project. See - Update a Automation Platform Controller Project. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -39,7 +39,7 @@ options:
type: bool type: bool
interval: interval:
description: description:
- The interval to request an update from Tower. - The interval to request an update from the controller.
required: False required: False
default: 1 default: 1
type: float type: float
@@ -67,17 +67,17 @@ status:
EXAMPLES = ''' EXAMPLES = '''
- name: Launch a project with a timeout of 10 seconds - name: Launch a project with a timeout of 10 seconds
tower_project_update: project_update:
project: "Networking Project" project: "Networking Project"
timeout: 10 timeout: 10
- name: Launch a Project with extra_vars without waiting - name: Launch a Project with extra_vars without waiting
tower_project_update: project_update:
project: "Networking Project" project: "Networking Project"
wait: False wait: False
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import json import json
import time import time
@@ -93,7 +93,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,12 +14,12 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_role module: role
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: grant or revoke an Ansible Tower role. short_description: grant or revoke an Automation Platform Controller role.
description: description:
- Roles are used for access control, this module is for managing user access to server resources. - Roles are used for access control, this module is for managing user access to server resources.
- Grant or revoke Ansible Tower roles to users. See U(https://www.ansible.com/tower) for an overview. - Grant or revoke Automation Platform Controller roles to users. See U(https://www.ansible.com/tower) for an overview.
options: options:
user: user:
description: description:
@@ -131,14 +131,14 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add jdoe to the member role of My Team - name: Add jdoe to the member role of My Team
tower_role: role:
user: jdoe user: jdoe
target_team: "My Team" target_team: "My Team"
role: member role: member
state: present state: present
- name: Add Joe to multiple job templates and a workflow - name: Add Joe to multiple job templates and a workflow
tower_role: role:
user: joe user: joe
role: execute role: execute
workflow: test-role-workflow workflow: test-role-workflow
@@ -148,7 +148,7 @@ EXAMPLES = '''
state: present state: present
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -194,7 +194,7 @@ def main():
state=dict(choices=['present', 'absent'], default='present'), state=dict(choices=['present', 'absent'], default='present'),
) )
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
role_type = module.params.pop('role') role_type = module.params.pop('role')
role_field = role_type + '_role' role_field = role_type + '_role'

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_schedule module: schedule
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
short_description: create, update, or destroy Ansible Tower schedules. short_description: create, update, or destroy Automation Platform Controller schedules.
description: description:
- Create, update, or destroy Ansible Tower schedules. See - Create, update, or destroy Automation Platform Controller schedules. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
rrule: rrule:
@@ -119,7 +119,7 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Build a schedule for Demo Job Template - name: Build a schedule for Demo Job Template
tower_schedule: schedule:
name: "{{ sched1 }}" name: "{{ sched1 }}"
state: present state: present
unified_job_template: "Demo Job Template" unified_job_template: "Demo Job Template"
@@ -127,15 +127,15 @@ EXAMPLES = '''
register: result register: result
- name: Build the same schedule using the rrule plugin - name: Build the same schedule using the rrule plugin
tower_schedule: schedule:
name: "{{ sched1 }}" name: "{{ sched1 }}"
state: present state: present
unified_job_template: "Demo Job Template" unified_job_template: "Demo Job Template"
rrule: "{{ query('awx.awx.tower_schedule_rrule', 'week', start_date='2019-12-19 13:05:51') }}" rrule: "{{ query('awx.awx.schedule_rrule', 'week', start_date='2019-12-19 13:05:51') }}"
register: result register: result
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -160,7 +160,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
rrule = module.params.get('rrule') rrule = module.params.get('rrule')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_settings module: settings
author: "Nikhil Jain (@jainnikhil30)" author: "Nikhil Jain (@jainnikhil30)"
short_description: Modify Ansible Tower settings. short_description: Modify Automation Platform Controller settings.
description: description:
- Modify Ansible Tower settings. See - Modify Automation Platform Controller settings. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -42,25 +42,25 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Set the value of AWX_ISOLATION_BASE_PATH - name: Set the value of AWX_ISOLATION_BASE_PATH
tower_settings: settings:
name: AWX_ISOLATION_BASE_PATH name: AWX_ISOLATION_BASE_PATH
value: "/tmp" value: "/tmp"
register: testing_settings register: testing_settings
- name: Set the value of AWX_ISOLATION_SHOW_PATHS - name: Set the value of AWX_ISOLATION_SHOW_PATHS
tower_settings: settings:
name: "AWX_ISOLATION_SHOW_PATHS" name: "AWX_ISOLATION_SHOW_PATHS"
value: "'/var/lib/awx/projects/', '/tmp'" value: "'/var/lib/awx/projects/', '/tmp'"
register: testing_settings register: testing_settings
- name: Set the LDAP Auth Bind Password - name: Set the LDAP Auth Bind Password
tower_settings: settings:
name: "AUTH_LDAP_BIND_PASSWORD" name: "AUTH_LDAP_BIND_PASSWORD"
value: "Password" value: "Password"
no_log: true no_log: true
- name: Set all the LDAP Auth Bind Params - name: Set all the LDAP Auth Bind Params
tower_settings: settings:
settings: settings:
AUTH_LDAP_BIND_PASSWORD: "password" AUTH_LDAP_BIND_PASSWORD: "password"
AUTH_LDAP_USER_ATTR_MAP: AUTH_LDAP_USER_ATTR_MAP:
@@ -69,7 +69,7 @@ EXAMPLES = '''
last_name: "surname" last_name: "surname"
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
try: try:
import yaml import yaml
@@ -107,7 +107,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule( module = ControllerAPIModule(
argument_spec=argument_spec, argument_spec=argument_spec,
required_one_of=[['name', 'settings']], required_one_of=[['name', 'settings']],
mutually_exclusive=[['name', 'settings']], mutually_exclusive=[['name', 'settings']],

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_team module: team
author: "Wayne Witzel III (@wwitzel3)" author: "Wayne Witzel III (@wwitzel3)"
short_description: create, update, or destroy Ansible Tower team. short_description: create, update, or destroy Automation Platform Controller team.
description: description:
- Create, update, or destroy Ansible Tower teams. See - Create, update, or destroy Automation Platform Controller teams. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -50,16 +50,16 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Create tower team - name: Create team
tower_team: team:
name: Team Name name: Team Name
description: Team Description description: Team Description
organization: test-org organization: test-org
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -73,7 +73,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,18 +14,18 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_token module: token
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
version_added: "2.3" version_added: "2.3.0"
short_description: create, update, or destroy Ansible Tower tokens. short_description: create, update, or destroy Automation Platform Controller tokens.
description: description:
- Create or destroy Ansible Tower tokens. See - Create or destroy Automation Platform Controller tokens. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
- In addition, the module sets an Ansible fact which can be passed into other - In addition, the module sets an Ansible fact which can be passed into other
tower_* modules as the parameter tower_oauthtoken. See examples for usage. controller modules as the parameter controller_oauthtoken. See examples for usage.
- Because of the sensitive nature of tokens, the created token value is only available once - Because of the sensitive nature of tokens, the created token value is only available once
through the Ansible fact. (See RETURN for details) through the Ansible fact. (See RETURN for details)
- Due to the nature of tokens in Tower this module is not idempotent. A second will - Due to the nature of tokens this module is not idempotent. A second will
with the same parameters will create a new token. with the same parameters will create a new token.
- If you are creating a temporary token for use with modules you should delete the token - If you are creating a temporary token for use with modules you should delete the token
when you are done with it. See the example for how to do it. when you are done with it. See the example for how to do it.
@@ -49,7 +49,7 @@ options:
default: 'write' default: 'write'
choices: ["read", "write"] choices: ["read", "write"]
existing_token: existing_token:
description: The data structure produced from tower_token in create mode to be used with state absent. description: The data structure produced from token in create mode to be used with state absent.
type: dict type: dict
existing_token_id: existing_token_id:
description: A token ID (number) which can be used to delete an arbitrary token with state absent. description: A token ID (number) which can be used to delete an arbitrary token with state absent.
@@ -66,38 +66,38 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- block: - block:
- name: Create a new token using an existing token - name: Create a new token using an existing token
tower_token: token:
description: '{{ token_description }}' description: '{{ token_description }}'
scope: "write" scope: "write"
state: present state: present
tower_oauthtoken: "{{ my_existing_token }}" controller_oauthtoken: "{{ my_existing_token }}"
- name: Delete this token - name: Delete this token
tower_token: token:
existing_token: "{{ tower_token }}" existing_token: "{{ token }}"
state: absent state: absent
- name: Create a new token using username/password - name: Create a new token using username/password
tower_token: token:
description: '{{ token_description }}' description: '{{ token_description }}'
scope: "write" scope: "write"
state: present state: present
tower_username: "{{ my_username }}" controller_username: "{{ my_username }}"
tower_password: "{{ my_password }}" controller_password: "{{ my_password }}"
- name: Use our new token to make another call - name: Use our new token to make another call
tower_job_list: job_list:
tower_oauthtoken: "{{ tower_token }}" controller_oauthtoken: "{{ token }}"
always: always:
- name: Delete our Token with the token we created - name: Delete our Token with the token we created
tower_token: token:
existing_token: "{{ tower_token }}" existing_token: "{{ token }}"
state: absent state: absent
when: tower_token is defined when: token is defined
- name: Delete a token by its id - name: Delete a token by its id
tower_token: token:
existing_token_id: 4 existing_token_id: 4
state: absent state: absent
''' '''
@@ -105,7 +105,7 @@ EXAMPLES = '''
RETURN = ''' RETURN = '''
tower_token: tower_token:
type: dict type: dict
description: An Ansible Fact variable representing a Tower token object which can be used for auth in subsequent modules. See examples for usage. description: An Ansible Fact variable representing a token object which can be used for auth in subsequent modules. See examples for usage.
contains: contains:
token: token:
description: The token that was generated. This token can never be accessed again, make sure this value is noted before it is lost. description: The token that was generated. This token can never be accessed again, make sure this value is noted before it is lost.
@@ -116,7 +116,7 @@ tower_token:
returned: on successful create returned: on successful create
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def return_token(module, last_response): def return_token(module, last_response):
@@ -136,13 +136,13 @@ def main():
description=dict(), description=dict(),
application=dict(), application=dict(),
scope=dict(choices=['read', 'write'], default='write'), scope=dict(choices=['read', 'write'], default='write'),
existing_token=dict(type='dict'), existing_token=dict(type='dict', no_log=False),
existing_token_id=dict(), existing_token_id=dict(),
state=dict(choices=['present', 'absent'], default='present'), state=dict(choices=['present', 'absent'], default='present'),
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule( module = ControllerAPIModule(
argument_spec=argument_spec, argument_spec=argument_spec,
mutually_exclusive=[ mutually_exclusive=[
('existing_token', 'existing_token_id'), ('existing_token', 'existing_token_id'),

View File

@@ -1,192 +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': ['deprecated'], 'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_receive
deprecated:
removed_in: "14.0.0"
why: Deprecated in favor of upcoming C(_export) module.
alternative: Once published, use M(tower_export) instead.
author: "John Westcott IV (@john-westcott-iv)"
short_description: Receive assets from 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: []
type: list
elements: str
user:
description:
- List of user names to export
default: []
type: list
elements: str
team:
description:
- List of team names to export
default: []
type: list
elements: str
credential_type:
description:
- List of credential type names to export
default: []
type: list
elements: str
credential:
description:
- List of credential names to export
default: []
type: list
elements: str
notification_template:
description:
- List of notification template names to export
default: []
type: list
elements: str
inventory:
description:
- List of inventory names to export
default: []
type: list
elements: str
project:
description:
- List of project names to export
default: []
type: list
elements: str
job_template:
description:
- List of job template names to export
default: []
type: list
elements: str
workflow:
description:
- List of workflow names to export
default: []
type: list
elements: str
requirements:
- "ansible-tower-cli >= 3.3.0"
notes:
- Specifying a name of "all" for any asset type will export all items of that asset type.
extends_documentation_fragment: awx.awx.auth_legacy
'''
EXAMPLES = '''
- name: Export all 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 ..module_utils.tower_legacy import TowerLegacyModule, tower_auth_config, HAS_TOWER_CLI
try:
from tower_cli.cli.transfer.receive import Receiver
from tower_cli.cli.transfer.common import SEND_ORDER
from tower_cli.utils.exceptions import TowerCLIError
from tower_cli.conf import settings
TOWER_CLI_HAS_EXPORT = True
except ImportError:
TOWER_CLI_HAS_EXPORT = False
def main():
argument_spec = dict(
all=dict(type='bool', default=False),
credential=dict(type='list', default=[], elements='str'),
credential_type=dict(type='list', default=[], elements='str'),
inventory=dict(type='list', default=[], elements='str'),
job_template=dict(type='list', default=[], elements='str'),
notification_template=dict(type='list', default=[], elements='str'),
organization=dict(type='list', default=[], elements='str'),
project=dict(type='list', default=[], elements='str'),
team=dict(type='list', default=[], elements='str'),
user=dict(type='list', default=[], elements='str'),
workflow=dict(type='list', default=[], elements='str'),
)
module = TowerLegacyModule(argument_spec=argument_spec, supports_check_mode=False)
module.deprecate(msg="This module is deprecated and will be replaced by the AWX CLI export command.", version="awx.awx:14.0.0")
if not HAS_TOWER_CLI:
module.fail_json(msg='ansible-tower-cli required for this module')
if not TOWER_CLI_HAS_EXPORT:
module.fail_json(msg='ansible-tower-cli version does not support export')
export_all = module.params.get('all')
assets_to_export = {}
for asset_type in SEND_ORDER:
assets_to_export[asset_type] = module.params.get(asset_type)
result = dict(
assets=None,
changed=False,
message='',
)
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
try:
receiver = Receiver()
result['assets'] = receiver.export_assets(all=export_all, asset_input=assets_to_export)
module.exit_json(**result)
except TowerCLIError as e:
result['message'] = e.message
module.fail_json(msg='Receive Failed', **result)
if __name__ == '__main__':
main()

View File

@@ -1,174 +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': ['deprecated'], 'supported_by': 'community'}
DOCUMENTATION = '''
---
module: tower_send
deprecated:
removed_in: "14.0.0"
why: Deprecated in favor of upcoming C(_import) module.
alternative: Once published, use M(tower_import) instead.
author: "John Westcott IV (@john-westcott-iv)"
short_description: Send assets to 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
type: str
files:
description:
- List of files to import.
default: []
type: list
elements: str
prevent:
description:
- A list of asset types to prevent import for
default: []
type: list
elements: str
password_management:
description:
- The password management option to use.
- The prompt option is not supported.
default: 'default'
choices: ["default", "random"]
type: str
notes:
- One of assets or files needs to be passed in
requirements:
- "ansible-tower-cli >= 3.3.0"
- six.moves.StringIO
- sys
extends_documentation_fragment: awx.awx.auth_legacy
'''
EXAMPLES = '''
- name: Import all 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 ..module_utils.tower_legacy import TowerLegacyModule, tower_auth_config, HAS_TOWER_CLI
from tempfile import mkstemp
try:
from tower_cli.cli.transfer.send import Sender
from tower_cli.utils.exceptions import TowerCLIError
from tower_cli.conf import settings
TOWER_CLI_HAS_EXPORT = True
except ImportError:
TOWER_CLI_HAS_EXPORT = False
def main():
argument_spec = dict(
assets=dict(),
files=dict(default=[], type='list', elements='str'),
prevent=dict(default=[], type='list', elements='str'),
password_management=dict(default='default', choices=['default', 'random']),
)
module = TowerLegacyModule(argument_spec=argument_spec, supports_check_mode=False)
module.deprecate(msg="This module is deprecated and will be replaced by the AWX CLI import command", version="awx.awx:14.0.0")
if not HAS_TOWER_CLI:
module.fail_json(msg='ansible-tower-cli required for this module')
if not TOWER_CLI_HAS_EXPORT:
module.fail_json(msg='ansible-tower-cli version does not support export')
assets = module.params.get('assets')
prevent = module.params.get('prevent')
password_management = module.params.get('password_management')
files = module.params.get('files')
result = dict(
changed=False,
msg='',
output='',
)
if not assets and not files:
result['msg'] = "Assets or files must be specified"
module.fail_json(**result)
path = None
if assets:
# We got assets so we need to dump this out to a temp file and append that to files
handle, path = mkstemp(prefix='', suffix='', dir='')
with open(path, 'w') as f:
f.write(assets)
files.append(path)
tower_auth = tower_auth_config(module)
failed = False
with settings.runtime_values(**tower_auth):
try:
sender = Sender(no_color=False)
old_stdout = sys.stdout
sys.stdout = captured_stdout = StringIO()
try:
sender.send(files, prevent, password_management)
except TypeError:
# Newer versions of TowerCLI require 4 parameters
sender.send(files, prevent, [], password_management)
if sender.error_messages > 0:
failed = True
result['msg'] = "Transfer Failed with %d errors" % sender.error_messages
if sender.changed_messages > 0:
result['changed'] = True
except TowerCLIError as e:
result['msg'] = e.message
failed = True
finally:
if path is not None:
os.remove(path)
result['output'] = captured_stdout.getvalue().split("\n")
sys.stdout = old_stdout
# Return stdout so that module returns will work
if failed:
module.fail_json(**result)
else:
module.exit_json(**result)
if __name__ == '__main__':
main()

View File

@@ -1,221 +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': ['deprecated'], 'supported_by': 'community', 'metadata_version': '1.1'}
DOCUMENTATION = '''
---
module: tower_workflow_template
deprecated:
removed_in: "14.0.0"
why: Deprecated in favor of C(_workflow_job_template) and C(_workflow_job_template_node) modules.
alternative: Use M(tower_workflow_job_template) and M(_workflow_job_template_node) instead.
author: "Adrien Fleury (@fleu42)"
short_description: create, update, or destroy Ansible Tower workflow template.
description:
- A tower-cli based module for CRUD actions on workflow job templates.
- Enables use of the old schema functionality.
- Not updated for new features, convert to the modules for
workflow_job_template and workflow_job_template node instead.
options:
allow_simultaneous:
description:
- If enabled, simultaneous runs of this job template will be allowed.
type: bool
ask_extra_vars:
description:
- Prompt user for (extra_vars) on launch.
type: bool
ask_inventory:
description:
- Prompt user for inventory on launch.
type: bool
description:
description:
- The description to use for the workflow.
type: str
extra_vars:
description:
- Extra variables used by Ansible in YAML or key=value format.
type: dict
inventory:
description:
- Name of the inventory to use for the job template.
type: str
name:
description:
- The name to use for the workflow.
required: True
type: str
organization:
description:
- The organization the workflow is linked to.
type: str
schema:
description:
- >
The schema is a JSON- or YAML-formatted string defining the
hierarchy structure that connects the nodes. Refer to Tower
documentation for more information.
type: list
elements: dict
survey_enabled:
description:
- Setting that variable will prompt the user for job type on the
workflow launch.
type: bool
survey:
description:
- The definition of the survey associated to the workflow.
type: dict
state:
description:
- Desired state of the resource.
default: "present"
choices: ["present", "absent"]
type: str
requirements:
- ansible-tower-cli >= 3.0.2
extends_documentation_fragment: awx.awx.auth_legacy
'''
EXAMPLES = '''
- 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 ..module_utils.tower_legacy import TowerLegacyModule, tower_auth_config, tower_check_mode
import json
try:
import tower_cli
import tower_cli.exceptions as exc
from tower_cli.conf import settings
except ImportError:
pass
def main():
argument_spec = dict(
name=dict(required=True),
description=dict(),
extra_vars=dict(type='dict'),
organization=dict(),
allow_simultaneous=dict(type='bool'),
schema=dict(type='list', elements='dict'),
survey=dict(type='dict'),
survey_enabled=dict(type='bool'),
inventory=dict(),
ask_inventory=dict(type='bool'),
ask_extra_vars=dict(type='bool'),
state=dict(choices=['present', 'absent'], default='present'),
)
module = TowerLegacyModule(argument_spec=argument_spec, supports_check_mode=False)
module.deprecate(
msg=(
"This module is replaced by the combination of tower_workflow_job_template and "
"tower_workflow_job_template_node. This uses the old tower-cli and wll be "
"removed in 2022."
),
version='awx.awx:14.0.0',
)
name = module.params.get('name')
state = module.params.get('state')
schema = None
if module.params.get('schema'):
schema = module.params.get('schema')
if schema and state == 'absent':
module.fail_json(msg='Setting schema when state is absent is not allowed', changed=False)
json_output = {'workflow_template': name, 'state': state}
tower_auth = tower_auth_config(module)
with settings.runtime_values(**tower_auth):
tower_check_mode(module)
wfjt_res = tower_cli.get_resource('workflow')
params = {}
params['name'] = name
if module.params.get('description'):
params['description'] = module.params.get('description')
if module.params.get('organization'):
organization_res = tower_cli.get_resource('organization')
try:
organization = organization_res.get(name=module.params.get('organization'))
params['organization'] = organization['id']
except exc.NotFound as excinfo:
module.fail_json(msg='Failed to update organization source,' 'organization not found: {0}'.format(excinfo), changed=False)
if module.params.get('survey'):
params['survey_spec'] = module.params.get('survey')
if module.params.get('ask_extra_vars'):
params['ask_variables_on_launch'] = module.params.get('ask_extra_vars')
if module.params.get('ask_inventory'):
params['ask_inventory_on_launch'] = module.params.get('ask_inventory')
for key in ('allow_simultaneous', 'inventory', 'survey_enabled', 'description'):
if module.params.get(key):
params[key] = module.params.get(key)
# Special treatment for tower-cli extra_vars
extra_vars = module.params.get('extra_vars')
if extra_vars:
params['extra_vars'] = [json.dumps(extra_vars)]
try:
if state == 'present':
params['create_on_missing'] = True
result = wfjt_res.modify(**params)
json_output['id'] = result['id']
if schema:
wfjt_res.schema(result['id'], json.dumps(schema))
elif state == 'absent':
params['fail_on_missing'] = False
result = wfjt_res.delete(**params)
except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
module.fail_json(
msg='Failed to update workflow template: \
{0}'.format(
excinfo
),
changed=False,
)
json_output['changed'] = result['changed']
module.exit_json(**json_output)
if __name__ == '__main__':
main()

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_user module: user
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
short_description: create, update, or destroy Ansible Tower users. short_description: create, update, or destroy Automation Platform Controller users.
description: description:
- Create, update, or destroy Ansible Tower users. See - Create, update, or destroy Automation Platform Controller users. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
username: username:
@@ -71,43 +71,43 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Add tower user - name: Add user
tower_user: user:
username: jdoe username: jdoe
password: foobarbaz password: foobarbaz
email: jdoe@example.org email: jdoe@example.org
first_name: John first_name: John
last_name: Doe last_name: Doe
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add tower user as a system administrator - name: Add user as a system administrator
tower_user: user:
username: jdoe username: jdoe
password: foobarbaz password: foobarbaz
email: jdoe@example.org email: jdoe@example.org
superuser: yes superuser: yes
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Add tower user as a system auditor - name: Add user as a system auditor
tower_user: user:
username: jdoe username: jdoe
password: foobarbaz password: foobarbaz
email: jdoe@example.org email: jdoe@example.org
auditor: yes auditor: yes
state: present state: present
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
- name: Delete tower user - name: Delete user
tower_user: user:
username: jdoe username: jdoe
email: jdoe@example.org email: jdoe@example.org
state: absent state: absent
tower_config_file: "~/tower_cli.cfg" controller_config_file: "~/tower_cli.cfg"
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -125,7 +125,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
username = module.params.get('username') username = module.params.get('username')

View File

@@ -18,7 +18,7 @@ ANSIBLE_METADATA = {
DOCUMENTATION = """ DOCUMENTATION = """
--- ---
module: tower_workflow_approval module: workflow_approval
author: "Sean Sullivan (@sean-m-sullivan)" author: "Sean Sullivan (@sean-m-sullivan)"
short_description: Approve an approval node in a workflow job. short_description: Approve an approval node in a workflow job.
description: description:
@@ -43,7 +43,7 @@ options:
type: str type: str
interval: interval:
description: description:
- The interval in sections, to request an update from Tower. - The interval in sections, to request an update from the controller.
required: False required: False
default: 1 default: 1
type: float type: float
@@ -58,13 +58,13 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = """ EXAMPLES = """
- name: Launch a workflow with a timeout of 10 seconds - name: Launch a workflow with a timeout of 10 seconds
tower_workflow_launch: workflow_launch:
workflow_template: "Test Workflow" workflow_template: "Test Workflow"
wait: False wait: False
register: workflow register: workflow
- name: Wait for approval node to activate and approve - name: Wait for approval node to activate and approve
tower_workflow_approval: workflow_approval:
workflow_job_id: "{{ workflow.id }}" workflow_job_id: "{{ workflow.id }}"
name: Approve Me name: Approve Me
interval: 10 interval: 10
@@ -77,7 +77,7 @@ RETURN = """
""" """
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -91,7 +91,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
workflow_job_id = module.params.get("workflow_job_id") workflow_job_id = module.params.get("workflow_job_id")

View File

@@ -14,13 +14,13 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_workflow_job_template module: workflow_job_template
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
short_description: create, update, or destroy Ansible Tower workflow job templates. short_description: create, update, or destroy Automation Platform Controller workflow job templates.
description: description:
- Create, update, or destroy Ansible Tower workflow job templates. - Create, update, or destroy Automation Platform Controller workflow job templates.
- Replaces the deprecated tower_workflow_template module. - Replaces the deprecated tower_workflow_template module.
- Use the tower_workflow_job_template_node after this, or use the schema paramater to build the workflow's graph - Use workflow_job_template_node after this, or use the schema parameter to build the workflow's graph
options: options:
name: name:
description: description:
@@ -148,6 +148,7 @@ options:
description: description:
- A json list of nodes and their coresponding options. The following suboptions describe a single node. - A json list of nodes and their coresponding options. The following suboptions describe a single node.
type: list type: list
elements: dict
suboptions: suboptions:
extra_data: extra_data:
description: description:
@@ -328,13 +329,13 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = ''' EXAMPLES = '''
- name: Create a workflow job template - name: Create a workflow job template
tower_workflow_job_template: workflow_job_template:
name: example-workflow name: example-workflow
description: created by Ansible Playbook description: created by Ansible Playbook
organization: Default organization: Default
- name: Create a workflow job template with schema in template - name: Create a workflow job template with schema in template
awx.awx.tower_workflow_job_template: awx.awx.workflow_job_template:
name: example-workflow name: example-workflow
inventory: Demo Inventory inventory: Demo Inventory
extra_vars: {'foo': 'bar', 'another-foo': {'barz': 'bar2'}} extra_vars: {'foo': 'bar', 'another-foo': {'barz': 'bar2'}}
@@ -391,13 +392,13 @@ EXAMPLES = '''
register: result register: result
- name: Copy a workflow job template - name: Copy a workflow job template
tower_workflow_job_template: workflow_job_template:
name: copy-workflow name: copy-workflow
copy_from: example-workflow copy_from: example-workflow
organization: Foo organization: Foo
- name: Create a workflow job template with schema in template - name: Create a workflow job template with schema in template
awx.awx.tower_workflow_job_template: awx.awx.workflow_job_template:
name: example-workflow name: example-workflow
inventory: Demo Inventory inventory: Demo Inventory
extra_vars: {'foo': 'bar', 'another-foo': {'barz': 'bar2'}} extra_vars: {'foo': 'bar', 'another-foo': {'barz': 'bar2'}}
@@ -455,7 +456,7 @@ EXAMPLES = '''
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import json import json
@@ -689,7 +690,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
name = module.params.get('name') name = module.params.get('name')

View File

@@ -14,11 +14,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_workflow_job_template_node module: workflow_job_template_node
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
short_description: create, update, or destroy Ansible Tower workflow job template nodes. short_description: create, update, or destroy Automation Platform Controller workflow job template nodes.
description: description:
- Create, update, or destroy Ansible Tower workflow job template nodes. - Create, update, or destroy Automation Platform Controller workflow job template nodes.
- Use this to build a graph for a workflow, which dictates what the workflow runs. - Use this to build a graph for a workflow, which dictates what the workflow runs.
- Replaces the deprecated tower_workflow_template module schema command. - Replaces the deprecated tower_workflow_template module schema command.
- You can create nodes first, and link them afterwards, and not worry about ordering. - You can create nodes first, and link them afterwards, and not worry about ordering.
@@ -157,8 +157,8 @@ extends_documentation_fragment: awx.awx.auth
''' '''
EXAMPLES = ''' EXAMPLES = '''
- name: Create a node, follows tower_workflow_job_template example - name: Create a node, follows workflow_job_template example
tower_workflow_job_template_node: workflow_job_template_node:
identifier: my-first-node identifier: my-first-node
workflow: example-workflow workflow: example-workflow
unified_job_template: jt-for-node-use unified_job_template: jt-for-node-use
@@ -167,7 +167,7 @@ EXAMPLES = '''
foo_key: bar_value foo_key: bar_value
- name: Create parent node for prior node - name: Create parent node for prior node
tower_workflow_job_template_node: workflow_job_template_node:
identifier: my-root-node identifier: my-root-node
workflow: example-workflow workflow: example-workflow
unified_job_template: jt-for-node-use unified_job_template: jt-for-node-use
@@ -224,7 +224,7 @@ EXAMPLES = '''
- my-third-node - my-third-node
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
def main(): def main():
@@ -255,11 +255,11 @@ def main():
required_if = [ required_if = [
['state', 'absent', ['identifier']], ['state', 'absent', ['identifier']],
['state', 'present', ['identifier']], ['state', 'present', ['identifier']],
['state', 'present', ['unified_job_template', 'approval_node', 'success_nodes', 'always_nodes', 'failure_nodes'], 'true'], ['state', 'present', ['unified_job_template', 'approval_node', 'success_nodes', 'always_nodes', 'failure_nodes'], True],
] ]
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule( module = ControllerAPIModule(
argument_spec=argument_spec, argument_spec=argument_spec,
mutually_exclusive=mutually_exclusive, mutually_exclusive=mutually_exclusive,
required_if=required_if, required_if=required_if,
@@ -283,7 +283,9 @@ def main():
wfjt_search_fields['organization'] = organization_id wfjt_search_fields['organization'] = organization_id
wfjt_data = module.get_one('workflow_job_templates', name_or_id=workflow_job_template, **{'data': wfjt_search_fields}) wfjt_data = module.get_one('workflow_job_templates', name_or_id=workflow_job_template, **{'data': wfjt_search_fields})
if wfjt_data is None: if wfjt_data is None:
module.fail_json(msg="The workflow {0} in organization {1} was not found on the Tower server".format(workflow_job_template, organization)) module.fail_json(
msg="The workflow {0} in organization {1} was not found on the controller instance server".format(workflow_job_template, organization)
)
workflow_job_template_id = wfjt_data['id'] workflow_job_template_id = wfjt_data['id']
search_fields['workflow_job_template'] = new_fields['workflow_job_template'] = workflow_job_template_id search_fields['workflow_job_template'] = new_fields['workflow_job_template'] = workflow_job_template_id

View File

@@ -11,11 +11,11 @@ ANSIBLE_METADATA = {'metadata_version': '1.1', 'status': ['preview'], 'supported
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: tower_workflow_launch module: workflow_launch
author: "John Westcott IV (@john-westcott-iv)" author: "John Westcott IV (@john-westcott-iv)"
short_description: Run a workflow in Ansible Tower short_description: Run a workflow in Automation Platform Controller
description: description:
- Launch an Ansible Tower workflows. See - Launch an Automation Platform Controller workflows. See
U(https://www.ansible.com/tower) for an overview. U(https://www.ansible.com/tower) for an overview.
options: options:
name: name:
@@ -55,7 +55,7 @@ options:
type: bool type: bool
interval: interval:
description: description:
- The interval to request an update from Tower. - The interval to request an update from the controller.
required: False required: False
default: 1 default: 1
type: float type: float
@@ -77,12 +77,12 @@ job_info:
EXAMPLES = ''' EXAMPLES = '''
- name: Launch a workflow with a timeout of 10 seconds - name: Launch a workflow with a timeout of 10 seconds
tower_workflow_launch: workflow_launch:
workflow_template: "Test Workflow" workflow_template: "Test Workflow"
timeout: 10 timeout: 10
- name: Launch a Workflow with extra_vars without waiting - name: Launch a Workflow with extra_vars without waiting
tower_workflow_launch: workflow_launch:
workflow_template: "Test workflow" workflow_template: "Test workflow"
extra_vars: extra_vars:
var1: My First Variable var1: My First Variable
@@ -90,7 +90,7 @@ EXAMPLES = '''
wait: False wait: False
''' '''
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import json import json
@@ -109,7 +109,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
optional_args = {} optional_args = {}
# Extract our parameters # Extract our parameters

View File

@@ -18,7 +18,7 @@ ANSIBLE_METADATA = {
DOCUMENTATION = """ DOCUMENTATION = """
--- ---
module: tower_workflow_node_wait module: workflow_node_wait
author: "Sean Sullivan (@sean-m-sullivan)" author: "Sean Sullivan (@sean-m-sullivan)"
short_description: Approve an approval node in a workflow job. short_description: Approve an approval node in a workflow job.
description: description:
@@ -37,7 +37,7 @@ options:
type: str type: str
interval: interval:
description: description:
- The interval in sections, to request an update from Tower. - The interval in sections, to request an update from the controller.
required: False required: False
default: 1 default: 1
type: float type: float
@@ -52,13 +52,13 @@ extends_documentation_fragment: awx.awx.auth
EXAMPLES = """ EXAMPLES = """
- name: Launch a workflow with a timeout of 10 seconds - name: Launch a workflow with a timeout of 10 seconds
tower_workflow_launch: workflow_launch:
workflow_template: "Test Workflow" workflow_template: "Test Workflow"
wait: False wait: False
register: workflow register: workflow
- name: Wait for a workflow node to finish - name: Wait for a workflow node to finish
tower_workflow_node_wait: workflow_node_wait:
workflow_job_id: "{{ workflow.id }}" workflow_job_id: "{{ workflow.id }}"
name: Approval Data Step name: Approval Data Step
timeout: 120 timeout: 120
@@ -69,7 +69,7 @@ RETURN = """
""" """
from ..module_utils.tower_api import TowerAPIModule from ..module_utils.controller_api import ControllerAPIModule
import time import time
@@ -83,7 +83,7 @@ def main():
) )
# Create a module for ourselves # Create a module for ourselves
module = TowerAPIModule(argument_spec=argument_spec) module = ControllerAPIModule(argument_spec=argument_spec)
# Extract our parameters # Extract our parameters
workflow_job_id = module.params.get("workflow_job_id") workflow_job_id = module.params.get("workflow_job_id")

View File

@@ -1,3 +1,3 @@
pytz # for tower_schedule_rrule lookup plugin pytz # for schedule_rrule lookup plugin
python-dateutil>=2.7.0 # tower_schedule_rrule python-dateutil>=2.7.0 # schedule_rrule
awxkit # For import and export modules awxkit # For import and export modules

View File

@@ -150,14 +150,14 @@ def run_module(request, collection_import):
def mock_load_params(self): def mock_load_params(self):
self.params = module_params self.params = module_params
if getattr(resource_module, 'TowerAWXKitModule', None): if getattr(resource_module, 'ControllerAWXKitModule', None):
resource_class = resource_module.TowerAWXKitModule resource_class = resource_module.ControllerAWXKitModule
elif getattr(resource_module, 'TowerAPIModule', None): elif getattr(resource_module, 'ControllerAPIModule', None):
resource_class = resource_module.TowerAPIModule resource_class = resource_module.ControllerAPIModule
elif getattr(resource_module, 'TowerLegacyModule', None): elif getattr(resource_module, 'TowerLegacyModule', None):
resource_class = resource_module.TowerLegacyModule resource_class = resource_module.TowerLegacyModule
else: else:
raise ("The module has neither a TowerLegacyModule, TowerAWXKitModule or a TowerAPIModule") raise ("The module has neither a TowerLegacyModule, ControllerAWXKitModule or a ControllerAPIModule")
with mock.patch.object(resource_class, '_load_params', new=mock_load_params): with mock.patch.object(resource_class, '_load_params', new=mock_load_params):
# Call the test utility (like a mock server) instead of issuing HTTP requests # Call the test utility (like a mock server) instead of issuing HTTP requests
@@ -184,7 +184,7 @@ def run_module(request, collection_import):
try: try:
result = json.loads(module_stdout) result = json.loads(module_stdout)
except Exception as e: except Exception as e:
raise Exception('Module did not write valid JSON, error: {0}, stdout:\n{1}'.format(str(e), module_stdout)) raise Exception('Module did not write valid JSON, error: {0}, stdout:\n{1}'.format(str(e), module_stdout)) from e
# A module exception should never be a test expectation # A module exception should never be a test expectation
if 'exception' in result: if 'exception' in result:
if "ModuleNotFoundError: No module named 'tower_cli'" in result['exception']: if "ModuleNotFoundError: No module named 'tower_cli'" in result['exception']:

View File

@@ -11,7 +11,7 @@ from awx.main.models.ad_hoc_commands import AdHocCommand
@pytest.mark.django_db @pytest.mark.django_db
def test_ad_hoc_command_wait_successful(run_module, admin_user): def test_ad_hoc_command_wait_successful(run_module, admin_user):
command = AdHocCommand.objects.create(status='successful', started=now(), finished=now()) command = AdHocCommand.objects.create(status='successful', started=now(), finished=now())
result = run_module('tower_ad_hoc_command_wait', dict(command_id=command.id), admin_user) result = run_module('ad_hoc_command_wait', dict(command_id=command.id), admin_user)
result.pop('invocation', None) result.pop('invocation', None)
result['elapsed'] = float(result['elapsed']) result['elapsed'] = float(result['elapsed'])
assert result.pop('finished', '')[:10] == str(command.finished)[:10] assert result.pop('finished', '')[:10] == str(command.finished)[:10]
@@ -22,7 +22,7 @@ def test_ad_hoc_command_wait_successful(run_module, admin_user):
@pytest.mark.django_db @pytest.mark.django_db
def test_ad_hoc_command_wait_failed(run_module, admin_user): def test_ad_hoc_command_wait_failed(run_module, admin_user):
command = AdHocCommand.objects.create(status='failed', started=now(), finished=now()) command = AdHocCommand.objects.create(status='failed', started=now(), finished=now())
result = run_module('tower_ad_hoc_command_wait', dict(command_id=command.id), admin_user) result = run_module('ad_hoc_command_wait', dict(command_id=command.id), admin_user)
result.pop('invocation', None) result.pop('invocation', None)
result['elapsed'] = float(result['elapsed']) result['elapsed'] = float(result['elapsed'])
assert result.pop('finished', '')[:10] == str(command.finished)[:10] assert result.pop('finished', '')[:10] == str(command.finished)[:10]
@@ -39,6 +39,6 @@ def test_ad_hoc_command_wait_failed(run_module, admin_user):
@pytest.mark.django_db @pytest.mark.django_db
def test_ad_hoc_command_wait_not_found(run_module, admin_user): def test_ad_hoc_command_wait_not_found(run_module, admin_user):
result = run_module('tower_ad_hoc_command_wait', dict(command_id=42), admin_user) result = run_module('ad_hoc_command_wait', dict(command_id=42), admin_user)
result.pop('invocation', None) result.pop('invocation', None)
assert result == {"failed": True, "msg": "Unable to wait on ad hoc command 42; that ID does not exist in Tower."} assert result == {"failed": True, "msg": "Unable to wait on ad hoc command 42; that ID does not exist."}

View File

@@ -21,7 +21,7 @@ def test_create_application(run_module, admin_user):
'organization': 'foo', 'organization': 'foo',
} }
result = run_module('tower_application', module_args, admin_user) result = run_module('application', module_args, admin_user)
assert result.get('changed'), result assert result.get('changed'), result
application = OAuth2Application.objects.get(name='foo_app') application = OAuth2Application.objects.get(name='foo_app')

View File

@@ -14,9 +14,9 @@ import re
# Read-only endpoints are dynamically created by an options page with no POST section. # Read-only endpoints are dynamically created by an options page with no POST section.
# Normally a read-only endpoint should not have a module (i.e. /api/v2/me) but sometimes we reuse a name # Normally a read-only endpoint should not have a module (i.e. /api/v2/me) but sometimes we reuse a name
# For example, we have a tower_role module but /api/v2/roles is a read only endpoint. # For example, we have a role module but /api/v2/roles is a read only endpoint.
# This list indicates which read-only endpoints have associated modules with them. # This list indicates which read-only endpoints have associated modules with them.
read_only_endpoints_with_modules = ['tower_settings', 'tower_role', 'tower_project_update'] read_only_endpoints_with_modules = ['settings', 'role', 'project_update']
# If a module should not be created for an endpoint and the endpoint is not read-only add it here # If a module should not be created for an endpoint and the endpoint is not read-only add it here
# THINK HARD ABOUT DOING THIS # THINK HARD ABOUT DOING THIS
@@ -24,23 +24,23 @@ no_module_for_endpoint = []
# Some modules work on the related fields of an endpoint. These modules will not have an auto-associated endpoint # Some modules work on the related fields of an endpoint. These modules will not have an auto-associated endpoint
no_endpoint_for_module = [ no_endpoint_for_module = [
'tower_import', 'import',
'tower_meta', 'controller_meta',
'tower_export', 'export',
'tower_inventory_source_update', 'inventory_source_update',
'tower_job_launch', 'job_launch',
'tower_job_wait', 'job_wait',
'tower_job_list', 'job_list',
'tower_license', 'license',
'tower_ping', 'ping',
'tower_receive', 'receive',
'tower_send', 'send',
'tower_workflow_launch', 'workflow_launch',
'tower_workflow_node_wait', 'workflow_node_wait',
'tower_job_cancel', 'job_cancel',
'tower_workflow_template', 'workflow_template',
'tower_ad_hoc_command_wait', 'ad_hoc_command_wait',
'tower_ad_hoc_command_cancel', 'ad_hoc_command_cancel',
] ]
# Global module parameters we can ignore # Global module parameters we can ignore
@@ -50,32 +50,32 @@ ignore_parameters = ['state', 'new_name', 'update_secrets', 'copy_from']
# Add the module name as the key with the value being the list of params to ignore # Add the module name as the key with the value being the list of params to ignore
no_api_parameter_ok = { no_api_parameter_ok = {
# The wait is for whether or not to wait for a project update on change # The wait is for whether or not to wait for a project update on change
'tower_project': ['wait', 'interval', 'update_project'], 'project': ['wait', 'interval', 'update_project'],
# Existing_token and id are for working with an existing tokens # Existing_token and id are for working with an existing tokens
'tower_token': ['existing_token', 'existing_token_id'], 'token': ['existing_token', 'existing_token_id'],
# /survey spec is now how we handle associations # /survey spec is now how we handle associations
# We take an organization here to help with the lookups only # We take an organization here to help with the lookups only
'tower_job_template': ['survey_spec', 'organization'], 'job_template': ['survey_spec', 'organization'],
'tower_inventory_source': ['organization'], 'inventory_source': ['organization'],
# Organization is how we are looking up job templates, Approval node is for workflow_approval_templates # Organization is how we are looking up job templates, Approval node is for workflow_approval_templates
'tower_workflow_job_template_node': ['organization', 'approval_node'], 'workflow_job_template_node': ['organization', 'approval_node'],
# Survey is how we handle associations # Survey is how we handle associations
'tower_workflow_job_template': ['survey_spec', 'destroy_current_schema'], 'workflow_job_template': ['survey_spec', 'destroy_current_schema'],
# ad hoc commands support interval and timeout since its more like tower_job_launch # ad hoc commands support interval and timeout since its more like job_launch
'tower_ad_hoc_command': ['interval', 'timeout', 'wait'], 'ad_hoc_command': ['interval', 'timeout', 'wait'],
# tower_group parameters to perserve hosts and children. # group parameters to perserve hosts and children.
'tower_group': ['preserve_existing_children', 'preserve_existing_hosts'], 'group': ['preserve_existing_children', 'preserve_existing_hosts'],
# tower_workflow_approval parameters that do not apply when approving an approval node. # workflow_approval parameters that do not apply when approving an approval node.
'tower_workflow_approval': ['action', 'interval', 'timeout', 'workflow_job_id'], 'workflow_approval': ['action', 'interval', 'timeout', 'workflow_job_id'],
} }
# When this tool was created we were not feature complete. Adding something in here indicates a module # When this tool was created we were not feature complete. Adding something in here indicates a module
# that needs to be developed. If the module is found on the file system it will auto-detect that the # that needs to be developed. If the module is found on the file system it will auto-detect that the
# work is being done and will bypass this check. At some point this module should be removed from this list. # work is being done and will bypass this check. At some point this module should be removed from this list.
needs_development = ['tower_inventory_script'] needs_development = ['inventory_script']
needs_param_development = { needs_param_development = {
'tower_host': ['instance_id'], 'host': ['instance_id'],
'tower_workflow_approval': ['description', 'execution_environment'], 'workflow_approval': ['description', 'execution_environment'],
} }
# ----------------------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------------------
@@ -169,7 +169,8 @@ def test_completeness(collection_import, request, admin_user, job_template, exec
for root, dirs, files in os.walk(module_directory): for root, dirs, files in os.walk(module_directory):
if root == module_directory: if root == module_directory:
for filename in files: for filename in files:
if re.match('^tower_.*.py$', filename): # must begin with a letter a-z, and end in .py
if re.match(r'^[a-z].*.py$', filename):
module_name = filename[:-3] module_name = filename[:-3]
option_comparison[module_name] = { option_comparison[module_name] = {
'endpoint': 'N/A', 'endpoint': 'N/A',
@@ -192,7 +193,7 @@ def test_completeness(collection_import, request, admin_user, job_template, exec
singular_endpoint = singular_endpoint[:-3] singular_endpoint = singular_endpoint[:-3]
if singular_endpoint != 'settings' and singular_endpoint.endswith('s'): if singular_endpoint != 'settings' and singular_endpoint.endswith('s'):
singular_endpoint = singular_endpoint[:-1] singular_endpoint = singular_endpoint[:-1]
module_name = 'tower_{0}'.format(singular_endpoint) module_name = '{0}'.format(singular_endpoint)
endpoint_url = endpoint_response.data.get(endpoint) endpoint_url = endpoint_response.data.get(endpoint)

View File

@@ -29,7 +29,7 @@ def test_create_machine_credential(run_module, admin_user, organization, silence
ct = CredentialType.defaults['ssh']() ct = CredentialType.defaults['ssh']()
ct.save() ct.save()
# Example from docs # Example from docs
result = run_module('tower_credential', dict(name='Test Machine Credential', organization=organization.name, kind='ssh', state='present'), admin_user) result = run_module('credential', dict(name='Test Machine Credential', organization=organization.name, kind='ssh', state='present'), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result assert result.get('changed'), result
@@ -48,7 +48,7 @@ def test_create_vault_credential(run_module, admin_user, organization, silence_d
ct.save() ct.save()
result = run_module( result = run_module(
'tower_credential', 'credential',
dict(name='Test Vault Credential', organization=organization.name, kind='vault', vault_id='bar', vault_password='foobar', state='present'), dict(name='Test Vault Credential', organization=organization.name, kind='vault', vault_id='bar', vault_password='foobar', state='present'),
admin_user, admin_user,
) )
@@ -67,7 +67,7 @@ def test_create_vault_credential(run_module, admin_user, organization, silence_d
@pytest.mark.django_db @pytest.mark.django_db
def test_ct_precedence_over_kind(run_module, admin_user, organization, cred_type, silence_deprecation): def test_ct_precedence_over_kind(run_module, admin_user, organization, cred_type, silence_deprecation):
result = run_module( result = run_module(
'tower_credential', dict(name='A credential', organization=organization.name, kind='ssh', credential_type=cred_type.name, state='present'), admin_user 'credential', dict(name='A credential', organization=organization.name, kind='ssh', credential_type=cred_type.name, state='present'), admin_user
) )
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
@@ -82,7 +82,7 @@ def test_input_overrides_old_fields(run_module, admin_user, organization, silenc
ct = CredentialType.defaults['vault']() ct = CredentialType.defaults['vault']()
ct.save() ct.save()
result = run_module( result = run_module(
'tower_credential', 'credential',
dict( dict(
name='A Vault credential', name='A Vault credential',
organization=organization.name, organization=organization.name,
@@ -103,7 +103,7 @@ def test_input_overrides_old_fields(run_module, admin_user, organization, silenc
@pytest.mark.django_db @pytest.mark.django_db
def test_missing_credential_type(run_module, admin_user, organization): def test_missing_credential_type(run_module, admin_user, organization):
Organization.objects.create(name='test-org') Organization.objects.create(name='test-org')
result = run_module('tower_credential', dict(name='A credential', organization=organization.name, credential_type='foobar', state='present'), admin_user) result = run_module('credential', dict(name='A credential', organization=organization.name, credential_type='foobar', state='present'), admin_user)
assert result.get('failed', False), result assert result.get('failed', False), result
assert 'credential_type' in result['msg'] assert 'credential_type' in result['msg']
assert 'foobar' in result['msg'] assert 'foobar' in result['msg']
@@ -113,7 +113,7 @@ def test_missing_credential_type(run_module, admin_user, organization):
@pytest.mark.django_db @pytest.mark.django_db
def test_make_use_of_custom_credential_type(run_module, organization, admin_user, cred_type): def test_make_use_of_custom_credential_type(run_module, organization, admin_user, cred_type):
result = run_module( result = run_module(
'tower_credential', 'credential',
dict(name='Galaxy Token for Steve', organization=organization.name, credential_type=cred_type.name, inputs={'token': '7rEZK38DJl58A7RxA6EC7lLvUHbBQ1'}), dict(name='Galaxy Token for Steve', organization=organization.name, credential_type=cred_type.name, inputs={'token': '7rEZK38DJl58A7RxA6EC7lLvUHbBQ1'}),
admin_user, admin_user,
) )
@@ -137,7 +137,7 @@ def test_secret_field_write_twice(run_module, organization, admin_user, cred_typ
val2 = '7rEZ238DJl5837rxA6xxxlLvUHbBQ1' val2 = '7rEZ238DJl5837rxA6xxxlLvUHbBQ1'
for val in (val1, val2): for val in (val1, val2):
result = run_module( result = run_module(
'tower_credential', 'credential',
dict( dict(
name='Galaxy Token for Steve', name='Galaxy Token for Steve',
organization=organization.name, organization=organization.name,

View File

@@ -29,7 +29,7 @@ def test_aim_credential_source(run_module, admin_user, organization, source_cred
tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'}) tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'})
result = run_module( result = run_module(
'tower_credential_input_source', 'credential_input_source',
dict( dict(
source_credential=source_cred_aim.name, source_credential=source_cred_aim.name,
target_credential=tgt_cred.name, target_credential=tgt_cred.name,
@@ -73,7 +73,7 @@ def test_conjur_credential_source(run_module, admin_user, organization, source_c
tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'}) tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'})
result = run_module( result = run_module(
'tower_credential_input_source', 'credential_input_source',
dict( dict(
source_credential=source_cred_conjur.name, source_credential=source_cred_conjur.name,
target_credential=tgt_cred.name, target_credential=tgt_cred.name,
@@ -123,7 +123,7 @@ def test_hashi_secret_credential_source(run_module, admin_user, organization, so
tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'}) tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'})
result = run_module( result = run_module(
'tower_credential_input_source', 'credential_input_source',
dict( dict(
source_credential=source_cred_hashi_secret.name, source_credential=source_cred_hashi_secret.name,
target_credential=tgt_cred.name, target_credential=tgt_cred.name,
@@ -170,7 +170,7 @@ def test_hashi_ssh_credential_source(run_module, admin_user, organization, sourc
tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'}) tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'})
result = run_module( result = run_module(
'tower_credential_input_source', 'credential_input_source',
dict( dict(
source_credential=source_cred_hashi_ssh.name, source_credential=source_cred_hashi_ssh.name,
target_credential=tgt_cred.name, target_credential=tgt_cred.name,
@@ -224,7 +224,7 @@ def test_azure_kv_credential_source(run_module, admin_user, organization, source
tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'}) tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'})
result = run_module( result = run_module(
'tower_credential_input_source', 'credential_input_source',
dict( dict(
source_credential=source_cred_azure_kv.name, source_credential=source_cred_azure_kv.name,
target_credential=tgt_cred.name, target_credential=tgt_cred.name,
@@ -265,7 +265,7 @@ def test_aim_credential_source(run_module, admin_user, organization, source_cred
tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'}) tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'})
result = run_module( result = run_module(
'tower_credential_input_source', 'credential_input_source',
dict( dict(
source_credential=source_cred_aim.name, source_credential=source_cred_aim.name,
target_credential=tgt_cred.name, target_credential=tgt_cred.name,
@@ -280,7 +280,7 @@ def test_aim_credential_source(run_module, admin_user, organization, source_cred
assert result.get('changed'), result assert result.get('changed'), result
unchangedResult = run_module( unchangedResult = run_module(
'tower_credential_input_source', 'credential_input_source',
dict( dict(
source_credential=source_cred_aim.name, source_credential=source_cred_aim.name,
target_credential=tgt_cred.name, target_credential=tgt_cred.name,
@@ -295,7 +295,7 @@ def test_aim_credential_source(run_module, admin_user, organization, source_cred
assert not unchangedResult.get('changed'), result assert not unchangedResult.get('changed'), result
changedResult = run_module( changedResult = run_module(
'tower_credential_input_source', 'credential_input_source',
dict(source_credential=source_cred_aim_alt.name, target_credential=tgt_cred.name, input_field_name='password', state='present'), dict(source_credential=source_cred_aim_alt.name, target_credential=tgt_cred.name, input_field_name='password', state='present'),
admin_user, admin_user,
) )
@@ -336,7 +336,7 @@ def test_centrify_vault_credential_source(run_module, admin_user, organization,
tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'}) tgt_cred = Credential.objects.create(name='Test Machine Credential', organization=organization, credential_type=ct, inputs={'username': 'bob'})
result = run_module( result = run_module(
'tower_credential_input_source', 'credential_input_source',
dict( dict(
source_credential=source_cred_centrify_secret.name, source_credential=source_cred_centrify_secret.name,
target_credential=tgt_cred.name, target_credential=tgt_cred.name,

View File

@@ -11,7 +11,7 @@ from awx.main.models import CredentialType
def test_create_custom_credential_type(run_module, admin_user, silence_deprecation): def test_create_custom_credential_type(run_module, admin_user, silence_deprecation):
# Example from docs # Example from docs
result = run_module( result = run_module(
'tower_credential_type', 'credential_type',
dict( dict(
name='Nexus', name='Nexus',
description='Credentials type for Nexus', description='Credentials type for Nexus',
@@ -37,7 +37,7 @@ def test_create_custom_credential_type(run_module, admin_user, silence_deprecati
@pytest.mark.django_db @pytest.mark.django_db
def test_changed_false_with_api_changes(run_module, admin_user): def test_changed_false_with_api_changes(run_module, admin_user):
result = run_module( result = run_module(
'tower_credential_type', 'credential_type',
dict( dict(
name='foo', name='foo',
kind='cloud', kind='cloud',
@@ -50,7 +50,7 @@ def test_changed_false_with_api_changes(run_module, admin_user):
assert result.get('changed'), result assert result.get('changed'), result
result = run_module( result = run_module(
'tower_credential_type', 'credential_type',
dict( dict(
name='foo', name='foo',
inputs={"fields": [{"id": "env_value", "label": "foo", "default": "foo"}]}, inputs={"fields": [{"id": "env_value", "label": "foo", "default": "foo"}]},

View File

@@ -13,7 +13,7 @@ def test_create_group(run_module, admin_user):
inv = Inventory.objects.create(name='test-inv', organization=org) inv = Inventory.objects.create(name='test-inv', organization=org)
variables = {"ansible_network_os": "iosxr"} variables = {"ansible_network_os": "iosxr"}
result = run_module('tower_group', dict(name='Test Group', inventory='test-inv', variables=variables, state='present'), admin_user) result = run_module('group', dict(name='Test Group', inventory='test-inv', variables=variables, state='present'), admin_user)
assert result.get('changed'), result assert result.get('changed'), result
group = Group.objects.get(name='Test Group') group = Group.objects.get(name='Test Group')
@@ -39,7 +39,7 @@ def test_associate_hosts_and_children(run_module, admin_user, organization):
child = Group.objects.create(inventory=inv, name='child_group') child = Group.objects.create(inventory=inv, name='child_group')
result = run_module( result = run_module(
'tower_group', 'group',
dict(name='Test Group', inventory='test-inv', hosts=[inv_hosts[1].name, inv_hosts[2].name], children=[child.name], state='present'), dict(name='Test Group', inventory='test-inv', hosts=[inv_hosts[1].name, inv_hosts[2].name], children=[child.name], state='present'),
admin_user, admin_user,
) )
@@ -56,7 +56,7 @@ def test_associate_on_create(run_module, admin_user, organization):
child = Group.objects.create(name='test-child', inventory=inv) child = Group.objects.create(name='test-child', inventory=inv)
host = Host.objects.create(name='test-host', inventory=inv) host = Host.objects.create(name='test-host', inventory=inv)
result = run_module('tower_group', dict(name='Test Group', inventory='test-inv', hosts=[host.name], groups=[child.name], state='present'), admin_user) result = run_module('group', dict(name='Test Group', inventory='test-inv', hosts=[host.name], groups=[child.name], state='present'), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result['changed'] is True assert result['changed'] is True
@@ -70,7 +70,7 @@ def test_children_alias_of_groups(run_module, admin_user, organization):
inv = Inventory.objects.create(name='test-inv', organization=organization) inv = Inventory.objects.create(name='test-inv', organization=organization)
group = Group.objects.create(name='Test Group', inventory=inv) group = Group.objects.create(name='Test Group', inventory=inv)
child = Group.objects.create(inventory=inv, name='child_group') child = Group.objects.create(inventory=inv, name='child_group')
result = run_module('tower_group', dict(name='Test Group', inventory='test-inv', groups=[child.name], state='present'), admin_user) result = run_module('group', dict(name='Test Group', inventory='test-inv', groups=[child.name], state='present'), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result['changed'] is True assert result['changed'] is True
@@ -78,7 +78,7 @@ def test_children_alias_of_groups(run_module, admin_user, organization):
@pytest.mark.django_db @pytest.mark.django_db
def test_tower_group_idempotent(run_module, admin_user): def test_group_idempotent(run_module, admin_user):
# https://github.com/ansible/ansible/issues/46803 # https://github.com/ansible/ansible/issues/46803
org = Organization.objects.create(name='test-org') org = Organization.objects.create(name='test-org')
inv = Inventory.objects.create(name='test-inv', organization=org) inv = Inventory.objects.create(name='test-inv', organization=org)
@@ -87,7 +87,7 @@ def test_tower_group_idempotent(run_module, admin_user):
inventory=inv, inventory=inv,
) )
result = run_module('tower_group', dict(name='Test Group', inventory='test-inv', state='present'), admin_user) result = run_module('group', dict(name='Test Group', inventory='test-inv', state='present'), admin_user)
result.pop('invocation') result.pop('invocation')
assert result == { assert result == {

View File

@@ -11,7 +11,7 @@ from awx.main.tests.functional.conftest import kube_credential, credentialtype_k
@pytest.mark.django_db @pytest.mark.django_db
def test_instance_group_create(run_module, admin_user): def test_instance_group_create(run_module, admin_user):
result = run_module( result = run_module(
'tower_instance_group', {'name': 'foo-group', 'policy_instance_percentage': 34, 'policy_instance_minimum': 12, 'state': 'present'}, admin_user 'instance_group', {'name': 'foo-group', 'policy_instance_percentage': 34, 'policy_instance_minimum': 12, 'state': 'present'}, admin_user
) )
assert not result.get('failed', False), result assert not result.get('failed', False), result
assert result['changed'] assert result['changed']
@@ -24,7 +24,7 @@ def test_instance_group_create(run_module, admin_user):
new_instance = Instance.objects.create(hostname='foo.example.com') new_instance = Instance.objects.create(hostname='foo.example.com')
# Set the new instance group only to the one instnace # Set the new instance group only to the one instnace
result = run_module('tower_instance_group', {'name': 'foo-group', 'instances': [new_instance.hostname], 'state': 'present'}, admin_user) result = run_module('instance_group', {'name': 'foo-group', 'instances': [new_instance.hostname], 'state': 'present'}, admin_user)
assert not result.get('failed', False), result assert not result.get('failed', False), result
assert result['changed'] assert result['changed']
@@ -41,9 +41,7 @@ def test_instance_group_create(run_module, admin_user):
def test_container_group_create(run_module, admin_user, kube_credential): def test_container_group_create(run_module, admin_user, kube_credential):
pod_spec = "{ 'Nothing': True }" pod_spec = "{ 'Nothing': True }"
result = run_module( result = run_module('instance_group', {'name': 'foo-c-group', 'credential': kube_credential.id, 'is_container_group': True, 'state': 'present'}, admin_user)
'tower_instance_group', {'name': 'foo-c-group', 'credential': kube_credential.id, 'is_container_group': True, 'state': 'present'}, admin_user
)
assert not result.get('failed', False), result['msg'] assert not result.get('failed', False), result['msg']
assert result['changed'] assert result['changed']
@@ -51,7 +49,7 @@ def test_container_group_create(run_module, admin_user, kube_credential):
assert ig.pod_spec_override == '' assert ig.pod_spec_override == ''
result = run_module( result = run_module(
'tower_instance_group', 'instance_group',
{'name': 'foo-c-group', 'credential': kube_credential.id, 'is_container_group': True, 'pod_spec_override': pod_spec, 'state': 'present'}, {'name': 'foo-c-group', 'credential': kube_credential.id, 'is_container_group': True, 'pod_spec_override': pod_spec, 'state': 'present'},
admin_user, admin_user,
) )

View File

@@ -13,7 +13,7 @@ def test_inventory_create(run_module, admin_user, organization, insights_credent
# Create an insights credential # Create an insights credential
result = run_module( result = run_module(
'tower_inventory', 'inventory',
{ {
'name': 'foo-inventory', 'name': 'foo-inventory',
'organization': organization.name, 'organization': organization.name,
@@ -39,7 +39,7 @@ def test_inventory_create(run_module, admin_user, organization, insights_credent
@pytest.mark.django_db @pytest.mark.django_db
def test_invalid_smart_inventory_create(run_module, admin_user, organization): def test_invalid_smart_inventory_create(run_module, admin_user, organization):
result = run_module( result = run_module(
'tower_inventory', 'inventory',
{'name': 'foo-inventory', 'organization': organization.name, 'kind': 'smart', 'host_filter': 'ansible', 'state': 'present'}, {'name': 'foo-inventory', 'organization': organization.name, 'kind': 'smart', 'host_filter': 'ansible', 'state': 'present'},
admin_user, admin_user,
) )
@@ -51,7 +51,7 @@ def test_invalid_smart_inventory_create(run_module, admin_user, organization):
@pytest.mark.django_db @pytest.mark.django_db
def test_valid_smart_inventory_create(run_module, admin_user, organization): def test_valid_smart_inventory_create(run_module, admin_user, organization):
result = run_module( result = run_module(
'tower_inventory', 'inventory',
{'name': 'foo-inventory', 'organization': organization.name, 'kind': 'smart', 'host_filter': 'name=my_host', 'state': 'present'}, {'name': 'foo-inventory', 'organization': organization.name, 'kind': 'smart', 'host_filter': 'name=my_host', 'state': 'present'},
admin_user, admin_user,
) )

View File

@@ -28,7 +28,7 @@ def project(base_inventory):
def test_inventory_source_create(run_module, admin_user, base_inventory, project): def test_inventory_source_create(run_module, admin_user, base_inventory, project):
source_path = '/var/lib/awx/example_source_path/' source_path = '/var/lib/awx/example_source_path/'
result = run_module( result = run_module(
'tower_inventory_source', 'inventory_source',
dict(name='foo', inventory=base_inventory.name, state='present', source='scm', source_path=source_path, source_project=project.name), dict(name='foo', inventory=base_inventory.name, state='present', source='scm', source_path=source_path, source_project=project.name),
admin_user, admin_user,
) )
@@ -49,7 +49,7 @@ def test_create_inventory_source_implied_org(run_module, admin_user):
inv = Inventory.objects.create(name='test-inv', organization=org) inv = Inventory.objects.create(name='test-inv', organization=org)
# Credential is not required for ec2 source, because of IAM roles # Credential is not required for ec2 source, because of IAM roles
result = run_module('tower_inventory_source', dict(name='Test Inventory Source', inventory='test-inv', source='ec2', state='present'), admin_user) result = run_module('inventory_source', dict(name='Test Inventory Source', inventory='test-inv', source='ec2', state='present'), admin_user)
assert result.pop('changed', None), result assert result.pop('changed', None), result
inv_src = InventorySource.objects.get(name='Test Inventory Source') inv_src = InventorySource.objects.get(name='Test Inventory Source')
@@ -72,7 +72,7 @@ def test_create_inventory_source_multiple_orgs(run_module, admin_user):
inv2 = Inventory.objects.create(name='test-inv', organization=org2) inv2 = Inventory.objects.create(name='test-inv', organization=org2)
result = run_module( result = run_module(
'tower_inventory_source', 'inventory_source',
dict(name='Test Inventory Source', inventory=inv2.name, organization='test-org-number-two', source='ec2', state='present'), dict(name='Test Inventory Source', inventory=inv2.name, organization='test-org-number-two', source='ec2', state='present'),
admin_user, admin_user,
) )
@@ -90,14 +90,14 @@ def test_create_inventory_source_multiple_orgs(run_module, admin_user):
@pytest.mark.django_db @pytest.mark.django_db
def test_falsy_value(run_module, admin_user, base_inventory): def test_falsy_value(run_module, admin_user, base_inventory):
result = run_module('tower_inventory_source', dict(name='falsy-test', inventory=base_inventory.name, source='ec2', update_on_launch=True), admin_user) result = run_module('inventory_source', dict(name='falsy-test', inventory=base_inventory.name, source='ec2', update_on_launch=True), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', None), result assert result.get('changed', None), result
inv_src = InventorySource.objects.get(name='falsy-test') inv_src = InventorySource.objects.get(name='falsy-test')
assert inv_src.update_on_launch is True assert inv_src.update_on_launch is True
result = run_module('tower_inventory_source', dict(name='falsy-test', inventory=base_inventory.name, source='ec2', update_on_launch=False), admin_user) result = run_module('inventory_source', dict(name='falsy-test', inventory=base_inventory.name, source='ec2', update_on_launch=False), admin_user)
inv_src.refresh_from_db() inv_src.refresh_from_db()
assert inv_src.update_on_launch is False assert inv_src.update_on_launch is False
@@ -127,7 +127,7 @@ def test_falsy_value(run_module, admin_user, base_inventory):
@pytest.mark.django_db @pytest.mark.django_db
def test_missing_required_credential(run_module, admin_user, base_inventory): def test_missing_required_credential(run_module, admin_user, base_inventory):
result = run_module('tower_inventory_source', dict(name='Test Azure Source', inventory=base_inventory.name, source='azure_rm', state='present'), admin_user) result = run_module('inventory_source', dict(name='Test Azure Source', inventory=base_inventory.name, source='azure_rm', state='present'), admin_user)
assert result.pop('failed', None) is True, result assert result.pop('failed', None) is True, result
assert 'Credential is required for a cloud source' in result.get('msg', '') assert 'Credential is required for a cloud source' in result.get('msg', '')
@@ -136,7 +136,7 @@ def test_missing_required_credential(run_module, admin_user, base_inventory):
@pytest.mark.django_db @pytest.mark.django_db
def test_source_project_not_for_cloud(run_module, admin_user, base_inventory, project): def test_source_project_not_for_cloud(run_module, admin_user, base_inventory, project):
result = run_module( result = run_module(
'tower_inventory_source', 'inventory_source',
dict(name='Test ec2 Inventory Source', inventory=base_inventory.name, source='ec2', state='present', source_project=project.name), dict(name='Test ec2 Inventory Source', inventory=base_inventory.name, source='ec2', state='present', source_project=project.name),
admin_user, admin_user,
) )
@@ -148,7 +148,7 @@ def test_source_project_not_for_cloud(run_module, admin_user, base_inventory, pr
@pytest.mark.django_db @pytest.mark.django_db
def test_source_path_not_for_cloud(run_module, admin_user, base_inventory): def test_source_path_not_for_cloud(run_module, admin_user, base_inventory):
result = run_module( result = run_module(
'tower_inventory_source', 'inventory_source',
dict(name='Test ec2 Inventory Source', inventory=base_inventory.name, source='ec2', state='present', source_path='where/am/I'), dict(name='Test ec2 Inventory Source', inventory=base_inventory.name, source='ec2', state='present', source_path='where/am/I'),
admin_user, admin_user,
) )
@@ -160,7 +160,7 @@ def test_source_path_not_for_cloud(run_module, admin_user, base_inventory):
@pytest.mark.django_db @pytest.mark.django_db
def test_scm_source_needs_project(run_module, admin_user, base_inventory): def test_scm_source_needs_project(run_module, admin_user, base_inventory):
result = run_module( result = run_module(
'tower_inventory_source', 'inventory_source',
dict( dict(
name='SCM inventory without project', inventory=base_inventory.name, state='present', source='scm', source_path='/var/lib/awx/example_source_path/' name='SCM inventory without project', inventory=base_inventory.name, state='present', source='scm', source_path='/var/lib/awx/example_source_path/'
), ),

View File

@@ -11,7 +11,7 @@ from awx.main.models import Job
@pytest.mark.django_db @pytest.mark.django_db
def test_job_wait_successful(run_module, admin_user): def test_job_wait_successful(run_module, admin_user):
job = Job.objects.create(status='successful', started=now(), finished=now()) job = Job.objects.create(status='successful', started=now(), finished=now())
result = run_module('tower_job_wait', dict(job_id=job.id), admin_user) result = run_module('job_wait', dict(job_id=job.id), admin_user)
result.pop('invocation', None) result.pop('invocation', None)
result['elapsed'] = float(result['elapsed']) result['elapsed'] = float(result['elapsed'])
assert result.pop('finished', '')[:10] == str(job.finished)[:10] assert result.pop('finished', '')[:10] == str(job.finished)[:10]
@@ -22,7 +22,7 @@ def test_job_wait_successful(run_module, admin_user):
@pytest.mark.django_db @pytest.mark.django_db
def test_job_wait_failed(run_module, admin_user): def test_job_wait_failed(run_module, admin_user):
job = Job.objects.create(status='failed', started=now(), finished=now()) job = Job.objects.create(status='failed', started=now(), finished=now())
result = run_module('tower_job_wait', dict(job_id=job.id), admin_user) result = run_module('job_wait', dict(job_id=job.id), admin_user)
result.pop('invocation', None) result.pop('invocation', None)
result['elapsed'] = float(result['elapsed']) result['elapsed'] = float(result['elapsed'])
assert result.pop('finished', '')[:10] == str(job.finished)[:10] assert result.pop('finished', '')[:10] == str(job.finished)[:10]
@@ -32,6 +32,6 @@ def test_job_wait_failed(run_module, admin_user):
@pytest.mark.django_db @pytest.mark.django_db
def test_job_wait_not_found(run_module, admin_user): def test_job_wait_not_found(run_module, admin_user):
result = run_module('tower_job_wait', dict(job_id=42), admin_user) result = run_module('job_wait', dict(job_id=42), admin_user)
result.pop('invocation', None) result.pop('invocation', None)
assert result == {"failed": True, "msg": "Unable to wait on job 42; that ID does not exist in Tower."} assert result == {"failed": True, "msg": "Unable to wait on job 42; that ID does not exist."}

View File

@@ -20,7 +20,7 @@ def test_create_job_template(run_module, admin_user, project, inventory):
'state': 'present', 'state': 'present',
} }
result = run_module('tower_job_template', module_args, admin_user) result = run_module('job_template', module_args, admin_user)
jt = JobTemplate.objects.get(name='foo') jt = JobTemplate.objects.get(name='foo')
assert jt.extra_vars == '{"foo": "bar"}' assert jt.extra_vars == '{"foo": "bar"}'
@@ -48,7 +48,7 @@ def test_resets_job_template_values(run_module, admin_user, project, inventory):
'ask_limit_on_launch': True, 'ask_limit_on_launch': True,
} }
result = run_module('tower_job_template', module_args, admin_user) result = run_module('job_template', module_args, admin_user)
jt = JobTemplate.objects.get(name='foo') jt = JobTemplate.objects.get(name='foo')
assert jt.forks == 20 assert jt.forks == 20
@@ -70,7 +70,7 @@ def test_resets_job_template_values(run_module, admin_user, project, inventory):
'ask_limit_on_launch': False, 'ask_limit_on_launch': False,
} }
result = run_module('tower_job_template', module_args, admin_user) result = run_module('job_template', module_args, admin_user)
assert result['changed'] assert result['changed']
jt = JobTemplate.objects.get(name='foo') jt = JobTemplate.objects.get(name='foo')
@@ -92,7 +92,7 @@ def test_job_launch_with_prompting(run_module, admin_user, project, organization
ask_credential_on_launch=True, ask_credential_on_launch=True,
) )
result = run_module( result = run_module(
'tower_job_launch', 'job_launch',
dict( dict(
job_template='foo', job_template='foo',
inventory=inventory.name, inventory=inventory.name,
@@ -112,7 +112,7 @@ def test_job_launch_with_prompting(run_module, admin_user, project, organization
@pytest.mark.django_db @pytest.mark.django_db
def test_job_template_with_new_credentials(run_module, admin_user, project, inventory, machine_credential, vault_credential): def test_job_template_with_new_credentials(run_module, admin_user, project, inventory, machine_credential, vault_credential):
result = run_module( result = run_module(
'tower_job_template', 'job_template',
dict( dict(
name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, credentials=[machine_credential.name, vault_credential.name] name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, credentials=[machine_credential.name, vault_credential.name]
), ),
@@ -126,7 +126,7 @@ def test_job_template_with_new_credentials(run_module, admin_user, project, inve
prior_ct = ActivityStream.objects.count() prior_ct = ActivityStream.objects.count()
result = run_module( result = run_module(
'tower_job_template', 'job_template',
dict( dict(
name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, credentials=[machine_credential.name, vault_credential.name] name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, credentials=[machine_credential.name, vault_credential.name]
), ),
@@ -144,7 +144,7 @@ def test_job_template_with_new_credentials(run_module, admin_user, project, inve
@pytest.mark.django_db @pytest.mark.django_db
def test_job_template_with_survey_spec(run_module, admin_user, project, inventory, survey_spec): def test_job_template_with_survey_spec(run_module, admin_user, project, inventory, survey_spec):
result = run_module( result = run_module(
'tower_job_template', 'job_template',
dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=survey_spec, survey_enabled=True), dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=survey_spec, survey_enabled=True),
admin_user, admin_user,
) )
@@ -156,7 +156,7 @@ def test_job_template_with_survey_spec(run_module, admin_user, project, inventor
prior_ct = ActivityStream.objects.count() prior_ct = ActivityStream.objects.count()
result = run_module( result = run_module(
'tower_job_template', 'job_template',
dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=survey_spec, survey_enabled=True), dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=survey_spec, survey_enabled=True),
admin_user, admin_user,
) )
@@ -172,7 +172,7 @@ def test_job_template_with_survey_spec(run_module, admin_user, project, inventor
@pytest.mark.django_db @pytest.mark.django_db
def test_job_template_with_wrong_survey_spec(run_module, admin_user, project, inventory, survey_spec): def test_job_template_with_wrong_survey_spec(run_module, admin_user, project, inventory, survey_spec):
result = run_module( result = run_module(
'tower_job_template', 'job_template',
dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=survey_spec, survey_enabled=True), dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=survey_spec, survey_enabled=True),
admin_user, admin_user,
) )
@@ -187,7 +187,7 @@ def test_job_template_with_wrong_survey_spec(run_module, admin_user, project, in
del survey_spec['description'] del survey_spec['description']
result = run_module( result = run_module(
'tower_job_template', 'job_template',
dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=survey_spec, survey_enabled=True), dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=survey_spec, survey_enabled=True),
admin_user, admin_user,
) )
@@ -204,7 +204,7 @@ def test_job_template_with_survey_encrypted_default(run_module, admin_user, proj
} }
for i in range(2): for i in range(2):
result = run_module( result = run_module(
'tower_job_template', 'job_template',
dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=spec, survey_enabled=True), dict(name='foo', playbook='helloworld.yml', project=project.name, inventory=inventory.name, survey_spec=spec, survey_enabled=True),
admin_user, admin_user,
) )
@@ -236,9 +236,7 @@ def test_associate_only_on_success(run_module, admin_user, organization, project
jt.notification_templates_error.add(nt1) jt.notification_templates_error.add(nt1)
# test preservation of error NTs when success NTs are added # test preservation of error NTs when success NTs are added
result = run_module( result = run_module('job_template', dict(name='foo', playbook='helloworld.yml', project=project.name, notification_templates_success=['nt2']), admin_user)
'tower_job_template', dict(name='foo', playbook='helloworld.yml', project=project.name, notification_templates_success=['nt2']), admin_user
)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', True), result assert result.get('changed', True), result
@@ -246,7 +244,7 @@ def test_associate_only_on_success(run_module, admin_user, organization, project
assert list(jt.notification_templates_error.values_list('id', flat=True)) == [nt1.id] assert list(jt.notification_templates_error.values_list('id', flat=True)) == [nt1.id]
# test removal to empty list # test removal to empty list
result = run_module('tower_job_template', dict(name='foo', playbook='helloworld.yml', project=project.name, notification_templates_success=[]), admin_user) result = run_module('job_template', dict(name='foo', playbook='helloworld.yml', project=project.name, notification_templates_success=[]), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', True), result assert result.get('changed', True), result

View File

@@ -9,7 +9,7 @@ from awx.main.models import Label
@pytest.mark.django_db @pytest.mark.django_db
def test_create_label(run_module, admin_user, organization): def test_create_label(run_module, admin_user, organization):
result = run_module('tower_label', dict(name='test-label', organization=organization.name), admin_user) result = run_module('label', dict(name='test-label', organization=organization.name), admin_user)
assert not result.get('failed'), result.get('msg', result) assert not result.get('failed'), result.get('msg', result)
assert result.get('changed', False) assert result.get('changed', False)
@@ -18,7 +18,7 @@ def test_create_label(run_module, admin_user, organization):
@pytest.mark.django_db @pytest.mark.django_db
def test_create_label_using_org_id(run_module, admin_user, organization): def test_create_label_using_org_id(run_module, admin_user, organization):
result = run_module('tower_label', dict(name='test-label', organization=organization.id), admin_user) result = run_module('label', dict(name='test-label', organization=organization.id), admin_user)
assert not result.get('failed'), result.get('msg', result) assert not result.get('failed'), result.get('msg', result)
assert result.get('changed', False) assert result.get('changed', False)
@@ -29,7 +29,7 @@ def test_create_label_using_org_id(run_module, admin_user, organization):
def test_modify_label(run_module, admin_user, organization): def test_modify_label(run_module, admin_user, organization):
label = Label.objects.create(name='test-label', organization=organization) label = Label.objects.create(name='test-label', organization=organization)
result = run_module('tower_label', dict(name='test-label', new_name='renamed-label', organization=organization.name), admin_user) result = run_module('label', dict(name='test-label', new_name='renamed-label', organization=organization.name), admin_user)
assert not result.get('failed'), result.get('msg', result) assert not result.get('failed'), result.get('msg', result)
assert result.get('changed', False) assert result.get('changed', False)

View File

@@ -10,12 +10,12 @@ from requests.models import Response
from unittest import mock from unittest import mock
awx_name = 'AWX' awx_name = 'AWX'
tower_name = 'Red Hat Ansible Tower' controller_name = 'Red Hat Automation Platform Controller'
ping_version = '1.2.3' ping_version = '1.2.3'
def getTowerheader(self, header_name, default): def getTowerheader(self, header_name, default):
mock_headers = {'X-API-Product-Name': tower_name, 'X-API-Product-Version': ping_version} mock_headers = {'X-API-Product-Name': controller_name, 'X-API-Product-Version': ping_version}
return mock_headers.get(header_name, default) return mock_headers.get(header_name, default)
@@ -32,7 +32,7 @@ def status(self):
return 200 return 200
def mock_tower_ping_response(self, method, url, **kwargs): def mock_controller_ping_response(self, method, url, **kwargs):
r = Response() r = Response()
r.getheader = getTowerheader.__get__(r) r.getheader = getTowerheader.__get__(r)
r.read = read.__get__(r) r.read = read.__get__(r)
@@ -49,12 +49,12 @@ def mock_awx_ping_response(self, method, url, **kwargs):
def test_version_warning(collection_import, silence_warning): def test_version_warning(collection_import, silence_warning):
TowerAPIModule = collection_import('plugins.module_utils.tower_api').TowerAPIModule ControllerAPIModule = collection_import('plugins.module_utils.controller_api').ControllerAPIModule
cli_data = {'ANSIBLE_MODULE_ARGS': {}} cli_data = {'ANSIBLE_MODULE_ARGS': {}}
testargs = ['module_file2.py', json.dumps(cli_data)] testargs = ['module_file2.py', json.dumps(cli_data)]
with mock.patch.object(sys, 'argv', testargs): with mock.patch.object(sys, 'argv', testargs):
with mock.patch('ansible.module_utils.urls.Request.open', new=mock_awx_ping_response): with mock.patch('ansible.module_utils.urls.Request.open', new=mock_awx_ping_response):
my_module = TowerAPIModule(argument_spec=dict()) my_module = ControllerAPIModule(argument_spec=dict())
my_module._COLLECTION_VERSION = "2.0.0" my_module._COLLECTION_VERSION = "2.0.0"
my_module._COLLECTION_TYPE = "awx" my_module._COLLECTION_TYPE = "awx"
my_module.get_endpoint('ping') my_module.get_endpoint('ping')
@@ -64,13 +64,13 @@ def test_version_warning(collection_import, silence_warning):
def test_version_warning_strictness_awx(collection_import, silence_warning): def test_version_warning_strictness_awx(collection_import, silence_warning):
TowerAPIModule = collection_import('plugins.module_utils.tower_api').TowerAPIModule ControllerAPIModule = collection_import('plugins.module_utils.controller_api').ControllerAPIModule
cli_data = {'ANSIBLE_MODULE_ARGS': {}} cli_data = {'ANSIBLE_MODULE_ARGS': {}}
testargs = ['module_file2.py', json.dumps(cli_data)] testargs = ['module_file2.py', json.dumps(cli_data)]
# Compare 1.0.0 to 1.2.3 (major matches) # Compare 1.0.0 to 1.2.3 (major matches)
with mock.patch.object(sys, 'argv', testargs): with mock.patch.object(sys, 'argv', testargs):
with mock.patch('ansible.module_utils.urls.Request.open', new=mock_awx_ping_response): with mock.patch('ansible.module_utils.urls.Request.open', new=mock_awx_ping_response):
my_module = TowerAPIModule(argument_spec=dict()) my_module = ControllerAPIModule(argument_spec=dict())
my_module._COLLECTION_VERSION = "1.0.0" my_module._COLLECTION_VERSION = "1.0.0"
my_module._COLLECTION_TYPE = "awx" my_module._COLLECTION_TYPE = "awx"
my_module.get_endpoint('ping') my_module.get_endpoint('ping')
@@ -79,47 +79,47 @@ def test_version_warning_strictness_awx(collection_import, silence_warning):
# Compare 1.2.0 to 1.2.3 (major matches minor does not count) # Compare 1.2.0 to 1.2.3 (major matches minor does not count)
with mock.patch.object(sys, 'argv', testargs): with mock.patch.object(sys, 'argv', testargs):
with mock.patch('ansible.module_utils.urls.Request.open', new=mock_awx_ping_response): with mock.patch('ansible.module_utils.urls.Request.open', new=mock_awx_ping_response):
my_module = TowerAPIModule(argument_spec=dict()) my_module = ControllerAPIModule(argument_spec=dict())
my_module._COLLECTION_VERSION = "1.2.0" my_module._COLLECTION_VERSION = "1.2.0"
my_module._COLLECTION_TYPE = "awx" my_module._COLLECTION_TYPE = "awx"
my_module.get_endpoint('ping') my_module.get_endpoint('ping')
silence_warning.assert_not_called() silence_warning.assert_not_called()
def test_version_warning_strictness_tower(collection_import, silence_warning): def test_version_warning_strictness_controller(collection_import, silence_warning):
TowerAPIModule = collection_import('plugins.module_utils.tower_api').TowerAPIModule ControllerAPIModule = collection_import('plugins.module_utils.controller_api').ControllerAPIModule
cli_data = {'ANSIBLE_MODULE_ARGS': {}} cli_data = {'ANSIBLE_MODULE_ARGS': {}}
testargs = ['module_file2.py', json.dumps(cli_data)] testargs = ['module_file2.py', json.dumps(cli_data)]
# Compare 1.2.0 to 1.2.3 (major/minor matches) # Compare 1.2.0 to 1.2.3 (major/minor matches)
with mock.patch.object(sys, 'argv', testargs): with mock.patch.object(sys, 'argv', testargs):
with mock.patch('ansible.module_utils.urls.Request.open', new=mock_tower_ping_response): with mock.patch('ansible.module_utils.urls.Request.open', new=mock_controller_ping_response):
my_module = TowerAPIModule(argument_spec=dict()) my_module = ControllerAPIModule(argument_spec=dict())
my_module._COLLECTION_VERSION = "1.2.0" my_module._COLLECTION_VERSION = "1.2.0"
my_module._COLLECTION_TYPE = "tower" my_module._COLLECTION_TYPE = "controller"
my_module.get_endpoint('ping') my_module.get_endpoint('ping')
silence_warning.assert_not_called() silence_warning.assert_not_called()
# Compare 1.0.0 to 1.2.3 (major/minor fail to match) # Compare 1.0.0 to 1.2.3 (major/minor fail to match)
with mock.patch.object(sys, 'argv', testargs): with mock.patch.object(sys, 'argv', testargs):
with mock.patch('ansible.module_utils.urls.Request.open', new=mock_tower_ping_response): with mock.patch('ansible.module_utils.urls.Request.open', new=mock_controller_ping_response):
my_module = TowerAPIModule(argument_spec=dict()) my_module = ControllerAPIModule(argument_spec=dict())
my_module._COLLECTION_VERSION = "1.0.0" my_module._COLLECTION_VERSION = "1.0.0"
my_module._COLLECTION_TYPE = "tower" my_module._COLLECTION_TYPE = "controller"
my_module.get_endpoint('ping') my_module.get_endpoint('ping')
silence_warning.assert_called_once_with( silence_warning.assert_called_once_with(
'You are running collection version {0} but connecting to {1} version {2}'.format(my_module._COLLECTION_VERSION, tower_name, ping_version) 'You are running collection version {0} but connecting to {1} version {2}'.format(my_module._COLLECTION_VERSION, controller_name, ping_version)
) )
def test_type_warning(collection_import, silence_warning): def test_type_warning(collection_import, silence_warning):
TowerAPIModule = collection_import('plugins.module_utils.tower_api').TowerAPIModule ControllerAPIModule = collection_import('plugins.module_utils.controller_api').ControllerAPIModule
cli_data = {'ANSIBLE_MODULE_ARGS': {}} cli_data = {'ANSIBLE_MODULE_ARGS': {}}
testargs = ['module_file2.py', json.dumps(cli_data)] testargs = ['module_file2.py', json.dumps(cli_data)]
with mock.patch.object(sys, 'argv', testargs): with mock.patch.object(sys, 'argv', testargs):
with mock.patch('ansible.module_utils.urls.Request.open', new=mock_awx_ping_response): with mock.patch('ansible.module_utils.urls.Request.open', new=mock_awx_ping_response):
my_module = TowerAPIModule(argument_spec={}) my_module = ControllerAPIModule(argument_spec={})
my_module._COLLECTION_VERSION = ping_version my_module._COLLECTION_VERSION = ping_version
my_module._COLLECTION_TYPE = "tower" my_module._COLLECTION_TYPE = "controller"
my_module.get_endpoint('ping') my_module.get_endpoint('ping')
silence_warning.assert_called_once_with( silence_warning.assert_called_once_with(
'You are using the {0} version of this collection but connecting to {1}'.format(my_module._COLLECTION_TYPE, awx_name) 'You are using the {0} version of this collection but connecting to {1}'.format(my_module._COLLECTION_TYPE, awx_name)
@@ -128,20 +128,20 @@ def test_type_warning(collection_import, silence_warning):
def test_duplicate_config(collection_import, silence_warning): def test_duplicate_config(collection_import, silence_warning):
# imports done here because of PATH issues unique to this test suite # imports done here because of PATH issues unique to this test suite
TowerAPIModule = collection_import('plugins.module_utils.tower_api').TowerAPIModule ControllerAPIModule = collection_import('plugins.module_utils.controller_api').ControllerAPIModule
data = {'name': 'zigzoom', 'zig': 'zoom', 'tower_username': 'bob', 'tower_config_file': 'my_config'} data = {'name': 'zigzoom', 'zig': 'zoom', 'controller_username': 'bob', 'controller_config_file': 'my_config'}
with mock.patch.object(TowerAPIModule, 'load_config') as mock_load: with mock.patch.object(ControllerAPIModule, 'load_config') as mock_load:
argument_spec = dict( argument_spec = dict(
name=dict(required=True), name=dict(required=True),
zig=dict(type='str'), zig=dict(type='str'),
) )
TowerAPIModule(argument_spec=argument_spec, direct_params=data) ControllerAPIModule(argument_spec=argument_spec, direct_params=data)
assert mock_load.mock_calls[-1] == mock.call('my_config') assert mock_load.mock_calls[-1] == mock.call('my_config')
silence_warning.assert_called_once_with( silence_warning.assert_called_once_with(
'The parameter(s) tower_username were provided at the same time as ' 'The parameter(s) controller_username were provided at the same time as '
'tower_config_file. Precedence may be unstable, ' 'controller_config_file. Precedence may be unstable, '
'we suggest either using config file or params.' 'we suggest either using config file or params.'
) )
@@ -152,12 +152,12 @@ def test_no_templated_values(collection_import):
Those replacements should happen at build time, so they should not be Those replacements should happen at build time, so they should not be
checked into source. checked into source.
""" """
TowerAPIModule = collection_import('plugins.module_utils.tower_api').TowerAPIModule ControllerAPIModule = collection_import('plugins.module_utils.controller_api').ControllerAPIModule
assert TowerAPIModule._COLLECTION_VERSION == "0.0.1-devel", ( assert ControllerAPIModule._COLLECTION_VERSION == "0.0.1-devel", (
'The collection version is templated when the collection is built ' 'and the code should retain the placeholder of "0.0.1-devel".' 'The collection version is templated when the collection is built ' 'and the code should retain the placeholder of "0.0.1-devel".'
) )
InventoryModule = collection_import('plugins.inventory.tower').InventoryModule InventoryModule = collection_import('plugins.inventory.controller').InventoryModule
assert InventoryModule.NAME == 'awx.awx.tower', ( assert InventoryModule.NAME == 'awx.awx.controller', (
'The inventory plugin FQCN is templated when the collection is built ' 'and the code should retain the default of awx.awx.' 'The inventory plugin FQCN is templated when the collection is built ' 'and the code should retain the default of awx.awx.'
) )
@@ -167,12 +167,12 @@ def test_conflicting_name_and_id(run_module, admin_user):
one item has an id that matches input one item has an id that matches input
one item has a name that matches input one item has a name that matches input
We should preference the id over the name. We should preference the id over the name.
Otherwise, the universality of the tower_api lookup plugin is compromised. Otherwise, the universality of the controller_api lookup plugin is compromised.
""" """
org_by_id = Organization.objects.create(name='foo') org_by_id = Organization.objects.create(name='foo')
slug = str(org_by_id.id) slug = str(org_by_id.id)
org_by_name = Organization.objects.create(name=slug) org_by_name = Organization.objects.create(name=slug)
result = run_module('tower_team', {'name': 'foo_team', 'description': 'fooin around', 'organization': slug}, admin_user) result = run_module('team', {'name': 'foo_team', 'description': 'fooin around', 'organization': slug}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
team = Team.objects.filter(name='foo_team').first() team = Team.objects.filter(name='foo_team').first()
assert str(team.organization_id) == slug, 'Lookup by id should be preferenced over name in cases of conflict.' assert str(team.organization_id) == slug, 'Lookup by id should be preferenced over name in cases of conflict.'
@@ -195,9 +195,7 @@ def test_multiple_lookup(run_module, admin_user):
scm_type='git', scm_type='git',
scm_url="https://github.com/ansible/ansible-tower-samples", scm_url="https://github.com/ansible/ansible-tower-samples",
) )
result = run_module( result = run_module('job_template', {'name': 'Demo Job Template', 'project': proj1.name, 'inventory': inv.id, 'playbook': 'hello_world.yml'}, admin_user)
'tower_job_template', {'name': 'Demo Job Template', 'project': proj1.name, 'inventory': inv.id, 'playbook': 'hello_world.yml'}, admin_user
)
assert result.get('failed', False) assert result.get('failed', False)
assert 'projects' in result['msg'] assert 'projects' in result['msg']
assert 'foo' in result['msg'] assert 'foo' in result['msg']

View File

@@ -35,7 +35,7 @@ def test_create_modify_notification_template(run_module, admin_user, organizatio
'timeout': 4, 'timeout': 4,
} }
result = run_module( result = run_module(
'tower_notification_template', 'notification_template',
dict( dict(
name='foo-notification-template', name='foo-notification-template',
organization=organization.name, organization=organization.name,
@@ -54,7 +54,7 @@ def test_create_modify_notification_template(run_module, admin_user, organizatio
# Test no-op, this is impossible if the notification_configuration is given # Test no-op, this is impossible if the notification_configuration is given
# because we cannot determine if password fields changed # because we cannot determine if password fields changed
result = run_module( result = run_module(
'tower_notification_template', 'notification_template',
dict( dict(
name='foo-notification-template', name='foo-notification-template',
organization=organization.name, organization=organization.name,
@@ -68,7 +68,7 @@ def test_create_modify_notification_template(run_module, admin_user, organizatio
# Test a change in the configuration # Test a change in the configuration
nt_config['timeout'] = 12 nt_config['timeout'] = 12
result = run_module( result = run_module(
'tower_notification_template', 'notification_template',
dict( dict(
name='foo-notification-template', name='foo-notification-template',
organization=organization.name, organization=organization.name,
@@ -87,7 +87,7 @@ def test_create_modify_notification_template(run_module, admin_user, organizatio
@pytest.mark.django_db @pytest.mark.django_db
def test_invalid_notification_configuration(run_module, admin_user, organization): def test_invalid_notification_configuration(run_module, admin_user, organization):
result = run_module( result = run_module(
'tower_notification_template', 'notification_template',
dict( dict(
name='foo-notification-template', name='foo-notification-template',
organization=organization.name, organization=organization.name,
@@ -104,7 +104,7 @@ def test_invalid_notification_configuration(run_module, admin_user, organization
def test_deprecated_to_modern_no_op(run_module, admin_user, organization): def test_deprecated_to_modern_no_op(run_module, admin_user, organization):
nt_config = {'url': 'http://www.example.com/hook', 'headers': {'X-Custom-Header': 'value123'}} nt_config = {'url': 'http://www.example.com/hook', 'headers': {'X-Custom-Header': 'value123'}}
result = run_module( result = run_module(
'tower_notification_template', 'notification_template',
dict( dict(
name='foo-notification-template', name='foo-notification-template',
organization=organization.name, organization=organization.name,
@@ -117,7 +117,7 @@ def test_deprecated_to_modern_no_op(run_module, admin_user, organization):
assert result.pop('changed', None), result assert result.pop('changed', None), result
result = run_module( result = run_module(
'tower_notification_template', 'notification_template',
dict( dict(
name='foo-notification-template', name='foo-notification-template',
organization=organization.name, organization=organization.name,
@@ -142,7 +142,7 @@ def test_build_notification_message_undefined(run_module, admin_user, organizati
custom_start_template = {'body': '{"started_by": "{{ job.summary_fields.created_by.username | default(\'My Placeholder\') }}"}'} custom_start_template = {'body': '{"started_by": "{{ job.summary_fields.created_by.username | default(\'My Placeholder\') }}"}'}
messages = {'started': custom_start_template, 'success': None, 'error': None, 'workflow_approval': None} messages = {'started': custom_start_template, 'success': None, 'error': None, 'workflow_approval': None}
result = run_module( result = run_module(
'tower_notification_template', 'notification_template',
dict( dict(
name='foo-notification-template', name='foo-notification-template',
organization=organization.name, organization=organization.name,

View File

@@ -15,15 +15,15 @@ def test_create_organization(run_module, admin_user):
'description': 'barfoo', 'description': 'barfoo',
'state': 'present', 'state': 'present',
'max_hosts': '0', 'max_hosts': '0',
'tower_host': None, 'controller_host': None,
'tower_username': None, 'controller_username': None,
'tower_password': None, 'controller_password': None,
'validate_certs': None, 'validate_certs': None,
'tower_oauthtoken': None, 'controller_oauthtoken': None,
'tower_config_file': None, 'controller_config_file': None,
} }
result = run_module('tower_organization', module_args, admin_user) result = run_module('organization', module_args, admin_user)
assert result.get('changed'), result assert result.get('changed'), result
org = Organization.objects.get(name='foo') org = Organization.objects.get(name='foo')

View File

@@ -10,7 +10,7 @@ from awx.main.models import Project
@pytest.mark.django_db @pytest.mark.django_db
def test_create_project(run_module, admin_user, organization, silence_warning): def test_create_project(run_module, admin_user, organization, silence_warning):
result = run_module( result = run_module(
'tower_project', 'project',
dict(name='foo', organization=organization.name, scm_type='git', scm_url='https://foo.invalid', wait=False, scm_update_cache_timeout=5), dict(name='foo', organization=organization.name, scm_type='git', scm_url='https://foo.invalid', wait=False, scm_update_cache_timeout=5),
admin_user, admin_user,
) )

View File

@@ -14,7 +14,7 @@ def test_grant_organization_permission(run_module, admin_user, organization, sta
if state == 'absent': if state == 'absent':
organization.admin_role.members.add(rando) organization.admin_role.members.add(rando)
result = run_module('tower_role', {'user': rando.username, 'organization': organization.name, 'role': 'admin', 'state': state}, admin_user) result = run_module('role', {'user': rando.username, 'organization': organization.name, 'role': 'admin', 'state': state}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
if state == 'present': if state == 'present':
@@ -31,7 +31,7 @@ def test_grant_workflow_permission(run_module, admin_user, organization, state):
if state == 'absent': if state == 'absent':
wfjt.execute_role.members.add(rando) wfjt.execute_role.members.add(rando)
result = run_module('tower_role', {'user': rando.username, 'workflow': wfjt.name, 'role': 'execute', 'state': state}, admin_user) result = run_module('role', {'user': rando.username, 'workflow': wfjt.name, 'role': 'execute', 'state': state}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
if state == 'present': if state == 'present':
@@ -49,7 +49,7 @@ def test_grant_workflow_list_permission(run_module, admin_user, organization, st
wfjt.execute_role.members.add(rando) wfjt.execute_role.members.add(rando)
result = run_module( result = run_module(
'tower_role', 'role',
{'user': rando.username, 'lookup_organization': wfjt.organization.name, 'workflows': [wfjt.name], 'role': 'execute', 'state': state}, {'user': rando.username, 'lookup_organization': wfjt.organization.name, 'workflows': [wfjt.name], 'role': 'execute', 'state': state},
admin_user, admin_user,
) )
@@ -69,7 +69,7 @@ def test_grant_workflow_approval_permission(run_module, admin_user, organization
if state == 'absent': if state == 'absent':
wfjt.execute_role.members.add(rando) wfjt.execute_role.members.add(rando)
result = run_module('tower_role', {'user': rando.username, 'workflow': wfjt.name, 'role': 'approval', 'state': state}, admin_user) result = run_module('role', {'user': rando.username, 'workflow': wfjt.name, 'role': 'approval', 'state': state}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
if state == 'present': if state == 'present':
@@ -81,7 +81,7 @@ def test_grant_workflow_approval_permission(run_module, admin_user, organization
@pytest.mark.django_db @pytest.mark.django_db
def test_invalid_role(run_module, admin_user, project): def test_invalid_role(run_module, admin_user, project):
rando = User.objects.create(username='rando') rando = User.objects.create(username='rando')
result = run_module('tower_role', {'user': rando.username, 'project': project.name, 'role': 'adhoc', 'state': 'present'}, admin_user) result = run_module('role', {'user': rando.username, 'project': project.name, 'role': 'adhoc', 'state': 'present'}, admin_user)
assert result.get('failed', False) assert result.get('failed', False)
msg = result.get('msg') msg = result.get('msg')
assert 'has no role adhoc_role' in msg assert 'has no role adhoc_role' in msg

View File

@@ -13,7 +13,7 @@ from awx.api.serializers import SchedulePreviewSerializer
@pytest.mark.django_db @pytest.mark.django_db
def test_create_schedule(run_module, job_template, admin_user): def test_create_schedule(run_module, job_template, admin_user):
my_rrule = 'DTSTART;TZID=Zulu:20200416T034507 RRULE:FREQ=MONTHLY;INTERVAL=1' my_rrule = 'DTSTART;TZID=Zulu:20200416T034507 RRULE:FREQ=MONTHLY;INTERVAL=1'
result = run_module('tower_schedule', {'name': 'foo_schedule', 'unified_job_template': job_template.name, 'rrule': my_rrule}, admin_user) result = run_module('schedule', {'name': 'foo_schedule', 'unified_job_template': job_template.name, 'rrule': my_rrule}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
schedule = Schedule.objects.filter(name='foo_schedule').first() schedule = Schedule.objects.filter(name='foo_schedule').first()
@@ -68,7 +68,7 @@ def test_create_schedule(run_module, job_template, admin_user):
], ],
) )
def test_rrule_lookup_plugin(collection_import, freq, kwargs, expect): def test_rrule_lookup_plugin(collection_import, freq, kwargs, expect):
LookupModule = collection_import('plugins.lookup.tower_schedule_rrule').LookupModule LookupModule = collection_import('plugins.lookup.schedule_rrule').LookupModule
generated_rule = LookupModule.get_rrule(freq, kwargs) generated_rule = LookupModule.get_rrule(freq, kwargs)
assert generated_rule == expect assert generated_rule == expect
rrule_checker = SchedulePreviewSerializer() rrule_checker = SchedulePreviewSerializer()
@@ -79,7 +79,7 @@ def test_rrule_lookup_plugin(collection_import, freq, kwargs, expect):
@pytest.mark.parametrize("freq", ('none', 'minute', 'hour', 'day', 'week', 'month')) @pytest.mark.parametrize("freq", ('none', 'minute', 'hour', 'day', 'week', 'month'))
def test_empty_schedule_rrule(collection_import, freq): def test_empty_schedule_rrule(collection_import, freq):
LookupModule = collection_import('plugins.lookup.tower_schedule_rrule').LookupModule LookupModule = collection_import('plugins.lookup.schedule_rrule').LookupModule
if freq == 'day': if freq == 'day':
pfreq = 'DAILY' pfreq = 'DAILY'
elif freq == 'none': elif freq == 'none':
@@ -123,7 +123,7 @@ def test_empty_schedule_rrule(collection_import, freq):
], ],
) )
def test_rrule_lookup_plugin_failure(collection_import, freq, kwargs, msg): def test_rrule_lookup_plugin_failure(collection_import, freq, kwargs, msg):
LookupModule = collection_import('plugins.lookup.tower_schedule_rrule').LookupModule LookupModule = collection_import('plugins.lookup.schedule_rrule').LookupModule
with pytest.raises(AnsibleError) as e: with pytest.raises(AnsibleError) as e:
assert LookupModule.get_rrule(freq, kwargs) assert LookupModule.get_rrule(freq, kwargs)
assert msg in str(e.value) assert msg in str(e.value)

View File

@@ -1,57 +0,0 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import pytest
import json
from awx.main.models import Organization, Project, Inventory, Host, CredentialType, Credential, JobTemplate
# warns based on password_management param, but not security issue
@pytest.mark.django_db
def test_receive_send_jt(run_module, admin_user, mocker, silence_deprecation):
org = Organization.objects.create(name='SRtest')
proj = Project.objects.create(
name='SRtest',
playbook_files=['debug.yml'],
scm_type='git',
scm_url='https://github.com/ansible/test-playbooks.git',
organization=org,
allow_override=True, # so we do not require playbooks populated
)
inv = Inventory.objects.create(name='SRtest', organization=org)
Host.objects.create(name='SRtest', inventory=inv)
ct = CredentialType.defaults['ssh']()
ct.save()
cred = Credential.objects.create(name='SRtest', credential_type=ct, organization=org)
jt = JobTemplate.objects.create(name='SRtest', project=proj, inventory=inv, playbook='helloworld.yml')
jt.credentials.add(cred)
jt.admin_role.members.add(admin_user) # work around send/receive bug
# receive everything
result = run_module('tower_receive', dict(all=True), admin_user)
assert 'assets' in result, result
assets = result['assets']
assert not result.get('changed', True)
assert set(a['asset_type'] for a in assets) == set(('organization', 'inventory', 'job_template', 'credential', 'project', 'user'))
# delete everything
for obj in (jt, inv, proj, cred, org):
obj.delete()
def fake_wait(self, pk, parent_pk=None, **kwargs):
return {"changed": True}
# recreate everything
with mocker.patch('sys.stdin.isatty', return_value=True):
with mocker.patch('tower_cli.models.base.MonitorableResource.wait'):
result = run_module('tower_send', dict(assets=json.dumps(assets)), admin_user)
assert not result.get('failed'), result
new = JobTemplate.objects.get(name='SRtest')
assert new.project.name == 'SRtest'
assert new.inventory.name == 'SRtest'
assert [cred.name for cred in new.credentials.all()] == ['SRtest']

View File

@@ -10,7 +10,7 @@ from awx.conf.models import Setting
@pytest.mark.django_db @pytest.mark.django_db
def test_setting_flat_value(run_module, admin_user): def test_setting_flat_value(run_module, admin_user):
the_value = 'CN=service_account,OU=ServiceAccounts,DC=domain,DC=company,DC=org' the_value = 'CN=service_account,OU=ServiceAccounts,DC=domain,DC=company,DC=org'
result = run_module('tower_settings', dict(name='AUTH_LDAP_BIND_DN', value=the_value), admin_user) result = run_module('settings', dict(name='AUTH_LDAP_BIND_DN', value=the_value), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result assert result.get('changed'), result
@@ -20,7 +20,7 @@ def test_setting_flat_value(run_module, admin_user):
@pytest.mark.django_db @pytest.mark.django_db
def test_setting_dict_value(run_module, admin_user): def test_setting_dict_value(run_module, admin_user):
the_value = {'email': 'mail', 'first_name': 'givenName', 'last_name': 'surname'} the_value = {'email': 'mail', 'first_name': 'givenName', 'last_name': 'surname'}
result = run_module('tower_settings', dict(name='AUTH_LDAP_USER_ATTR_MAP', value=the_value), admin_user) result = run_module('settings', dict(name='AUTH_LDAP_USER_ATTR_MAP', value=the_value), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result assert result.get('changed'), result
@@ -30,7 +30,7 @@ def test_setting_dict_value(run_module, admin_user):
@pytest.mark.django_db @pytest.mark.django_db
def test_setting_nested_type(run_module, admin_user): def test_setting_nested_type(run_module, admin_user):
the_value = {'email': 'mail', 'first_name': 'givenName', 'last_name': 'surname'} the_value = {'email': 'mail', 'first_name': 'givenName', 'last_name': 'surname'}
result = run_module('tower_settings', dict(settings={'AUTH_LDAP_USER_ATTR_MAP': the_value}), admin_user) result = run_module('settings', dict(settings={'AUTH_LDAP_USER_ATTR_MAP': the_value}), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result assert result.get('changed'), result
@@ -40,7 +40,7 @@ def test_setting_nested_type(run_module, admin_user):
@pytest.mark.django_db @pytest.mark.django_db
def test_setting_bool_value(run_module, admin_user): def test_setting_bool_value(run_module, admin_user):
for the_value in (True, False): for the_value in (True, False):
result = run_module('tower_settings', dict(name='ACTIVITY_STREAM_ENABLED_FOR_INVENTORY_SYNC', value=the_value), admin_user) result = run_module('settings', dict(name='ACTIVITY_STREAM_ENABLED_FOR_INVENTORY_SYNC', value=the_value), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result assert result.get('changed'), result

View File

@@ -11,7 +11,7 @@ from awx.main.models import Organization, Team
def test_create_team(run_module, admin_user): def test_create_team(run_module, admin_user):
org = Organization.objects.create(name='foo') org = Organization.objects.create(name='foo')
result = run_module('tower_team', {'name': 'foo_team', 'description': 'fooin around', 'state': 'present', 'organization': 'foo'}, admin_user) result = run_module('team', {'name': 'foo_team', 'description': 'fooin around', 'state': 'present', 'organization': 'foo'}, admin_user)
team = Team.objects.filter(name='foo_team').first() team = Team.objects.filter(name='foo_team').first()
@@ -32,7 +32,7 @@ def test_modify_team(run_module, admin_user):
team = Team.objects.create(name='foo_team', organization=org, description='flat foo') team = Team.objects.create(name='foo_team', organization=org, description='flat foo')
assert team.description == 'flat foo' assert team.description == 'flat foo'
result = run_module('tower_team', {'name': 'foo_team', 'description': 'fooin around', 'organization': 'foo'}, admin_user) result = run_module('team', {'name': 'foo_team', 'description': 'fooin around', 'organization': 'foo'}, admin_user)
team.refresh_from_db() team.refresh_from_db()
result.pop('invocation') result.pop('invocation')
assert result == { assert result == {
@@ -42,6 +42,6 @@ def test_modify_team(run_module, admin_user):
assert team.description == 'fooin around' assert team.description == 'fooin around'
# 2nd modification, should cause no change # 2nd modification, should cause no change
result = run_module('tower_team', {'name': 'foo_team', 'description': 'fooin around', 'organization': 'foo'}, admin_user) result = run_module('team', {'name': 'foo_team', 'description': 'fooin around', 'organization': 'foo'}, admin_user)
result.pop('invocation') result.pop('invocation')
assert result == {"id": team.id, "changed": False} assert result == {"id": team.id, "changed": False}

View File

@@ -14,15 +14,15 @@ def test_create_token(run_module, admin_user):
'description': 'barfoo', 'description': 'barfoo',
'state': 'present', 'state': 'present',
'scope': 'read', 'scope': 'read',
'tower_host': None, 'controller_host': None,
'tower_username': None, 'controller_username': None,
'tower_password': None, 'controller_password': None,
'validate_certs': None, 'validate_certs': None,
'tower_oauthtoken': None, 'controller_oauthtoken': None,
'tower_config_file': None, 'controller_config_file': None,
} }
result = run_module('tower_token', module_args, admin_user) result = run_module('token', module_args, admin_user)
assert result.get('changed'), result assert result.get('changed'), result
tokens = OAuth2AccessToken.objects.filter(description='barfoo') tokens = OAuth2AccessToken.objects.filter(description='barfoo')

View File

@@ -20,7 +20,7 @@ def mock_auth_stuff():
@pytest.mark.django_db @pytest.mark.django_db
def test_create_user(run_module, admin_user, mock_auth_stuff): def test_create_user(run_module, admin_user, mock_auth_stuff):
result = run_module('tower_user', dict(username='Bob', password='pass4word'), admin_user) result = run_module('user', dict(username='Bob', password='pass4word'), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result assert result.get('changed'), result
@@ -31,7 +31,7 @@ def test_create_user(run_module, admin_user, mock_auth_stuff):
@pytest.mark.django_db @pytest.mark.django_db
def test_password_no_op_warning(run_module, admin_user, mock_auth_stuff, silence_warning): def test_password_no_op_warning(run_module, admin_user, mock_auth_stuff, silence_warning):
for i in range(2): for i in range(2):
result = run_module('tower_user', dict(username='Bob', password='pass4word'), admin_user) result = run_module('user', dict(username='Bob', password='pass4word'), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed') # not actually desired, but assert for sanity assert result.get('changed') # not actually desired, but assert for sanity
@@ -44,7 +44,7 @@ def test_password_no_op_warning(run_module, admin_user, mock_auth_stuff, silence
@pytest.mark.django_db @pytest.mark.django_db
def test_update_password_on_create(run_module, admin_user, mock_auth_stuff): def test_update_password_on_create(run_module, admin_user, mock_auth_stuff):
for i in range(2): for i in range(2):
result = run_module('tower_user', dict(username='Bob', password='pass4word', update_secrets=False), admin_user) result = run_module('user', dict(username='Bob', password='pass4word', update_secrets=False), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert not result.get('changed') assert not result.get('changed')
@@ -52,11 +52,11 @@ def test_update_password_on_create(run_module, admin_user, mock_auth_stuff):
@pytest.mark.django_db @pytest.mark.django_db
def test_update_user(run_module, admin_user, mock_auth_stuff): def test_update_user(run_module, admin_user, mock_auth_stuff):
result = run_module('tower_user', dict(username='Bob', password='pass4word', is_system_auditor=True), admin_user) result = run_module('user', dict(username='Bob', password='pass4word', is_system_auditor=True), admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed'), result assert result.get('changed'), result
update_result = run_module('tower_user', dict(username='Bob', is_system_auditor=False), admin_user) update_result = run_module('user', dict(username='Bob', is_system_auditor=False), admin_user)
assert update_result.get('changed') assert update_result.get('changed')
user = User.objects.get(id=result['id']) user = User.objects.get(id=result['id'])

View File

@@ -10,7 +10,7 @@ from awx.main.models import WorkflowJobTemplate, NotificationTemplate
@pytest.mark.django_db @pytest.mark.django_db
def test_create_workflow_job_template(run_module, admin_user, organization, survey_spec): def test_create_workflow_job_template(run_module, admin_user, organization, survey_spec):
result = run_module( result = run_module(
'tower_workflow_job_template', 'workflow_job_template',
{ {
'name': 'foo-workflow', 'name': 'foo-workflow',
'organization': organization.name, 'organization': organization.name,
@@ -35,7 +35,7 @@ def test_create_workflow_job_template(run_module, admin_user, organization, surv
@pytest.mark.django_db @pytest.mark.django_db
def test_create_modify_no_survey(run_module, admin_user, organization, survey_spec): def test_create_modify_no_survey(run_module, admin_user, organization, survey_spec):
result = run_module('tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name}, admin_user) result = run_module('workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', False), result assert result.get('changed', False), result
@@ -45,7 +45,7 @@ def test_create_modify_no_survey(run_module, admin_user, organization, survey_sp
result.pop('invocation', None) result.pop('invocation', None)
assert result == {"name": "foo-workflow", "id": wfjt.id, "changed": True} assert result == {"name": "foo-workflow", "id": wfjt.id, "changed": True}
result = run_module('tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name}, admin_user) result = run_module('workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert not result.get('changed', True), result assert not result.get('changed', True), result
@@ -53,7 +53,7 @@ def test_create_modify_no_survey(run_module, admin_user, organization, survey_sp
@pytest.mark.django_db @pytest.mark.django_db
def test_survey_spec_only_changed(run_module, admin_user, organization, survey_spec): def test_survey_spec_only_changed(run_module, admin_user, organization, survey_spec):
wfjt = WorkflowJobTemplate.objects.create(organization=organization, name='foo-workflow', survey_enabled=True, survey_spec=survey_spec) wfjt = WorkflowJobTemplate.objects.create(organization=organization, name='foo-workflow', survey_enabled=True, survey_spec=survey_spec)
result = run_module('tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'state': 'present'}, admin_user) result = run_module('workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'state': 'present'}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert not result.get('changed', True), result assert not result.get('changed', True), result
wfjt.refresh_from_db() wfjt.refresh_from_db()
@@ -62,7 +62,7 @@ def test_survey_spec_only_changed(run_module, admin_user, organization, survey_s
survey_spec['description'] = 'changed description' survey_spec['description'] = 'changed description'
result = run_module( result = run_module(
'tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'survey_spec': survey_spec, 'state': 'present'}, admin_user 'workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'survey_spec': survey_spec, 'state': 'present'}, admin_user
) )
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', True), result assert result.get('changed', True), result
@@ -73,7 +73,7 @@ def test_survey_spec_only_changed(run_module, admin_user, organization, survey_s
@pytest.mark.django_db @pytest.mark.django_db
def test_survey_spec_only_changed(run_module, admin_user, organization, survey_spec): def test_survey_spec_only_changed(run_module, admin_user, organization, survey_spec):
wfjt = WorkflowJobTemplate.objects.create(organization=organization, name='foo-workflow', survey_enabled=True, survey_spec=survey_spec) wfjt = WorkflowJobTemplate.objects.create(organization=organization, name='foo-workflow', survey_enabled=True, survey_spec=survey_spec)
result = run_module('tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'state': 'present'}, admin_user) result = run_module('workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'state': 'present'}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert not result.get('changed', True), result assert not result.get('changed', True), result
wfjt.refresh_from_db() wfjt.refresh_from_db()
@@ -82,7 +82,7 @@ def test_survey_spec_only_changed(run_module, admin_user, organization, survey_s
del survey_spec['description'] del survey_spec['description']
result = run_module( result = run_module(
'tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'survey_spec': survey_spec, 'state': 'present'}, admin_user 'workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'survey_spec': survey_spec, 'state': 'present'}, admin_user
) )
assert result.get('failed', True) assert result.get('failed', True)
assert result.get('msg') == "Failed to update survey: Field 'description' is missing from survey spec." assert result.get('msg') == "Failed to update survey: Field 'description' is missing from survey spec."
@@ -107,7 +107,7 @@ def test_associate_only_on_success(run_module, admin_user, organization, project
# test preservation of error NTs when success NTs are added # test preservation of error NTs when success NTs are added
result = run_module( result = run_module(
'tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'notification_templates_success': ['nt2']}, admin_user 'workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'notification_templates_success': ['nt2']}, admin_user
) )
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', True), result assert result.get('changed', True), result
@@ -116,9 +116,7 @@ def test_associate_only_on_success(run_module, admin_user, organization, project
assert list(wfjt.notification_templates_error.values_list('id', flat=True)) == [nt1.id] assert list(wfjt.notification_templates_error.values_list('id', flat=True)) == [nt1.id]
# test removal to empty list # test removal to empty list
result = run_module( result = run_module('workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'notification_templates_success': []}, admin_user)
'tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'notification_templates_success': []}, admin_user
)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', True), result assert result.get('changed', True), result
@@ -129,7 +127,7 @@ def test_associate_only_on_success(run_module, admin_user, organization, project
@pytest.mark.django_db @pytest.mark.django_db
def test_delete_with_spec(run_module, admin_user, organization, survey_spec): def test_delete_with_spec(run_module, admin_user, organization, survey_spec):
WorkflowJobTemplate.objects.create(organization=organization, name='foo-workflow', survey_enabled=True, survey_spec=survey_spec) WorkflowJobTemplate.objects.create(organization=organization, name='foo-workflow', survey_enabled=True, survey_spec=survey_spec)
result = run_module('tower_workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'state': 'absent'}, admin_user) result = run_module('workflow_job_template', {'name': 'foo-workflow', 'organization': organization.name, 'state': 'absent'}, admin_user)
assert not result.get('failed', False), result.get('msg', result) assert not result.get('failed', False), result.get('msg', result)
assert result.get('changed', True), result assert result.get('changed', True), result

View File

@@ -31,7 +31,7 @@ def wfjt(organization):
def test_create_workflow_job_template_node(run_module, admin_user, wfjt, job_template): def test_create_workflow_job_template_node(run_module, admin_user, wfjt, job_template):
this_identifier = '42🐉' this_identifier = '42🐉'
result = run_module( result = run_module(
'tower_workflow_job_template_node', 'workflow_job_template_node',
{ {
'identifier': this_identifier, 'identifier': this_identifier,
'workflow_job_template': 'foo-workflow', 'workflow_job_template': 'foo-workflow',
@@ -58,7 +58,7 @@ def test_create_workflow_job_template_node_approval_node(run_module, admin_user,
"""This is a part of the API contract for creating approval nodes""" """This is a part of the API contract for creating approval nodes"""
this_identifier = '42🐉' this_identifier = '42🐉'
result = run_module( result = run_module(
'tower_workflow_job_template_node', 'workflow_job_template_node',
{ {
'identifier': this_identifier, 'identifier': this_identifier,
'workflow_job_template': wfjt.name, 'workflow_job_template': wfjt.name,
@@ -83,7 +83,7 @@ def test_create_workflow_job_template_node_approval_node(run_module, admin_user,
@pytest.mark.django_db @pytest.mark.django_db
def test_make_use_of_prompts(run_module, admin_user, wfjt, job_template, machine_credential, vault_credential): def test_make_use_of_prompts(run_module, admin_user, wfjt, job_template, machine_credential, vault_credential):
result = run_module( result = run_module(
'tower_workflow_job_template_node', 'workflow_job_template_node',
{ {
'identifier': '42', 'identifier': '42',
'workflow_job_template': 'foo-workflow', 'workflow_job_template': 'foo-workflow',
@@ -113,7 +113,7 @@ def test_create_with_edges(run_module, admin_user, wfjt, job_template):
] ]
result = run_module( result = run_module(
'tower_workflow_job_template_node', 'workflow_job_template_node',
{ {
'identifier': '42', 'identifier': '42',
'workflow_job_template': 'foo-workflow', 'workflow_job_template': 'foo-workflow',

View File

@@ -1,102 +0,0 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
import pytest
from awx.main.models import WorkflowJobTemplate, JobTemplate, Project, InventorySource, Inventory, WorkflowJobTemplateNode
@pytest.mark.django_db
def test_create_workflow_job_template(run_module, admin_user, organization, survey_spec, silence_deprecation):
result = run_module(
'tower_workflow_template',
{
'name': 'foo-workflow',
'organization': organization.name,
'extra_vars': {'foo': 'bar', 'another-foo': {'barz': 'bar2'}},
'survey': survey_spec,
'survey_enabled': True,
'state': 'present',
},
admin_user,
)
wfjt = WorkflowJobTemplate.objects.get(name='foo-workflow')
assert wfjt.extra_vars == '{"foo": "bar", "another-foo": {"barz": "bar2"}}'
result.pop('invocation', None)
assert result == {"workflow_template": "foo-workflow", "state": "present", "id": wfjt.id, "changed": True} # TODO: remove after refactor
assert wfjt.organization_id == organization.id
assert wfjt.survey_spec == survey_spec
@pytest.mark.django_db
def test_with_nested_workflow(run_module, admin_user, organization, silence_deprecation):
wfjt1 = WorkflowJobTemplate.objects.create(name='first', organization=organization)
result = run_module(
'tower_workflow_template',
{'name': 'foo-workflow', 'organization': organization.name, 'schema': [{'workflow': wfjt1.name}], 'state': 'present'},
admin_user,
)
assert not result.get('failed', False), result.get('msg', result)
wfjt = WorkflowJobTemplate.objects.get(name='foo-workflow')
node = wfjt.workflow_nodes.first()
assert node is not None
assert node.unified_job_template == wfjt1
@pytest.mark.django_db
def test_schema_with_branches(run_module, admin_user, organization, silence_deprecation):
proj = Project.objects.create(organization=organization, name='Ansible Examples')
inv = Inventory.objects.create(organization=organization, name='test-inv')
jt = JobTemplate.objects.create(project=proj, playbook='helloworld.yml', inventory=inv, name='Hello world')
inv_src = InventorySource.objects.create(inventory=inv, name='AWS servers', source='ec2')
result = run_module(
'tower_workflow_template',
{
'name': 'foo-workflow',
'organization': organization.name,
'schema': [
{
'job_template': 'Hello world',
'failure': [{'inventory_source': 'AWS servers', 'success': [{'project': 'Ansible Examples', 'always': [{'job_template': "Hello world"}]}]}],
}
],
'state': 'present',
},
admin_user,
)
assert not result.get('failed', False), result.get('msg', result)
wfjt = WorkflowJobTemplate.objects.get(name='foo-workflow')
root_nodes = wfjt.workflow_nodes.filter(
**{
'%ss_success__isnull' % WorkflowJobTemplateNode.__name__.lower(): True,
'%ss_failure__isnull' % WorkflowJobTemplateNode.__name__.lower(): True,
'%ss_always__isnull' % WorkflowJobTemplateNode.__name__.lower(): True,
}
)
assert len(root_nodes) == 1
node = root_nodes[0]
assert node.unified_job_template == jt
second = node.failure_nodes.first()
assert second.unified_job_template == inv_src
third = second.success_nodes.first()
assert third.unified_job_template == proj
fourth = third.always_nodes.first()
assert fourth.unified_job_template == jt
@pytest.mark.django_db
def test_with_missing_ujt(run_module, admin_user, organization, silence_deprecation):
result = run_module(
'tower_workflow_template', {'name': 'foo-workflow', 'organization': organization.name, 'schema': [{'foo': 'bar'}], 'state': 'present'}, admin_user
)
assert result.get('failed', False), result
assert 'You should provide exactly one of the attributes job_template,' in result['msg']

View File

@@ -6,36 +6,36 @@
- name: Generate names - name: Generate names
set_fact: set_fact:
inv_name: "AWX-Collection-tests-tower_tower_ad_hoc_command-inventory-{{ test_id }}" inv_name: "AWX-Collection-tests-ad_hoc_command-inventory-{{ test_id }}"
ssh_cred_name: "AWX-Collection-tests-tower_tower_ad_hoc_command-ssh-cred-{{ test_id }}" ssh_cred_name: "AWX-Collection-tests-ad_hoc_command-ssh-cred-{{ test_id }}"
org_name: "AWX-Collection-tests-tower_tower_ad_hoc_command-org-{{ test_id }}" org_name: "AWX-Collection-tests-ad_hoc_command-org-{{ test_id }}"
- name: Create a New Organization - name: Create a New Organization
tower_organization: organization:
name: "{{ org_name }}" name: "{{ org_name }}"
- name: Create an Inventory - name: Create an Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
state: present state: present
- name: Add localhost to the Inventory - name: Add localhost to the Inventory
tower_host: host:
name: localhost name: localhost
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
variables: variables:
ansible_connection: local ansible_connection: local
- name: Create a Credential - name: Create a Credential
tower_credential: credential:
name: "{{ ssh_cred_name }}" name: "{{ ssh_cred_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
credential_type: 'Machine' credential_type: 'Machine'
state: present state: present
- name: Launch an Ad Hoc Command waiting for it to finish - name: Launch an Ad Hoc Command waiting for it to finish
tower_ad_hoc_command: ad_hoc_command:
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
credential: "{{ ssh_cred_name }}" credential: "{{ ssh_cred_name }}"
module_name: "command" module_name: "command"
@@ -49,7 +49,7 @@
- "result.status == 'successful'" - "result.status == 'successful'"
- name: Launch an Ad Hoc Command without module argument - name: Launch an Ad Hoc Command without module argument
tower_ad_hoc_command: ad_hoc_command:
inventory: "Demo Inventory" inventory: "Demo Inventory"
credential: "{{ ssh_cred_name }}" credential: "{{ ssh_cred_name }}"
module_name: "ping" module_name: "ping"
@@ -62,7 +62,7 @@
- "result.status == 'successful'" - "result.status == 'successful'"
- name: Check module fails with correct msg - name: Check module fails with correct msg
tower_ad_hoc_command: ad_hoc_command:
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
credential: "{{ ssh_cred_name }}" credential: "{{ ssh_cred_name }}"
module_name: "Does not exist" module_name: "Does not exist"
@@ -76,19 +76,19 @@
- "'Does not exist' in result.response['json']['module_name'][0]" - "'Does not exist' in result.response['json']['module_name'][0]"
- name: Delete the Credential - name: Delete the Credential
tower_credential: credential:
name: "{{ ssh_cred_name }}" name: "{{ ssh_cred_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
credential_type: 'Machine' credential_type: 'Machine'
state: absent state: absent
- name: Delete the Inventory - name: Delete the Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
state: absent state: absent
- name: Remove the Organization - name: Remove the Organization
tower_organization: organization:
name: "{{ org_name }}" name: "{{ org_name }}"
state: absent state: absent

View File

@@ -6,36 +6,36 @@
- name: Generate names - name: Generate names
set_fact: set_fact:
inv_name: "AWX-Collection-tests-tower_tower_ad_hoc_command_cancel-inventory-{{ test_id }}" inv_name: "AWX-Collection-tests-ad_hoc_command_cancel-inventory-{{ test_id }}"
ssh_cred_name: "AWX-Collection-tests-tower_tower_ad_hoc_command_cancel-ssh-cred-{{ test_id }}" ssh_cred_name: "AWX-Collection-tests-ad_hoc_command_cancel-ssh-cred-{{ test_id }}"
org_name: "AWX-Collection-tests-tower_tower_ad_hoc_command_cancel-org-{{ test_id }}" org_name: "AWX-Collection-tests-ad_hoc_command_cancel-org-{{ test_id }}"
- name: Create a New Organization - name: Create a New Organization
tower_organization: organization:
name: "{{ org_name }}" name: "{{ org_name }}"
- name: Create an Inventory - name: Create an Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
state: present state: present
- name: Add localhost to the Inventory - name: Add localhost to the Inventory
tower_host: host:
name: localhost name: localhost
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
variables: variables:
ansible_connection: local ansible_connection: local
- name: Create a Credential - name: Create a Credential
tower_credential: credential:
name: "{{ ssh_cred_name }}" name: "{{ ssh_cred_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
credential_type: 'Machine' credential_type: 'Machine'
state: present state: present
- name: Launch an Ad Hoc Command - name: Launch an Ad Hoc Command
tower_ad_hoc_command: ad_hoc_command:
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
credential: "{{ ssh_cred_name }}" credential: "{{ ssh_cred_name }}"
module_name: "command" module_name: "command"
@@ -47,7 +47,7 @@
- "command is changed" - "command is changed"
- name: Timeout waiting for the command to cancel - name: Timeout waiting for the command to cancel
tower_ad_hoc_command_cancel: ad_hoc_command_cancel:
command_id: "{{ command.id }}" command_id: "{{ command.id }}"
timeout: -1 timeout: -1
register: results register: results
@@ -59,7 +59,7 @@
- "results['msg'] == 'Monitoring of ad hoc command aborted due to timeout'" - "results['msg'] == 'Monitoring of ad hoc command aborted due to timeout'"
- name: Cancel the command with hard error if it's not running - name: Cancel the command with hard error if it's not running
tower_ad_hoc_command_cancel: ad_hoc_command_cancel:
command_id: "{{ command.id }}" command_id: "{{ command.id }}"
fail_if_not_running: true fail_if_not_running: true
register: results register: results
@@ -70,7 +70,7 @@
- results is failed - results is failed
- name: Cancel an already canceled command (assert failure) - name: Cancel an already canceled command (assert failure)
tower_ad_hoc_command_cancel: ad_hoc_command_cancel:
command_id: "{{ command.id }}" command_id: "{{ command.id }}"
fail_if_not_running: true fail_if_not_running: true
register: results register: results
@@ -81,7 +81,7 @@
- results is failed - results is failed
- name: Check module fails with correct msg - name: Check module fails with correct msg
tower_ad_hoc_command_cancel: ad_hoc_command_cancel:
command_id: 9999999999 command_id: 9999999999
register: result register: result
ignore_errors: true ignore_errors: true
@@ -91,19 +91,19 @@
- "result.msg == 'Unable to find command with id 9999999999'" - "result.msg == 'Unable to find command with id 9999999999'"
- name: Delete the Credential - name: Delete the Credential
tower_credential: credential:
name: "{{ ssh_cred_name }}" name: "{{ ssh_cred_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
credential_type: 'Machine' credential_type: 'Machine'
state: absent state: absent
- name: Delete the Inventory - name: Delete the Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
state: absent state: absent
- name: Remove the Organization - name: Remove the Organization
tower_organization: organization:
name: "{{ org_name }}" name: "{{ org_name }}"
state: absent state: absent

View File

@@ -6,36 +6,36 @@
- name: Generate names - name: Generate names
set_fact: set_fact:
inv_name: "AWX-Collection-tests-tower_ad_hoc_command_wait-inventory-{{ test_id }}" inv_name: "AWX-Collection-tests-ad_hoc_command_wait-inventory-{{ test_id }}"
ssh_cred_name: "AWX-Collection-tests-tower_ad_hoc_command_wait-ssh-cred-{{ test_id }}" ssh_cred_name: "AWX-Collection-tests-ad_hoc_command_wait-ssh-cred-{{ test_id }}"
org_name: "AWX-Collection-tests-tower_ad_hoc_command_wait-org-{{ test_id }}" org_name: "AWX-Collection-tests-ad_hoc_command_wait-org-{{ test_id }}"
- name: Create a New Organization - name: Create a New Organization
tower_organization: organization:
name: "{{ org_name }}" name: "{{ org_name }}"
- name: Create an Inventory - name: Create an Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
state: present state: present
- name: Add localhost to the Inventory - name: Add localhost to the Inventory
tower_host: host:
name: localhost name: localhost
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
variables: variables:
ansible_connection: local ansible_connection: local
- name: Create a Credential - name: Create a Credential
tower_credential: credential:
name: "{{ ssh_cred_name }}" name: "{{ ssh_cred_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
credential_type: 'Machine' credential_type: 'Machine'
state: present state: present
- name: Check module fails with correct msg - name: Check module fails with correct msg
tower_ad_hoc_command_wait: ad_hoc_command_wait:
command_id: "99999999" command_id: "99999999"
register: result register: result
ignore_errors: true ignore_errors: true
@@ -43,10 +43,10 @@
- assert: - assert:
that: that:
- result is failed - result is failed
- "result.msg == 'Unable to wait on ad hoc command 99999999; that ID does not exist in Tower.'" - "result.msg == 'Unable to wait on ad hoc command 99999999; that ID does not exist.'"
- name: Launch command module with sleep 10 - name: Launch command module with sleep 10
tower_ad_hoc_command: ad_hoc_command:
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
credential: "{{ ssh_cred_name }}" credential: "{{ ssh_cred_name }}"
module_name: "command" module_name: "command"
@@ -58,7 +58,7 @@
- command is changed - command is changed
- name: Wait for the Job to finish - name: Wait for the Job to finish
tower_ad_hoc_command_wait: ad_hoc_command_wait:
command_id: "{{ command.id }}" command_id: "{{ command.id }}"
register: wait_results register: wait_results
@@ -70,7 +70,7 @@
- "'id' in wait_results" - "'id' in wait_results"
- name: Launch a long running command - name: Launch a long running command
tower_ad_hoc_command: ad_hoc_command:
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
credential: "{{ ssh_cred_name }}" credential: "{{ ssh_cred_name }}"
module_name: "command" module_name: "command"
@@ -82,7 +82,7 @@
- command is changed - command is changed
- name: Timeout waiting for the command to complete - name: Timeout waiting for the command to complete
tower_ad_hoc_command_wait: ad_hoc_command_wait:
command_id: "{{ command.id }}" command_id: "{{ command.id }}"
timeout: 1 timeout: 1
ignore_errors: true ignore_errors: true
@@ -95,13 +95,13 @@
- "'id' in wait_results" - "'id' in wait_results"
- name: Async cancel the long-running command - name: Async cancel the long-running command
tower_ad_hoc_command_cancel: ad_hoc_command_cancel:
command_id: "{{ command.id }}" command_id: "{{ command.id }}"
async: 3600 async: 3600
poll: 0 poll: 0
- name: Wait for the command to exit on cancel - name: Wait for the command to exit on cancel
tower_ad_hoc_command_wait: ad_hoc_command_wait:
command_id: "{{ command.id }}" command_id: "{{ command.id }}"
register: wait_results register: wait_results
ignore_errors: true ignore_errors: true
@@ -113,19 +113,19 @@
- "wait_results.msg == 'The ad hoc command - {{ command.id }}, failed'" - "wait_results.msg == 'The ad hoc command - {{ command.id }}, failed'"
- name: Delete the Credential - name: Delete the Credential
tower_credential: credential:
name: "{{ ssh_cred_name }}" name: "{{ ssh_cred_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
credential_type: 'Machine' credential_type: 'Machine'
state: absent state: absent
- name: Delete the Inventory - name: Delete the Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: "{{ org_name }}" organization: "{{ org_name }}"
state: absent state: absent
- name: Remove the Organization - name: Remove the Organization
tower_organization: organization:
name: "{{ org_name }}" name: "{{ org_name }}"
state: absent state: absent

View File

@@ -5,13 +5,13 @@
- name: Generate names - name: Generate names
set_fact: set_fact:
app1_name: "AWX-Collection-tests-tower_application-app1-{{ test_id }}" app1_name: "AWX-Collection-tests-application-app1-{{ test_id }}"
app2_name: "AWX-Collection-tests-tower_application-app2-{{ test_id }}" app2_name: "AWX-Collection-tests-application-app2-{{ test_id }}"
app3_name: "AWX-Collection-tests-tower_application-app3-{{ test_id }}" app3_name: "AWX-Collection-tests-application-app3-{{ test_id }}"
- block: - block:
- name: Create an application - name: Create an application
tower_application: application:
name: "{{ app1_name }}" name: "{{ app1_name }}"
authorization_grant_type: "password" authorization_grant_type: "password"
client_type: "public" client_type: "public"
@@ -24,7 +24,7 @@
- "result is changed" - "result is changed"
- name: Delete our application - name: Delete our application
tower_application: application:
name: "{{ app1_name }}" name: "{{ app1_name }}"
organization: "Default" organization: "Default"
state: absent state: absent
@@ -35,7 +35,7 @@
- "result is changed" - "result is changed"
- name: Create a second application - name: Create a second application
tower_application: application:
name: "{{ app2_name }}" name: "{{ app2_name }}"
authorization_grant_type: "authorization-code" authorization_grant_type: "authorization-code"
client_type: "confidential" client_type: "confidential"
@@ -52,7 +52,7 @@
- "result is changed" - "result is changed"
- name: Create an all trusting application - name: Create an all trusting application
tower_application: application:
name: "{{ app3_name }}" name: "{{ app3_name }}"
organization: "Default" organization: "Default"
description: "All Trusting Application" description: "All Trusting Application"
@@ -68,7 +68,7 @@
always: always:
- name: Delete our application - name: Delete our application
tower_application: application:
name: "{{ item }}" name: "{{ item }}"
organization: "Default" organization: "Default"
state: absent state: absent

View File

@@ -6,23 +6,23 @@
- name: Generate names - name: Generate names
set_fact: set_fact:
ssh_cred_name1: "AWX-Collection-tests-tower_credential-ssh-cred1-{{ test_id }}" ssh_cred_name1: "AWX-Collection-tests-credential-ssh-cred1-{{ test_id }}"
ssh_cred_name2: "AWX-Collection-tests-tower_credential-ssh-cred2-{{ test_id }}" ssh_cred_name2: "AWX-Collection-tests-credential-ssh-cred2-{{ test_id }}"
ssh_cred_name3: "AWX-Collection-tests-tower_credential-ssh-cred-lookup-source-{{ test_id }}" ssh_cred_name3: "AWX-Collection-tests-credential-ssh-cred-lookup-source-{{ test_id }}"
ssh_cred_name4: "AWX-Collection-tests-tower_credential-ssh-cred-file-source-{{ test_id }}" ssh_cred_name4: "AWX-Collection-tests-credential-ssh-cred-file-source-{{ test_id }}"
vault_cred_name1: "AWX-Collection-tests-tower_credential-vault-cred1-{{ test_id }}" vault_cred_name1: "AWX-Collection-tests-credential-vault-cred1-{{ test_id }}"
vault_cred_name2: "AWX-Collection-tests-tower_credential-vault-ssh-cred1-{{ test_id }}" vault_cred_name2: "AWX-Collection-tests-credential-vault-ssh-cred1-{{ test_id }}"
net_cred_name1: "AWX-Collection-tests-tower_credential-net-cred1-{{ test_id }}" net_cred_name1: "AWX-Collection-tests-credential-net-cred1-{{ test_id }}"
scm_cred_name1: "AWX-Collection-tests-tower_credential-scm-cred1-{{ test_id }}" scm_cred_name1: "AWX-Collection-tests-credential-scm-cred1-{{ test_id }}"
aws_cred_name1: "AWX-Collection-tests-tower_credential-aws-cred1-{{ test_id }}" aws_cred_name1: "AWX-Collection-tests-credential-aws-cred1-{{ test_id }}"
vmware_cred_name1: "AWX-Collection-tests-tower_credential-vmware-cred1-{{ test_id }}" vmware_cred_name1: "AWX-Collection-tests-credential-vmware-cred1-{{ test_id }}"
sat6_cred_name1: "AWX-Collection-tests-tower_credential-sat6-cred1-{{ test_id }}" sat6_cred_name1: "AWX-Collection-tests-credential-sat6-cred1-{{ test_id }}"
gce_cred_name1: "AWX-Collection-tests-tower_credential-gce-cred1-{{ test_id }}" gce_cred_name1: "AWX-Collection-tests-credential-gce-cred1-{{ test_id }}"
azurerm_cred_name1: "AWX-Collection-tests-tower_credential-azurerm-cred1-{{ test_id }}" azurerm_cred_name1: "AWX-Collection-tests-credential-azurerm-cred1-{{ test_id }}"
openstack_cred_name1: "AWX-Collection-tests-tower_credential-openstack-cred1-{{ test_id }}" openstack_cred_name1: "AWX-Collection-tests-credential-openstack-cred1-{{ test_id }}"
rhv_cred_name1: "AWX-Collection-tests-tower_credential-rhv-cred1-{{ test_id }}" rhv_cred_name1: "AWX-Collection-tests-credential-rhv-cred1-{{ test_id }}"
insights_cred_name1: "AWX-Collection-tests-tower_credential-insights-cred1-{{ test_id }}" insights_cred_name1: "AWX-Collection-tests-credential-insights-cred1-{{ test_id }}"
tower_cred_name1: "AWX-Collection-tests-tower_credential-tower-cred1-{{ test_id }}" tower_cred_name1: "AWX-Collection-tests-credential-tower-cred1-{{ test_id }}"
- name: create a tempdir for an SSH key - name: create a tempdir for an SSH key
local_action: shell mktemp -d local_action: shell mktemp -d
@@ -36,7 +36,7 @@
ssh_key_data: "{{ lookup('file', tempdir.stdout + '/id_rsa') }}" ssh_key_data: "{{ lookup('file', tempdir.stdout + '/id_rsa') }}"
- name: Test deprecation warnings - name: Test deprecation warnings
tower_credential: credential:
name: "{{ ssh_cred_name1 }}" name: "{{ ssh_cred_name1 }}"
organization: Default organization: Default
kind: ssh kind: ssh
@@ -70,7 +70,7 @@
- result['deprecations'] | length() == 20 - result['deprecations'] | length() == 20
- name: Create an Org-specific credential (old school) - name: Create an Org-specific credential (old school)
tower_credential: credential:
name: "{{ ssh_cred_name1 }}" name: "{{ ssh_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -82,7 +82,7 @@
- "result is changed" - "result is changed"
- name: Re-create the Org-specific credential (new school) with an ID - name: Re-create the Org-specific credential (new school) with an ID
tower_credential: credential:
name: "{{ result.id }}" name: "{{ result.id }}"
organization: Default organization: Default
credential_type: 'Machine' credential_type: 'Machine'
@@ -94,7 +94,7 @@
- "result is not changed" - "result is not changed"
- name: Delete a Org-specific credential - name: Delete a Org-specific credential
tower_credential: credential:
name: "{{ ssh_cred_name1 }}" name: "{{ ssh_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -106,7 +106,7 @@
- "result is changed" - "result is changed"
- name: Create the User-specific credential - name: Create the User-specific credential
tower_credential: credential:
name: "{{ ssh_cred_name1 }}" name: "{{ ssh_cred_name1 }}"
user: admin user: admin
credential_type: 'Machine' credential_type: 'Machine'
@@ -118,7 +118,7 @@
- "result is changed" - "result is changed"
- name: Delete a User-specific credential - name: Delete a User-specific credential
tower_credential: credential:
name: "{{ ssh_cred_name1 }}" name: "{{ ssh_cred_name1 }}"
user: admin user: admin
state: absent state: absent
@@ -130,7 +130,7 @@
- "result is changed" - "result is changed"
- name: Create a valid SSH credential (old school) - name: Create a valid SSH credential (old school)
tower_credential: credential:
name: "{{ ssh_cred_name2 }}" name: "{{ ssh_cred_name2 }}"
organization: Default organization: Default
state: present state: present
@@ -150,7 +150,7 @@
- "result is changed" - "result is changed"
- name: Create a valid SSH credential (new school) - name: Create a valid SSH credential (new school)
tower_credential: credential:
name: "{{ ssh_cred_name2 }}" name: "{{ ssh_cred_name2 }}"
organization: Default organization: Default
state: present state: present
@@ -173,7 +173,7 @@
- result is changed - result is changed
- name: Create a valid SSH credential (new school) - name: Create a valid SSH credential (new school)
tower_credential: credential:
name: "{{ ssh_cred_name2 }}" name: "{{ ssh_cred_name2 }}"
organization: Default organization: Default
state: present state: present
@@ -191,7 +191,7 @@
- result is changed - result is changed
- name: Check for inputs idempotency (when "inputs" is blank) - name: Check for inputs idempotency (when "inputs" is blank)
tower_credential: credential:
name: "{{ ssh_cred_name2 }}" name: "{{ ssh_cred_name2 }}"
organization: Default organization: Default
state: present state: present
@@ -204,7 +204,7 @@
- result is not changed - result is not changed
- name: Copy ssh Credential - name: Copy ssh Credential
tower_credential: credential:
name: "copy_{{ ssh_cred_name2 }}" name: "copy_{{ ssh_cred_name2 }}"
copy_from: "{{ ssh_cred_name2 }}" copy_from: "{{ ssh_cred_name2 }}"
credential_type: Machine credential_type: Machine
@@ -215,7 +215,7 @@
- result.copied - result.copied
- name: Delete an SSH credential - name: Delete an SSH credential
tower_credential: credential:
name: "copy_{{ ssh_cred_name2 }}" name: "copy_{{ ssh_cred_name2 }}"
organization: Default organization: Default
state: absent state: absent
@@ -227,7 +227,7 @@
- "result is changed" - "result is changed"
- name: Create a valid SSH credential from lookup source (old school) - name: Create a valid SSH credential from lookup source (old school)
tower_credential: credential:
name: "{{ ssh_cred_name3 }}" name: "{{ ssh_cred_name3 }}"
organization: Default organization: Default
state: present state: present
@@ -247,7 +247,7 @@
- "result is changed" - "result is changed"
- name: Create a valid SSH credential from lookup source (new school) - name: Create a valid SSH credential from lookup source (new school)
tower_credential: credential:
name: "{{ ssh_cred_name3 }}" name: "{{ ssh_cred_name3 }}"
organization: Default organization: Default
state: present state: present
@@ -269,7 +269,7 @@
- result is changed - result is changed
- name: Fail to create an SSH credential from a file source (old school format) - name: Fail to create an SSH credential from a file source (old school format)
tower_credential: credential:
name: "{{ ssh_cred_name4 }}" name: "{{ ssh_cred_name4 }}"
organization: Default organization: Default
state: present state: present
@@ -292,7 +292,7 @@
- "'Invalid certificate or key' in result.msg" - "'Invalid certificate or key' in result.msg"
- name: Create an invalid SSH credential (passphrase required) - name: Create an invalid SSH credential (passphrase required)
tower_credential: credential:
name: SSH Credential name: SSH Credential
organization: Default organization: Default
state: present state: present
@@ -308,7 +308,7 @@
- "'must be set when SSH key is encrypted' in result.msg" - "'must be set when SSH key is encrypted' in result.msg"
- name: Create an invalid SSH credential (Organization not found) - name: Create an invalid SSH credential (Organization not found)
tower_credential: credential:
name: SSH Credential name: SSH Credential
organization: Missing_Organization organization: Missing_Organization
state: present state: present
@@ -325,7 +325,7 @@
- "result.total_results == 0" - "result.total_results == 0"
- name: Delete an SSH credential - name: Delete an SSH credential
tower_credential: credential:
name: "{{ ssh_cred_name2 }}" name: "{{ ssh_cred_name2 }}"
organization: Default organization: Default
state: absent state: absent
@@ -337,7 +337,7 @@
- "result is changed" - "result is changed"
- name: Delete an SSH credential - name: Delete an SSH credential
tower_credential: credential:
name: "{{ ssh_cred_name3 }}" name: "{{ ssh_cred_name3 }}"
organization: Default organization: Default
state: absent state: absent
@@ -349,7 +349,7 @@
- "result is changed" - "result is changed"
- name: Delete an SSH credential - name: Delete an SSH credential
tower_credential: credential:
name: "{{ ssh_cred_name4 }}" name: "{{ ssh_cred_name4 }}"
organization: Default organization: Default
state: absent state: absent
@@ -362,7 +362,7 @@
- "result is not changed" - "result is not changed"
- name: Create a valid Vault credential - name: Create a valid Vault credential
tower_credential: credential:
name: "{{ vault_cred_name1 }}" name: "{{ vault_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -376,7 +376,7 @@
- "result is changed" - "result is changed"
- name: Delete a Vault credential - name: Delete a Vault credential
tower_credential: credential:
name: "{{ vault_cred_name1 }}" name: "{{ vault_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -388,7 +388,7 @@
- "result is changed" - "result is changed"
- name: Delete a Vault credential - name: Delete a Vault credential
tower_credential: credential:
name: "{{ vault_cred_name2 }}" name: "{{ vault_cred_name2 }}"
organization: Default organization: Default
state: absent state: absent
@@ -401,7 +401,7 @@
- "result is not changed" - "result is not changed"
- name: Create a valid Network credential - name: Create a valid Network credential
tower_credential: credential:
name: "{{ net_cred_name1 }}" name: "{{ net_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -417,7 +417,7 @@
- "result is changed" - "result is changed"
- name: Delete a Network credential - name: Delete a Network credential
tower_credential: credential:
name: "{{ net_cred_name1 }}" name: "{{ net_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -429,7 +429,7 @@
- "result is changed" - "result is changed"
- name: Create a valid SCM credential - name: Create a valid SCM credential
tower_credential: credential:
name: "{{ scm_cred_name1 }}" name: "{{ scm_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -445,7 +445,7 @@
- "result is changed" - "result is changed"
- name: Delete an SCM credential - name: Delete an SCM credential
tower_credential: credential:
name: "{{ scm_cred_name1 }}" name: "{{ scm_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -457,7 +457,7 @@
- "result is changed" - "result is changed"
- name: Create a valid AWS credential - name: Create a valid AWS credential
tower_credential: credential:
name: "{{ aws_cred_name1 }}" name: "{{ aws_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -472,7 +472,7 @@
- "result is changed" - "result is changed"
- name: Delete an AWS credential - name: Delete an AWS credential
tower_credential: credential:
name: "{{ aws_cred_name1 }}" name: "{{ aws_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -484,7 +484,7 @@
- "result is changed" - "result is changed"
- name: Create a valid VMWare credential - name: Create a valid VMWare credential
tower_credential: credential:
name: "{{ vmware_cred_name1 }}" name: "{{ vmware_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -499,7 +499,7 @@
- "result is changed" - "result is changed"
- name: Delete an VMWare credential - name: Delete an VMWare credential
tower_credential: credential:
name: "{{ vmware_cred_name1 }}" name: "{{ vmware_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -511,7 +511,7 @@
- "result is changed" - "result is changed"
- name: Create a valid Satellite6 credential - name: Create a valid Satellite6 credential
tower_credential: credential:
name: "{{ sat6_cred_name1 }}" name: "{{ sat6_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -526,7 +526,7 @@
- "result is changed" - "result is changed"
- name: Delete a Satellite6 credential - name: Delete a Satellite6 credential
tower_credential: credential:
name: "{{ sat6_cred_name1 }}" name: "{{ sat6_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -538,7 +538,7 @@
- "result is changed" - "result is changed"
- name: Create a valid GCE credential - name: Create a valid GCE credential
tower_credential: credential:
name: "{{ gce_cred_name1 }}" name: "{{ gce_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -553,7 +553,7 @@
- "result is changed" - "result is changed"
- name: Delete a GCE credential - name: Delete a GCE credential
tower_credential: credential:
name: "{{ gce_cred_name1 }}" name: "{{ gce_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -565,7 +565,7 @@
- "result is changed" - "result is changed"
- name: Create a valid AzureRM credential - name: Create a valid AzureRM credential
tower_credential: credential:
name: "{{ azurerm_cred_name1 }}" name: "{{ azurerm_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -580,7 +580,7 @@
- "result is changed" - "result is changed"
- name: Create a valid AzureRM credential with a tenant - name: Create a valid AzureRM credential with a tenant
tower_credential: credential:
name: "{{ azurerm_cred_name1 }}" name: "{{ azurerm_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -596,7 +596,7 @@
- "result is changed" - "result is changed"
- name: Delete an AzureRM credential - name: Delete an AzureRM credential
tower_credential: credential:
name: "{{ azurerm_cred_name1 }}" name: "{{ azurerm_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -608,7 +608,7 @@
- "result is changed" - "result is changed"
- name: Create a valid OpenStack credential - name: Create a valid OpenStack credential
tower_credential: credential:
name: "{{ openstack_cred_name1 }}" name: "{{ openstack_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -625,7 +625,7 @@
- "result is changed" - "result is changed"
- name: Delete a OpenStack credential - name: Delete a OpenStack credential
tower_credential: credential:
name: "{{ openstack_cred_name1 }}" name: "{{ openstack_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -637,7 +637,7 @@
- "result is changed" - "result is changed"
- name: Create a valid RHV credential - name: Create a valid RHV credential
tower_credential: credential:
name: "{{ rhv_cred_name1 }}" name: "{{ rhv_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -652,7 +652,7 @@
- "result is changed" - "result is changed"
- name: Delete an RHV credential - name: Delete an RHV credential
tower_credential: credential:
name: "{{ rhv_cred_name1 }}" name: "{{ rhv_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -664,7 +664,7 @@
- "result is changed" - "result is changed"
- name: Create a valid Insights credential - name: Create a valid Insights credential
tower_credential: credential:
name: "{{ insights_cred_name1 }}" name: "{{ insights_cred_name1 }}"
organization: Default organization: Default
state: present state: present
@@ -678,7 +678,7 @@
- "result is changed" - "result is changed"
- name: Delete an Insights credential - name: Delete an Insights credential
tower_credential: credential:
name: "{{ insights_cred_name1 }}" name: "{{ insights_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -690,12 +690,12 @@
- "result is changed" - "result is changed"
- name: Create a valid Tower-to-Tower credential - name: Create a valid Tower-to-Tower credential
tower_credential: credential:
name: "{{ tower_cred_name1 }}" name: "{{ tower_cred_name1 }}"
organization: Default organization: Default
state: present state: present
kind: tower kind: tower
host: https://tower.example.org host: https://controller.example.org
username: joe username: joe
password: secret password: secret
register: result register: result
@@ -705,7 +705,7 @@
- "result is changed" - "result is changed"
- name: Delete a Tower-to-Tower credential - name: Delete a Tower-to-Tower credential
tower_credential: credential:
name: "{{ tower_cred_name1 }}" name: "{{ tower_cred_name1 }}"
organization: Default organization: Default
state: absent state: absent
@@ -717,7 +717,7 @@
- "result is changed" - "result is changed"
- name: Check module fails with correct msg - name: Check module fails with correct msg
tower_credential: credential:
name: test-credential name: test-credential
description: Credential Description description: Credential Description
kind: ssh kind: ssh

View File

@@ -6,12 +6,12 @@
- name: Generate names - name: Generate names
set_fact: set_fact:
src_cred_name: "AWX-Collection-tests-tower_credential_input_source-src_cred-{{ test_id }}" src_cred_name: "AWX-Collection-tests-credential_input_source-src_cred-{{ test_id }}"
target_cred_name: "AWX-Collection-tests-tower_credential_input_source-target_cred-{{ test_id }}" target_cred_name: "AWX-Collection-tests-credential_input_source-target_cred-{{ test_id }}"
- block: - block:
- name: Add Tower credential Lookup - name: Add credential Lookup
tower_credential: credential:
description: Credential for Testing Source description: Credential for Testing Source
name: "{{ src_cred_name }}" name: "{{ src_cred_name }}"
credential_type: CyberArk AIM Central Credential Provider Lookup credential_type: CyberArk AIM Central Credential Provider Lookup
@@ -25,8 +25,8 @@
that: that:
- "src_cred_result is changed" - "src_cred_result is changed"
- name: Add Tower credential Target - name: Add credential Target
tower_credential: credential:
description: Credential for Testing Target description: Credential for Testing Target
name: "{{ target_cred_name }}" name: "{{ target_cred_name }}"
credential_type: Machine credential_type: Machine
@@ -40,7 +40,7 @@
- "target_cred_result is changed" - "target_cred_result is changed"
- name: Add credential Input Source - name: Add credential Input Source
tower_credential_input_source: credential_input_source:
input_field_name: password input_field_name: password
target_credential: "{{ target_cred_result.id }}" target_credential: "{{ target_cred_result.id }}"
source_credential: "{{ src_cred_result.id }}" source_credential: "{{ src_cred_result.id }}"
@@ -54,8 +54,8 @@
that: that:
- "result is changed" - "result is changed"
- name: Add Second Tower credential Lookup - name: Add Second credential Lookup
tower_credential: credential:
description: Credential for Testing Source Change description: Credential for Testing Source Change
name: "{{ src_cred_name }}-2" name: "{{ src_cred_name }}-2"
credential_type: CyberArk AIM Central Credential Provider Lookup credential_type: CyberArk AIM Central Credential Provider Lookup
@@ -66,7 +66,7 @@
register: result register: result
- name: Change credential Input Source - name: Change credential Input Source
tower_credential_input_source: credential_input_source:
input_field_name: password input_field_name: password
target_credential: "{{ target_cred_name }}" target_credential: "{{ target_cred_name }}"
source_credential: "{{ src_cred_name }}-2" source_credential: "{{ src_cred_name }}-2"
@@ -77,8 +77,8 @@
- "result is changed" - "result is changed"
always: always:
- name: Remove a Tower credential source - name: Remove a credential source
tower_credential_input_source: credential_input_source:
input_field_name: password input_field_name: password
target_credential: "{{ target_cred_name }}" target_credential: "{{ target_cred_name }}"
state: absent state: absent
@@ -88,24 +88,24 @@
that: that:
- "result is changed" - "result is changed"
- name: Remove Tower credential Lookup - name: Remove credential Lookup
tower_credential: credential:
name: "{{ src_cred_name }}" name: "{{ src_cred_name }}"
organization: Default organization: Default
credential_type: CyberArk AIM Central Credential Provider Lookup credential_type: CyberArk AIM Central Credential Provider Lookup
state: absent state: absent
register: result register: result
- name: Remove Alt Tower credential Lookup - name: Remove Alt credential Lookup
tower_credential: credential:
name: "{{ src_cred_name }}-2" name: "{{ src_cred_name }}-2"
organization: Default organization: Default
credential_type: CyberArk AIM Central Credential Provider Lookup credential_type: CyberArk AIM Central Credential Provider Lookup
state: absent state: absent
register: result register: result
- name: Remove Tower credential - name: Remove credential
tower_credential: credential:
name: "{{ target_cred_name }}" name: "{{ target_cred_name }}"
organization: Default organization: Default
credential_type: Machine credential_type: Machine

View File

@@ -1,10 +1,10 @@
--- ---
- name: Generate names - name: Generate names
set_fact: set_fact:
cred_type_name: "AWX-Collection-tests-tower_credential_type-cred-type-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" cred_type_name: "AWX-Collection-tests-credential_type-cred-type-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
- name: Add Tower credential type - name: Add Tower credential type
tower_credential_type: credential_type:
description: Credential type for Test description: Credential type for Test
name: "{{ cred_type_name }}" name: "{{ cred_type_name }}"
kind: cloud kind: cloud
@@ -17,7 +17,7 @@
- "result is changed" - "result is changed"
- name: Remove a Tower credential type - name: Remove a Tower credential type
tower_credential_type: credential_type:
name: "{{ result.id }}" name: "{{ result.id }}"
state: absent state: absent
register: result register: result

View File

@@ -1,22 +1,22 @@
--- ---
- name: Assure that default organization exists - name: Assure that default organization exists
tower_organization: organization:
name: Default name: Default
- name: HACK - delete orphaned projects from preload data where organization deletd - name: HACK - delete orphaned projects from preload data where organization deletd
tower_project: project:
name: "{{ item['id'] }}" name: "{{ item['id'] }}"
scm_type: git scm_type: git
state: absent state: absent
loop: > loop: >
{{ query('awx.awx.tower_api', 'projects', {{ query('awx.awx.controller_api', 'projects',
query_params={'organization__isnull': true, 'name': 'Demo Project'}) query_params={'organization__isnull': true, 'name': 'Demo Project'})
}} }}
loop_control: loop_control:
label: "Deleting Demo Project with null organization id={{ item['id'] }}" label: "Deleting Demo Project with null organization id={{ item['id'] }}"
- name: Assure that demo project exists - name: Assure that demo project exists
tower_project: project:
name: "Demo Project" name: "Demo Project"
scm_type: 'git' scm_type: 'git'
scm_url: 'https://github.com/ansible/ansible-tower-samples' scm_url: 'https://github.com/ansible/ansible-tower-samples'
@@ -24,12 +24,12 @@
organization: Default organization: Default
- name: Assure that demo inventory exists - name: Assure that demo inventory exists
tower_inventory: inventory:
name: "Demo Inventory" name: "Demo Inventory"
organization: Default organization: Default
- name: Create a Host - name: Create a Host
tower_host: host:
name: "localhost" name: "localhost"
inventory: "Demo Inventory" inventory: "Demo Inventory"
state: present state: present
@@ -38,7 +38,7 @@
register: result register: result
- name: Assure that demo job template exists - name: Assure that demo job template exists
tower_job_template: job_template:
name: "Demo Job Template" name: "Demo Job Template"
project: "Demo Project" project: "Demo Project"
inventory: "Demo Inventory" inventory: "Demo Inventory"

View File

@@ -6,25 +6,25 @@
- name: Generate names - name: Generate names
set_fact: set_fact:
org_name1: "AWX-Collection-tests-tower_export-organization-{{ test_id }}" org_name1: "AWX-Collection-tests-export-organization-{{ test_id }}"
org_name2: "AWX-Collection-tests-tower_export-organization2-{{ test_id }}" org_name2: "AWX-Collection-tests-export-organization2-{{ test_id }}"
inventory_name1: "AWX-Collection-tests-tower_export-inv1-{{ test_id }}" inventory_name1: "AWX-Collection-tests-export-inv1-{{ test_id }}"
- block: - block:
- name: Create some organizations - name: Create some organizations
tower_organization: organization:
name: "{{ item }}" name: "{{ item }}"
loop: loop:
- "{{ org_name1 }}" - "{{ org_name1 }}"
- "{{ org_name2 }}" - "{{ org_name2 }}"
- name: Create an inventory - name: Create an inventory
tower_inventory: inventory:
name: "{{ inventory_name1 }}" name: "{{ inventory_name1 }}"
organization: "{{ org_name1 }}" organization: "{{ org_name1 }}"
- name: Export all tower assets - name: Export all assets
tower_export: export:
all: true all: true
register: all_assets register: all_assets
@@ -35,7 +35,7 @@
- all_assets['assets']['organizations'] | length() >= 2 - all_assets['assets']['organizations'] | length() >= 2
- name: Export all inventories - name: Export all inventories
tower_export: export:
inventory: 'all' inventory: 'all'
register: inventory_export register: inventory_export
@@ -48,7 +48,7 @@
# This mimics the example in the module # This mimics the example in the module
- name: Export an all and a specific - name: Export an all and a specific
tower_export: export:
inventory: 'all' inventory: 'all'
organizations: "{{ org_name1 }}" organizations: "{{ org_name1 }}"
register: mixed_export register: mixed_export
@@ -63,13 +63,13 @@
always: always:
- name: Remove our inventory - name: Remove our inventory
tower_inventory: inventory:
name: "{{ inventory_name1 }}" name: "{{ inventory_name1 }}"
organization: "{{ org_name1 }}" organization: "{{ org_name1 }}"
state: absent state: absent
- name: Remove test organizations - name: Remove test organizations
tower_organization: organization:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent
loop: loop:

View File

@@ -1,23 +1,23 @@
--- ---
- name: Generate names - name: Generate names
set_fact: set_fact:
group_name1: "AWX-Collection-tests-tower_group-group-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" group_name1: "AWX-Collection-tests-group-group-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
group_name2: "AWX-Collection-tests-tower_group-group-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" group_name2: "AWX-Collection-tests-group-group-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
group_name3: "AWX-Collection-tests-tower_group-group-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" group_name3: "AWX-Collection-tests-group-group-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
inv_name: "AWX-Collection-test-tower_group-inv-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" inv_name: "AWX-Collection-tests-group-inv-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
host_name1: "AWX-Collection-test-tower_group-host-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" host_name1: "AWX-Collection-tests-group-host-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
host_name2: "AWX-Collection-test-tower_group-host-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" host_name2: "AWX-Collection-tests-group-host-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
host_name3: "AWX-Collection-test-tower_group-host-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" host_name3: "AWX-Collection-tests-group-host-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
- name: Create an Inventory - name: Create an Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: Default organization: Default
state: present state: present
register: result register: result
- name: Create a Group - name: Create a Group
tower_group: group:
name: "{{ group_name1 }}" name: "{{ group_name1 }}"
inventory: "{{ result.id }}" inventory: "{{ result.id }}"
state: present state: present
@@ -30,7 +30,7 @@
- "result is changed" - "result is changed"
- name: Create a Group - name: Create a Group
tower_group: group:
name: "{{ group_name2 }}" name: "{{ group_name2 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
state: present state: present
@@ -43,7 +43,7 @@
- "result is changed" - "result is changed"
- name: Create a Group - name: Create a Group
tower_group: group:
name: "{{ group_name3 }}" name: "{{ group_name3 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
state: present state: present
@@ -56,7 +56,7 @@
- "result is changed" - "result is changed"
- name: add hosts - name: add hosts
tower_host: host:
name: "{{ item }}" name: "{{ item }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
loop: loop:
@@ -65,7 +65,7 @@
- "{{ host_name3 }}" - "{{ host_name3 }}"
- name: Create a Group with hosts and sub group - name: Create a Group with hosts and sub group
tower_group: group:
name: "{{ group_name1 }}" name: "{{ group_name1 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
hosts: hosts:
@@ -79,7 +79,7 @@
register: result register: result
- name: Create a Group with hosts and sub group - name: Create a Group with hosts and sub group
tower_group: group:
name: "{{ group_name1 }}" name: "{{ group_name1 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
hosts: hosts:
@@ -93,14 +93,14 @@
- name: "Find number of hosts in {{ group_name1 }}" - name: "Find number of hosts in {{ group_name1 }}"
set_fact: set_fact:
group1_host_count: "{{ lookup('awx.awx.tower_api', 'groups/{{result.id}}/all_hosts/') |length}}" group1_host_count: "{{ lookup('awx.awx.controller_api', 'groups/{{result.id}}/all_hosts/') |length}}"
- assert: - assert:
that: that:
- group1_host_count == "3" - group1_host_count == "3"
- name: Delete a Group - name: Delete a Group
tower_group: group:
name: "{{ group_name1 }}" name: "{{ group_name1 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
state: absent state: absent
@@ -111,7 +111,7 @@
- "result is changed" - "result is changed"
- name: Delete a Group - name: Delete a Group
tower_group: group:
name: "{{ group_name2 }}" name: "{{ group_name2 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
state: absent state: absent
@@ -122,7 +122,7 @@
- "result is changed" - "result is changed"
- name: Delete a Group - name: Delete a Group
tower_group: group:
name: "{{ group_name3 }}" name: "{{ group_name3 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
state: absent state: absent
@@ -133,7 +133,7 @@
- "result is not changed" - "result is not changed"
- name: Check module fails with correct msg - name: Check module fails with correct msg
tower_group: group:
name: test-group name: test-group
description: Group Description description: Group Description
inventory: test-non-existing-inventory inventory: test-non-existing-inventory
@@ -149,7 +149,7 @@
- "result.total_results == 0" - "result.total_results == 0"
- name: add hosts - name: add hosts
tower_host: host:
name: "{{ item }}" name: "{{ item }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
loop: loop:
@@ -158,14 +158,14 @@
- "{{ host_name3 }}" - "{{ host_name3 }}"
- name: add mid level group - name: add mid level group
tower_group: group:
name: "{{ group_name2 }}" name: "{{ group_name2 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
hosts: hosts:
- "{{ host_name3 }}" - "{{ host_name3 }}"
- name: add top group - name: add top group
tower_group: group:
name: "{{ group_name3 }}" name: "{{ group_name3 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
hosts: hosts:
@@ -175,19 +175,19 @@
- "{{ group_name2 }}" - "{{ group_name2 }}"
- name: Delete the parent group - name: Delete the parent group
tower_group: group:
name: "{{ group_name3 }}" name: "{{ group_name3 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
state: absent state: absent
- name: Delete the child group - name: Delete the child group
tower_group: group:
name: "{{ group_name2 }}" name: "{{ group_name2 }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
state: absent state: absent
- name: Delete an Inventory - name: Delete an Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: Default organization: Default
state: absent state: absent

View File

@@ -1,18 +1,18 @@
--- ---
- name: Generate names - name: Generate names
set_fact: set_fact:
host_name: "AWX-Collection-tests-tower_host-host-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" host_name: "AWX-Collection-tests-host-host-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
inv_name: "AWX-Collection-tests-tower_host-inv-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" inv_name: "AWX-Collection-tests-host-inv-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
- name: Create an Inventory - name: Create an Inventory
tower_inventory: inventory:
name: "{{ inv_name }}" name: "{{ inv_name }}"
organization: Default organization: Default
state: present state: present
register: result register: result
- name: Create a Host - name: Create a Host
tower_host: host:
name: "{{ host_name }}" name: "{{ host_name }}"
inventory: "{{ result.id }}" inventory: "{{ result.id }}"
state: present state: present
@@ -25,7 +25,7 @@
- "result is changed" - "result is changed"
- name: Delete a Host - name: Delete a Host
tower_host: host:
name: "{{ result.id }}" name: "{{ result.id }}"
inventory: "{{ inv_name }}" inventory: "{{ inv_name }}"
state: absent state: absent
@@ -36,7 +36,7 @@
- "result is changed" - "result is changed"
- name: Check module fails with correct msg - name: Check module fails with correct msg
tower_host: host:
name: test-host name: test-host
description: Host Description description: Host Description
inventory: test-non-existing-inventory inventory: test-non-existing-inventory

View File

@@ -6,12 +6,12 @@
- name: Generate names - name: Generate names
set_fact: set_fact:
org_name1: "AWX-Collection-tests-tower_import-organization-{{ test_id }}" org_name1: "AWX-Collection-tests-import-organization-{{ test_id }}"
org_name2: "AWX-Collection-tests-tower_import-organization2-{{ test_id }}" org_name2: "AWX-Collection-tests-import-organization2-{{ test_id }}"
- block: - block:
- name: "Import something" - name: "Import something"
tower_import: import:
assets: assets:
organizations: organizations:
- name: "{{ org_name1 }}" - name: "{{ org_name1 }}"
@@ -33,7 +33,7 @@
- import_output is changed - import_output is changed
- name: "Import the same thing again" - name: "Import the same thing again"
tower_import: import:
assets: assets:
organizations: organizations:
- name: "{{ org_name1 }}" - name: "{{ org_name1 }}"
@@ -82,7 +82,7 @@
dest: ./org.json dest: ./org.json
- name: "Load assets from a file" - name: "Load assets from a file"
tower_import: import:
assets: "{{ lookup('file', 'org.json') | from_json() }}" assets: "{{ lookup('file', 'org.json') | from_json() }}"
register: import_output register: import_output
@@ -92,7 +92,7 @@
always: always:
- name: Remove organizations - name: Remove organizations
tower_organization: organization:
name: "{{ item }}" name: "{{ item }}"
state: absent state: absent
loop: loop:

Some files were not shown because too many files have changed in this diff Show More