mirror of
https://github.com/ansible/awx.git
synced 2026-01-25 00:11:23 -03:30
Merge pull request #7963 from john-westcott-iv/tools
Collections Completeness Tests Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
commit
1514a5ac23
@ -13,3 +13,5 @@ plugin_routing:
|
||||
deprecation:
|
||||
removal_date: TBD
|
||||
warning_text: see plugin documentation for details
|
||||
tower_notifitcation:
|
||||
redirect: tower_notification_template
|
||||
|
||||
@ -15,7 +15,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: tower_notification
|
||||
module: tower_notification_template
|
||||
author: "Samuel Carpentier (@samcarpentier)"
|
||||
short_description: create, update, or destroy Ansible Tower notification.
|
||||
description:
|
||||
@ -203,7 +203,7 @@ extends_documentation_fragment: awx.awx.auth
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Add Slack notification with custom messages
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: slack notification
|
||||
organization: Default
|
||||
notification_type: slack
|
||||
@ -222,7 +222,7 @@ EXAMPLES = '''
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Add webhook notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: webhook notification
|
||||
notification_type: webhook
|
||||
notification_configuration:
|
||||
@ -233,7 +233,7 @@ EXAMPLES = '''
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Add email notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: email notification
|
||||
notification_type: email
|
||||
notification_configuration:
|
||||
@ -250,7 +250,7 @@ EXAMPLES = '''
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Add twilio notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: twilio notification
|
||||
notification_type: twilio
|
||||
notification_configuration:
|
||||
@ -263,7 +263,7 @@ EXAMPLES = '''
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Add PagerDuty notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: pagerduty notification
|
||||
notification_type: pagerduty
|
||||
notification_configuration:
|
||||
@ -275,7 +275,7 @@ EXAMPLES = '''
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Add IRC notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: irc notification
|
||||
notification_type: irc
|
||||
notification_configuration:
|
||||
@ -290,7 +290,7 @@ EXAMPLES = '''
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
|
||||
- name: Delete notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: old notification
|
||||
state: absent
|
||||
tower_config_file: "~/tower_cli.cfg"
|
||||
@ -55,10 +55,12 @@ options:
|
||||
- The refspec to use for the SCM resource.
|
||||
type: str
|
||||
default: ''
|
||||
scm_credential:
|
||||
credential:
|
||||
description:
|
||||
- Name of the credential to use with this SCM resource.
|
||||
type: str
|
||||
aliases:
|
||||
- scm_credential
|
||||
scm_clean:
|
||||
description:
|
||||
- Remove local modifications before updating.
|
||||
@ -86,11 +88,13 @@ options:
|
||||
type: bool
|
||||
aliases:
|
||||
- scm_allow_override
|
||||
job_timeout:
|
||||
timeout:
|
||||
description:
|
||||
- The amount of time (in seconds) to run before the SCM Update is canceled. A value of 0 means no timeout.
|
||||
default: 0
|
||||
type: int
|
||||
aliases:
|
||||
- job_timeout
|
||||
custom_virtualenv:
|
||||
description:
|
||||
- Local absolute file path containing a custom Python virtualenv to use
|
||||
@ -188,13 +192,13 @@ def main():
|
||||
local_path=dict(),
|
||||
scm_branch=dict(default=''),
|
||||
scm_refspec=dict(default=''),
|
||||
scm_credential=dict(),
|
||||
credential=dict(aliases=['scm_credential']),
|
||||
scm_clean=dict(type='bool', default=False),
|
||||
scm_delete_on_update=dict(type='bool', default=False),
|
||||
scm_update_on_launch=dict(type='bool', default=False),
|
||||
scm_update_cache_timeout=dict(type='int', default=0),
|
||||
allow_override=dict(type='bool', aliases=['scm_allow_override']),
|
||||
job_timeout=dict(type='int', default=0),
|
||||
timeout=dict(type='int', default=0, aliases=['job_timeout']),
|
||||
custom_virtualenv=dict(),
|
||||
organization=dict(required=True),
|
||||
notification_templates_started=dict(type="list", elements='str'),
|
||||
@ -217,13 +221,13 @@ def main():
|
||||
local_path = module.params.get('local_path')
|
||||
scm_branch = module.params.get('scm_branch')
|
||||
scm_refspec = module.params.get('scm_refspec')
|
||||
scm_credential = module.params.get('scm_credential')
|
||||
credential = module.params.get('credential')
|
||||
scm_clean = module.params.get('scm_clean')
|
||||
scm_delete_on_update = module.params.get('scm_delete_on_update')
|
||||
scm_update_on_launch = module.params.get('scm_update_on_launch')
|
||||
scm_update_cache_timeout = module.params.get('scm_update_cache_timeout')
|
||||
allow_override = module.params.get('allow_override')
|
||||
job_timeout = module.params.get('job_timeout')
|
||||
timeout = module.params.get('timeout')
|
||||
custom_virtualenv = module.params.get('custom_virtualenv')
|
||||
organization = module.params.get('organization')
|
||||
state = module.params.get('state')
|
||||
@ -231,8 +235,8 @@ def main():
|
||||
|
||||
# Attempt to look up the related items the user specified (these will fail the module if not found)
|
||||
org_id = module.resolve_name_to_id('organizations', organization)
|
||||
if scm_credential is not None:
|
||||
scm_credential_id = module.resolve_name_to_id('credentials', scm_credential)
|
||||
if credential is not None:
|
||||
credential = module.resolve_name_to_id('credentials', credential)
|
||||
|
||||
# Attempt to look up project based on the provided name and org ID
|
||||
project = module.get_one('projects', **{
|
||||
@ -276,7 +280,7 @@ def main():
|
||||
'scm_refspec': scm_refspec,
|
||||
'scm_clean': scm_clean,
|
||||
'scm_delete_on_update': scm_delete_on_update,
|
||||
'timeout': job_timeout,
|
||||
'timeout': timeout,
|
||||
'organization': org_id,
|
||||
'scm_update_on_launch': scm_update_on_launch,
|
||||
'scm_update_cache_timeout': scm_update_cache_timeout,
|
||||
@ -284,8 +288,8 @@ def main():
|
||||
}
|
||||
if description is not None:
|
||||
project_fields['description'] = description
|
||||
if scm_credential is not None:
|
||||
project_fields['credential'] = scm_credential_id
|
||||
if credential is not None:
|
||||
project_fields['credential'] = credential
|
||||
if allow_override is not None:
|
||||
project_fields['allow_override'] = allow_override
|
||||
if scm_type == '':
|
||||
|
||||
268
awx_collection/test/awx/test_completeness.py
Normal file
268
awx_collection/test/awx/test_completeness.py
Normal file
@ -0,0 +1,268 @@
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
from awx.main.tests.functional.conftest import _request
|
||||
from ansible.module_utils.six import PY2, string_types
|
||||
import yaml
|
||||
import os
|
||||
import re
|
||||
|
||||
# Analysis variables
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
# 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
|
||||
# For example, we have a tower_role module but /api/v2/roles is a read only endpoint.
|
||||
# This list indicates which read-only endpoints have associated modules with them.
|
||||
read_only_endpoints_with_modules = ['tower_settings', 'tower_role']
|
||||
|
||||
# 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
|
||||
no_module_for_endpoint = []
|
||||
|
||||
# Some modules work on the related fields of an endpoint. These modules will not have an auto-associated endpoint
|
||||
no_endpoint_for_module = [
|
||||
'tower_import', 'tower_meta', 'tower_export', 'tower_job_launch', 'tower_job_wait', 'tower_job_list',
|
||||
'tower_license', 'tower_ping', 'tower_receive', 'tower_send', 'tower_workflow_launch', 'tower_job_cancel',
|
||||
'tower_workflow_template',
|
||||
]
|
||||
|
||||
# Global module parameters we can ignore
|
||||
ignore_parameters = [
|
||||
'state', 'new_name',
|
||||
]
|
||||
|
||||
# Some modules take additional parameters that do not appear in the API
|
||||
# Add the module name as the key with the value being the list of params to ignore
|
||||
no_api_parameter_ok = {
|
||||
# The wait is for whether or not to wait for a project update on change
|
||||
'tower_project': ['wait'],
|
||||
# Existing_token and id are for working with an existing tokens
|
||||
'tower_token': ['existing_token', 'existing_token_id'],
|
||||
# /survey spec is now how we handle associations
|
||||
# We take an organization here to help with the lookups only
|
||||
'tower_job_template': ['survey_spec', 'organization'],
|
||||
# Organization is how we looking job templates
|
||||
'tower_workflow_job_template_node': ['organization'],
|
||||
# Survey is how we handle associations
|
||||
'tower_workflow_job_template': ['survey'],
|
||||
}
|
||||
|
||||
# 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
|
||||
# work is being done and will bypass this check. At some point this module should be removed from this list.
|
||||
needs_development = [
|
||||
'tower_ad_hoc_command', 'tower_application', 'tower_instance_group', 'tower_inventory_script',
|
||||
'tower_workflow_approval'
|
||||
]
|
||||
needs_param_development = {
|
||||
'tower_host': ['instance_id'],
|
||||
'tower_inventory': ['insights_credential'],
|
||||
}
|
||||
# -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
return_value = 0
|
||||
read_only_endpoint = []
|
||||
|
||||
|
||||
def cause_error(msg):
|
||||
global return_value
|
||||
return_value = 255
|
||||
return msg
|
||||
|
||||
|
||||
def determine_state(module_id, endpoint, module, parameter, api_option, module_option):
|
||||
# This is a hierarchical list of things that are ok/failures based on conditions
|
||||
|
||||
# If we know this module needs development this is a non-blocking failure
|
||||
if module_id in needs_development and module == 'N/A':
|
||||
return "Failed (non-blocking), module needs development"
|
||||
|
||||
# If the module is a read only endpoint:
|
||||
# If it has no module on disk that is ok.
|
||||
# If it has a module on disk but its listed in read_only_endpoints_with_modules that is ok
|
||||
# Else we have a module for a read only endpoint that should not exit
|
||||
if module_id in read_only_endpoint:
|
||||
if module == 'N/A':
|
||||
# There may be some cases where a read only endpoint has a module
|
||||
return "OK, this endpoint is read-only and should not have a module"
|
||||
elif module_id in read_only_endpoints_with_modules:
|
||||
return "OK, module params can not be checked to read-only"
|
||||
else:
|
||||
return cause_error("Failed, read-only endpoint should not have an associated module")
|
||||
|
||||
# If the endpoint is listed as not needing a module and we don't have one we are ok
|
||||
if module_id in no_module_for_endpoint and module == 'N/A':
|
||||
return "OK, this endpoint should not have a module"
|
||||
|
||||
# If module is listed as not needing an endpoint and we don't have one we are ok
|
||||
if module_id in no_endpoint_for_module and endpoint == 'N/A':
|
||||
return "OK, this module does not require an endpoint"
|
||||
|
||||
# All of the end/point module conditionals are done so if we don't have a module or endpoint we have a problem
|
||||
if module == 'N/A':
|
||||
return cause_error('Failed, missing module')
|
||||
if endpoint == 'N/A':
|
||||
return cause_error('Failed, why does this module have no endpoint')
|
||||
|
||||
# Now perform parameter checks
|
||||
|
||||
# First, if the parameter is in the ignore_parameters list we are ok
|
||||
if parameter in ignore_parameters:
|
||||
return "OK, globally ignored parameter"
|
||||
|
||||
# If both the api option and the module option are both either objects or none
|
||||
if (api_option is None) ^ (module_option is None):
|
||||
# If the API option is node and the parameter is in the no_api_parameter list we are ok
|
||||
if api_option is None and parameter in no_api_parameter_ok.get(module, {}):
|
||||
return 'OK, no api parameter is ok'
|
||||
# If we know this parameter needs development and we don't have a module option we are non-blocking
|
||||
if module_option is None and parameter in needs_param_development.get(module_id, {}):
|
||||
return "Failed (non-blocking), parameter needs development"
|
||||
# Check for deprecated in the node, if its deprecated and has no api option we are ok, otherwise we have a problem
|
||||
if module_option and module_option.get('description'):
|
||||
description = ''
|
||||
if isinstance(module_option.get('description'), string_types):
|
||||
description = module_option.get('description')
|
||||
else:
|
||||
description = " ".join(module_option.get('description'))
|
||||
|
||||
if 'deprecated' in description.lower():
|
||||
if api_option is None:
|
||||
return 'OK, deprecated module option'
|
||||
else:
|
||||
return cause_error('Failed, module marks option as deprecated but option still exists in API')
|
||||
# If we don't have a corresponding API option but we are a list then we are likely a relation
|
||||
if not api_option and module_option and module_option.get('type', 'str') == 'list':
|
||||
return "OK, Field appears to be relation"
|
||||
# TODO, at some point try and check the object model to confirm its actually a relation
|
||||
return cause_error('Failed, option mismatch')
|
||||
|
||||
# We made it through all of the checks so we are ok
|
||||
return 'OK'
|
||||
|
||||
|
||||
def test_completeness(collection_import, request, admin_user, job_template):
|
||||
option_comparison = {}
|
||||
# Load a list of existing module files from disk
|
||||
base_folder = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)
|
||||
)
|
||||
module_directory = os.path.join(base_folder, 'plugins', 'modules')
|
||||
for root, dirs, files in os.walk(module_directory):
|
||||
if root == module_directory:
|
||||
for filename in files:
|
||||
if re.match('^tower_.*.py$', filename):
|
||||
module_name = filename[:-3]
|
||||
option_comparison[module_name] = {
|
||||
'endpoint': 'N/A',
|
||||
'api_options': {},
|
||||
'module_options': {},
|
||||
'module_name': module_name,
|
||||
}
|
||||
resource_module = collection_import('plugins.modules.{0}'.format(module_name))
|
||||
option_comparison[module_name]['module_options'] = yaml.load(
|
||||
resource_module.DOCUMENTATION,
|
||||
Loader=yaml.SafeLoader
|
||||
)['options']
|
||||
|
||||
endpoint_response = _request('get')(
|
||||
url='/api/v2/',
|
||||
user=admin_user,
|
||||
expect=None,
|
||||
)
|
||||
for endpoint in endpoint_response.data.keys():
|
||||
# Module names are singular and endpoints are plural so we need to convert to singular
|
||||
singular_endpoint = '{0}'.format(endpoint)
|
||||
if singular_endpoint.endswith('ies'):
|
||||
singular_endpoint = singular_endpoint[:-3]
|
||||
if singular_endpoint != 'settings' and singular_endpoint.endswith('s'):
|
||||
singular_endpoint = singular_endpoint[:-1]
|
||||
module_name = 'tower_{0}'.format(singular_endpoint)
|
||||
|
||||
endpoint_url = endpoint_response.data.get(endpoint)
|
||||
|
||||
# If we don't have a module for this endpoint then we can create an empty one
|
||||
if module_name not in option_comparison:
|
||||
option_comparison[module_name] = {}
|
||||
option_comparison[module_name]['module_name'] = 'N/A'
|
||||
option_comparison[module_name]['module_options'] = {}
|
||||
|
||||
# Add in our endpoint and an empty api_options
|
||||
option_comparison[module_name]['endpoint'] = endpoint_url
|
||||
option_comparison[module_name]['api_options'] = {}
|
||||
|
||||
# Get out the endpoint, load and parse its options page
|
||||
options_response = _request('options')(
|
||||
url=endpoint_url,
|
||||
user=admin_user,
|
||||
expect=None,
|
||||
)
|
||||
if 'POST' in options_response.data.get('actions', {}):
|
||||
option_comparison[module_name]['api_options'] = options_response.data.get('actions').get('POST')
|
||||
else:
|
||||
read_only_endpoint.append(module_name)
|
||||
|
||||
# Parse through our data to get string lengths to make a pretty report
|
||||
longest_module_name = 0
|
||||
longest_option_name = 0
|
||||
longest_endpoint = 0
|
||||
for module in option_comparison:
|
||||
if len(option_comparison[module]['module_name']) > longest_module_name:
|
||||
longest_module_name = len(option_comparison[module]['module_name'])
|
||||
if len(option_comparison[module]['endpoint']) > longest_endpoint:
|
||||
longest_endpoint = len(option_comparison[module]['endpoint'])
|
||||
for option in option_comparison[module]['api_options'], option_comparison[module]['module_options']:
|
||||
if len(option) > longest_option_name:
|
||||
longest_option_name = len(option)
|
||||
|
||||
# Print out some headers
|
||||
print("".join([
|
||||
"End Point", " " * (longest_endpoint - len("End Point")),
|
||||
" | Module Name", " " * (longest_module_name - len("Module Name")),
|
||||
" | Option", " " * (longest_option_name - len("Option")),
|
||||
" | API | Module | State",
|
||||
]))
|
||||
print("-|-".join([
|
||||
"-" * longest_endpoint,
|
||||
"-" * longest_module_name,
|
||||
"-" * longest_option_name,
|
||||
"---",
|
||||
"------",
|
||||
"---------------------------------------------",
|
||||
]))
|
||||
|
||||
# Print out all of our data
|
||||
for module in sorted(option_comparison):
|
||||
module_data = option_comparison[module]
|
||||
all_param_names = list(set(module_data['api_options']) | set(module_data['module_options']))
|
||||
for parameter in sorted(all_param_names):
|
||||
print("".join([
|
||||
module_data['endpoint'], " " * (longest_endpoint - len(module_data['endpoint'])), " | ",
|
||||
module_data['module_name'], " " * (longest_module_name - len(module_data['module_name'])), " | ",
|
||||
parameter, " " * (longest_option_name - len(parameter)), " | ",
|
||||
" X " if (parameter in module_data['api_options']) else ' ', " | ",
|
||||
' X ' if (parameter in module_data['module_options']) else ' ', " | ",
|
||||
determine_state(
|
||||
module,
|
||||
module_data['endpoint'],
|
||||
module_data['module_name'],
|
||||
parameter,
|
||||
module_data['api_options'][parameter] if (parameter in module_data['api_options']) else None,
|
||||
module_data['module_options'][parameter] if (parameter in module_data['module_options']) else None,
|
||||
),
|
||||
]))
|
||||
# This handles cases were we got no params from the options page nor from the modules
|
||||
if len(all_param_names) == 0:
|
||||
print("".join([
|
||||
module_data['endpoint'], " " * (longest_endpoint - len(module_data['endpoint'])), " | ",
|
||||
module_data['module_name'], " " * (longest_module_name - len(module_data['module_name'])), " | ",
|
||||
"N/A", " " * (longest_option_name - len("N/A")), " | ",
|
||||
' ', " | ",
|
||||
' ', " | ",
|
||||
determine_state(module, module_data['endpoint'], module_data['module_name'], 'N/A', None, None),
|
||||
]))
|
||||
|
||||
if return_value != 0:
|
||||
raise Exception("One or more failures caused issues")
|
||||
@ -34,7 +34,7 @@ def test_create_modify_notification_template(run_module, admin_user, organizatio
|
||||
'use_tls': False, 'use_ssl': False,
|
||||
'timeout': 4
|
||||
}
|
||||
result = run_module('tower_notification', dict(
|
||||
result = run_module('tower_notification_template', dict(
|
||||
name='foo-notification-template',
|
||||
organization=organization.name,
|
||||
notification_type='email',
|
||||
@ -49,7 +49,7 @@ def test_create_modify_notification_template(run_module, admin_user, organizatio
|
||||
|
||||
# Test no-op, this is impossible if the notification_configuration is given
|
||||
# because we cannot determine if password fields changed
|
||||
result = run_module('tower_notification', dict(
|
||||
result = run_module('tower_notification_template', dict(
|
||||
name='foo-notification-template',
|
||||
organization=organization.name,
|
||||
notification_type='email',
|
||||
@ -59,7 +59,7 @@ def test_create_modify_notification_template(run_module, admin_user, organizatio
|
||||
|
||||
# Test a change in the configuration
|
||||
nt_config['timeout'] = 12
|
||||
result = run_module('tower_notification', dict(
|
||||
result = run_module('tower_notification_template', dict(
|
||||
name='foo-notification-template',
|
||||
organization=organization.name,
|
||||
notification_type='email',
|
||||
@ -74,7 +74,7 @@ def test_create_modify_notification_template(run_module, admin_user, organizatio
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_invalid_notification_configuration(run_module, admin_user, organization):
|
||||
result = run_module('tower_notification', dict(
|
||||
result = run_module('tower_notification_template', dict(
|
||||
name='foo-notification-template',
|
||||
organization=organization.name,
|
||||
notification_type='email',
|
||||
@ -92,7 +92,7 @@ def test_deprecated_to_modern_no_op(run_module, admin_user, organization):
|
||||
'X-Custom-Header': 'value123'
|
||||
}
|
||||
}
|
||||
result = run_module('tower_notification', dict(
|
||||
result = run_module('tower_notification_template', dict(
|
||||
name='foo-notification-template',
|
||||
organization=organization.name,
|
||||
notification_type='webhook',
|
||||
@ -101,7 +101,7 @@ def test_deprecated_to_modern_no_op(run_module, admin_user, organization):
|
||||
assert not result.get('failed', False), result.get('msg', result)
|
||||
assert result.pop('changed', None), result
|
||||
|
||||
result = run_module('tower_notification', dict(
|
||||
result = run_module('tower_notification_template', dict(
|
||||
name='foo-notification-template',
|
||||
organization=organization.name,
|
||||
notification_type='webhook',
|
||||
@ -1,14 +1,14 @@
|
||||
---
|
||||
- name: Generate names
|
||||
set_fact:
|
||||
slack_not: "AWX-Collection-tests-tower_notification-slack-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
webhook_not: "AWX-Collection-tests-tower_notification-wehbook-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
email_not: "AWX-Collection-tests-tower_notification-email-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
twillo_not: "AWX-Collection-tests-tower_notification-twillo-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
pd_not: "AWX-Collection-tests-tower_notification-pd-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
irc_not: "AWX-Collection-tests-tower_notification-irc-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
slack_not: "AWX-Collection-tests-tower_notification_template-slack-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
webhook_not: "AWX-Collection-tests-tower_notification_template-wehbook-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
email_not: "AWX-Collection-tests-tower_notification_template-email-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
twillo_not: "AWX-Collection-tests-tower_notification_template-twillo-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
pd_not: "AWX-Collection-tests-tower_notification_template-pd-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
irc_not: "AWX-Collection-tests-tower_notification_template-irc-not-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||
|
||||
- name: Test deprecation warnings
|
||||
- name: Test deprecation warnings with legacy name
|
||||
tower_notification:
|
||||
name: "{{ slack_not }}"
|
||||
organization: Default
|
||||
@ -54,7 +54,7 @@
|
||||
- result['deprecations'] | length() == 25
|
||||
|
||||
- name: Create Slack notification with custom messages
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ slack_not }}"
|
||||
organization: Default
|
||||
notification_type: slack
|
||||
@ -76,7 +76,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Delete Slack notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ slack_not }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
@ -87,7 +87,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Add webhook notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ webhook_not }}"
|
||||
organization: Default
|
||||
notification_type: webhook
|
||||
@ -102,7 +102,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Delete webhook notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ webhook_not }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
@ -113,7 +113,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Add email notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ email_not }}"
|
||||
organization: Default
|
||||
notification_type: email
|
||||
@ -134,7 +134,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Delete email notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ email_not }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
@ -145,7 +145,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Add twilio notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ twillo_not }}"
|
||||
organization: Default
|
||||
notification_type: twilio
|
||||
@ -162,7 +162,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Delete twilio notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ twillo_not }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
@ -173,7 +173,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Add PagerDuty notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ pd_not }}"
|
||||
organization: Default
|
||||
notification_type: pagerduty
|
||||
@ -189,7 +189,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Delete PagerDuty notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ pd_not }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
@ -200,7 +200,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Add IRC notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ irc_not }}"
|
||||
organization: Default
|
||||
notification_type: irc
|
||||
@ -219,7 +219,7 @@
|
||||
- result is changed
|
||||
|
||||
- name: Delete IRC notification
|
||||
tower_notification:
|
||||
tower_notification_template:
|
||||
name: "{{ irc_not }}"
|
||||
organization: Default
|
||||
state: absent
|
||||
Loading…
x
Reference in New Issue
Block a user