mirror of
https://github.com/ansible/awx.git
synced 2026-02-27 15:58:45 -03:30
Merge branch 'devel' into 5813-WorkflowJTForm
This commit is contained in:
@@ -4303,7 +4303,7 @@ class NotificationTemplateTest(GenericAPIView):
|
|||||||
msg = "Tower Notification Test {} {}".format(obj.id, settings.TOWER_URL_BASE)
|
msg = "Tower Notification Test {} {}".format(obj.id, settings.TOWER_URL_BASE)
|
||||||
if obj.notification_type in ('email', 'pagerduty'):
|
if obj.notification_type in ('email', 'pagerduty'):
|
||||||
body = "Ansible Tower Test Notification {} {}".format(obj.id, settings.TOWER_URL_BASE)
|
body = "Ansible Tower Test Notification {} {}".format(obj.id, settings.TOWER_URL_BASE)
|
||||||
elif obj.notification_type == 'webhook':
|
elif obj.notification_type in ('webhook', 'grafana'):
|
||||||
body = '{{"body": "Ansible Tower Test Notification {} {}"}}'.format(obj.id, settings.TOWER_URL_BASE)
|
body = '{{"body": "Ansible Tower Test Notification {} {}"}}'.format(obj.id, settings.TOWER_URL_BASE)
|
||||||
else:
|
else:
|
||||||
body = {"body": "Ansible Tower Test Notification {} {}".format(obj.id, settings.TOWER_URL_BASE)}
|
body = {"body": "Ansible Tower Test Notification {} {}".format(obj.id, settings.TOWER_URL_BASE)}
|
||||||
|
|||||||
@@ -270,21 +270,19 @@ class JobNotificationMixin(object):
|
|||||||
'elapsed', 'job_explanation', 'execution_node', 'controller_node', 'allow_simultaneous',
|
'elapsed', 'job_explanation', 'execution_node', 'controller_node', 'allow_simultaneous',
|
||||||
'scm_revision', 'diff_mode', 'job_slice_number', 'job_slice_count', 'custom_virtualenv',
|
'scm_revision', 'diff_mode', 'job_slice_number', 'job_slice_count', 'custom_virtualenv',
|
||||||
'approval_status', 'approval_node_name', 'workflow_url',
|
'approval_status', 'approval_node_name', 'workflow_url',
|
||||||
{'host_status_counts': ['skipped', 'ok', 'changed', 'failures', 'dark']},
|
{'host_status_counts': ['skipped', 'ok', 'changed', 'failed', 'failures', 'dark'
|
||||||
{'playbook_counts': ['play_count', 'task_count']},
|
'processed', 'rescued', 'ignored']},
|
||||||
{'summary_fields': [{'inventory': ['id', 'name', 'description', 'has_active_failures',
|
{'summary_fields': [{'inventory': ['id', 'name', 'description', 'has_active_failures',
|
||||||
'total_hosts', 'hosts_with_active_failures', 'total_groups',
|
'total_hosts', 'hosts_with_active_failures', 'total_groups',
|
||||||
'has_inventory_sources',
|
'has_inventory_sources',
|
||||||
'total_inventory_sources', 'inventory_sources_with_failures',
|
'total_inventory_sources', 'inventory_sources_with_failures',
|
||||||
'organization_id', 'kind']},
|
'organization_id', 'kind']},
|
||||||
{'project': ['id', 'name', 'description', 'status', 'scm_type']},
|
{'project': ['id', 'name', 'description', 'status', 'scm_type']},
|
||||||
{'project_update': ['id', 'name', 'description', 'status', 'failed']},
|
|
||||||
{'job_template': ['id', 'name', 'description']},
|
{'job_template': ['id', 'name', 'description']},
|
||||||
{'unified_job_template': ['id', 'name', 'description', 'unified_job_type']},
|
{'unified_job_template': ['id', 'name', 'description', 'unified_job_type']},
|
||||||
{'instance_group': ['name', 'id']},
|
{'instance_group': ['name', 'id']},
|
||||||
{'created_by': ['id', 'username', 'first_name', 'last_name']},
|
{'created_by': ['id', 'username', 'first_name', 'last_name']},
|
||||||
{'labels': ['count', 'results']},
|
{'labels': ['count', 'results']}]}]
|
||||||
{'source_workflow_job': ['description', 'elapsed', 'failed', 'id', 'name', 'status']}]}]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def context_stub(cls):
|
def context_stub(cls):
|
||||||
@@ -303,7 +301,7 @@ class JobNotificationMixin(object):
|
|||||||
'finished': False,
|
'finished': False,
|
||||||
'force_handlers': False,
|
'force_handlers': False,
|
||||||
'forks': 0,
|
'forks': 0,
|
||||||
'host_status_counts': {'skipped': 1, 'ok': 5, 'changed': 3, 'failures': 0, 'dark': 0},
|
'host_status_counts': {'skipped': 1, 'ok': 5, 'changed': 3, 'failures': 0, 'dark': 0, 'failed': False, 'processed': 0, 'rescued': 0},
|
||||||
'id': 42,
|
'id': 42,
|
||||||
'job_explanation': 'Sample job explanation',
|
'job_explanation': 'Sample job explanation',
|
||||||
'job_slice_count': 1,
|
'job_slice_count': 1,
|
||||||
@@ -314,7 +312,6 @@ class JobNotificationMixin(object):
|
|||||||
'limit': 'bar_limit',
|
'limit': 'bar_limit',
|
||||||
'modified': datetime.datetime(2018, 12, 13, 6, 4, 0, 0, tzinfo=datetime.timezone.utc),
|
'modified': datetime.datetime(2018, 12, 13, 6, 4, 0, 0, tzinfo=datetime.timezone.utc),
|
||||||
'name': 'Stub JobTemplate',
|
'name': 'Stub JobTemplate',
|
||||||
'playbook_counts': {'play_count': 5, 'task_count': 10},
|
|
||||||
'playbook': 'ping.yml',
|
'playbook': 'ping.yml',
|
||||||
'scm_revision': '',
|
'scm_revision': '',
|
||||||
'skip_tags': '',
|
'skip_tags': '',
|
||||||
@@ -347,18 +344,10 @@ class JobNotificationMixin(object):
|
|||||||
'name': 'Stub project',
|
'name': 'Stub project',
|
||||||
'scm_type': 'git',
|
'scm_type': 'git',
|
||||||
'status': 'successful'},
|
'status': 'successful'},
|
||||||
'project_update': {'id': 5, 'name': 'Stub Project Update', 'description': 'Project Update',
|
|
||||||
'status': 'running', 'failed': False},
|
|
||||||
'unified_job_template': {'description': 'Sample unified job template description',
|
'unified_job_template': {'description': 'Sample unified job template description',
|
||||||
'id': 39,
|
'id': 39,
|
||||||
'name': 'Stub Job Template',
|
'name': 'Stub Job Template',
|
||||||
'unified_job_type': 'job'},
|
'unified_job_type': 'job'}},
|
||||||
'source_workflow_job': {'description': 'Sample workflow job description',
|
|
||||||
'elapsed': 0.000,
|
|
||||||
'failed': False,
|
|
||||||
'id': 88,
|
|
||||||
'name': 'Stub WorkflowJobTemplate',
|
|
||||||
'status': 'running'}},
|
|
||||||
'timeout': 0,
|
'timeout': 0,
|
||||||
'type': 'job',
|
'type': 'job',
|
||||||
'url': '/api/v2/jobs/13/',
|
'url': '/api/v2/jobs/13/',
|
||||||
@@ -392,10 +381,20 @@ class JobNotificationMixin(object):
|
|||||||
The context will contain whitelisted content retrieved from a serialized job object
|
The context will contain whitelisted content retrieved from a serialized job object
|
||||||
(see JobNotificationMixin.JOB_FIELDS_WHITELIST), the job's friendly name,
|
(see JobNotificationMixin.JOB_FIELDS_WHITELIST), the job's friendly name,
|
||||||
and a url to the job run."""
|
and a url to the job run."""
|
||||||
context = {'job': {},
|
job_context = {'host_status_counts': {}}
|
||||||
'job_friendly_name': self.get_notification_friendly_name(),
|
summary = None
|
||||||
'url': self.get_ui_url(),
|
if hasattr(self, 'job_host_summaries'):
|
||||||
'job_metadata': json.dumps(self.notification_data(), indent=4)}
|
summary = self.job_host_summaries.first()
|
||||||
|
if summary:
|
||||||
|
from awx.api.serializers import JobHostSummarySerializer
|
||||||
|
summary_data = JobHostSummarySerializer(summary).to_representation(summary)
|
||||||
|
job_context['host_status_counts'] = summary_data
|
||||||
|
context = {
|
||||||
|
'job': job_context,
|
||||||
|
'job_friendly_name': self.get_notification_friendly_name(),
|
||||||
|
'url': self.get_ui_url(),
|
||||||
|
'job_metadata': json.dumps(self.notification_data(), indent=4)
|
||||||
|
}
|
||||||
|
|
||||||
def build_context(node, fields, whitelisted_fields):
|
def build_context(node, fields, whitelisted_fields):
|
||||||
for safe_field in whitelisted_fields:
|
for safe_field in whitelisted_fields:
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import dateutil.parser as dp
|
import dateutil.parser as dp
|
||||||
@@ -23,6 +24,33 @@ class GrafanaBackend(AWXBaseEmailBackend, CustomNotificationBase):
|
|||||||
recipient_parameter = "grafana_url"
|
recipient_parameter = "grafana_url"
|
||||||
sender_parameter = None
|
sender_parameter = None
|
||||||
|
|
||||||
|
DEFAULT_BODY = "{{ job_metadata }}"
|
||||||
|
default_messages = {
|
||||||
|
"started": {
|
||||||
|
"body": DEFAULT_BODY, "message": CustomNotificationBase.DEFAULT_MSG
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
"body": DEFAULT_BODY, "message": CustomNotificationBase.DEFAULT_MSG
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"body": DEFAULT_BODY, "message": CustomNotificationBase.DEFAULT_MSG
|
||||||
|
},
|
||||||
|
"workflow_approval": {
|
||||||
|
"running": {
|
||||||
|
"message": CustomNotificationBase.DEFAULT_APPROVAL_RUNNING_MSG, "body": None
|
||||||
|
},
|
||||||
|
"approved": {
|
||||||
|
"message": CustomNotificationBase.DEFAULT_APPROVAL_APPROVED_MSG, "body": None
|
||||||
|
},
|
||||||
|
"timed_out": {
|
||||||
|
"message": CustomNotificationBase.DEFAULT_APPROVAL_TIMEOUT_MSG, "body": None
|
||||||
|
},
|
||||||
|
"denied": {
|
||||||
|
"message": CustomNotificationBase.DEFAULT_APPROVAL_DENIED_MSG, "body": None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, grafana_key,dashboardId=None, panelId=None, annotation_tags=None, grafana_no_verify_ssl=False, isRegion=True,
|
def __init__(self, grafana_key,dashboardId=None, panelId=None, annotation_tags=None, grafana_no_verify_ssl=False, isRegion=True,
|
||||||
fail_silently=False, **kwargs):
|
fail_silently=False, **kwargs):
|
||||||
super(GrafanaBackend, self).__init__(fail_silently=fail_silently)
|
super(GrafanaBackend, self).__init__(fail_silently=fail_silently)
|
||||||
@@ -34,6 +62,13 @@ class GrafanaBackend(AWXBaseEmailBackend, CustomNotificationBase):
|
|||||||
self.isRegion = isRegion
|
self.isRegion = isRegion
|
||||||
|
|
||||||
def format_body(self, body):
|
def format_body(self, body):
|
||||||
|
# expect body to be a string representing a dict
|
||||||
|
try:
|
||||||
|
potential_body = json.loads(body)
|
||||||
|
if isinstance(potential_body, dict):
|
||||||
|
body = potential_body
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
body = {}
|
||||||
return body
|
return body
|
||||||
|
|
||||||
def send_messages(self, messages):
|
def send_messages(self, messages):
|
||||||
@@ -41,14 +76,16 @@ class GrafanaBackend(AWXBaseEmailBackend, CustomNotificationBase):
|
|||||||
for m in messages:
|
for m in messages:
|
||||||
grafana_data = {}
|
grafana_data = {}
|
||||||
grafana_headers = {}
|
grafana_headers = {}
|
||||||
try:
|
if 'started' in m.body:
|
||||||
epoch=datetime.datetime.utcfromtimestamp(0)
|
try:
|
||||||
grafana_data['time'] = int((dp.parse(m.body['started']).replace(tzinfo=None) - epoch).total_seconds() * 1000)
|
epoch=datetime.datetime.utcfromtimestamp(0)
|
||||||
grafana_data['timeEnd'] = int((dp.parse(m.body['finished']).replace(tzinfo=None) - epoch).total_seconds() * 1000)
|
grafana_data['time'] = grafana_data['timeEnd'] = int((dp.parse(m.body['started']).replace(tzinfo=None) - epoch).total_seconds() * 1000)
|
||||||
except ValueError:
|
if m.body.get('finished'):
|
||||||
logger.error(smart_text(_("Error converting time {} or timeEnd {} to int.").format(m.body['started'],m.body['finished'])))
|
grafana_data['timeEnd'] = int((dp.parse(m.body['finished']).replace(tzinfo=None) - epoch).total_seconds() * 1000)
|
||||||
if not self.fail_silently:
|
except ValueError:
|
||||||
raise Exception(smart_text(_("Error converting time {} and/or timeEnd {} to int.").format(m.body['started'],m.body['finished'])))
|
logger.error(smart_text(_("Error converting time {} or timeEnd {} to int.").format(m.body['started'],m.body['finished'])))
|
||||||
|
if not self.fail_silently:
|
||||||
|
raise Exception(smart_text(_("Error converting time {} and/or timeEnd {} to int.").format(m.body['started'],m.body['finished'])))
|
||||||
grafana_data['isRegion'] = self.isRegion
|
grafana_data['isRegion'] = self.isRegion
|
||||||
grafana_data['dashboardId'] = self.dashboardId
|
grafana_data['dashboardId'] = self.dashboardId
|
||||||
grafana_data['panelId'] = self.panelId
|
grafana_data['panelId'] = self.panelId
|
||||||
|
|||||||
@@ -23,8 +23,11 @@ class TestJobNotificationMixin(object):
|
|||||||
'finished': bool,
|
'finished': bool,
|
||||||
'force_handlers': bool,
|
'force_handlers': bool,
|
||||||
'forks': int,
|
'forks': int,
|
||||||
'host_status_counts': {'skipped': int, 'ok': int, 'changed': int,
|
'host_status_counts': {
|
||||||
'failures': int, 'dark': int},
|
'skipped': int, 'ok': int, 'changed': int,
|
||||||
|
'failures': int, 'dark': int, 'processed': int,
|
||||||
|
'rescued': int, 'failed': bool
|
||||||
|
},
|
||||||
'id': int,
|
'id': int,
|
||||||
'job_explanation': str,
|
'job_explanation': str,
|
||||||
'job_slice_count': int,
|
'job_slice_count': int,
|
||||||
@@ -36,7 +39,6 @@ class TestJobNotificationMixin(object):
|
|||||||
'modified': datetime.datetime,
|
'modified': datetime.datetime,
|
||||||
'name': str,
|
'name': str,
|
||||||
'playbook': str,
|
'playbook': str,
|
||||||
'playbook_counts': {'play_count': int, 'task_count': int},
|
|
||||||
'scm_revision': str,
|
'scm_revision': str,
|
||||||
'skip_tags': str,
|
'skip_tags': str,
|
||||||
'start_at_task': str,
|
'start_at_task': str,
|
||||||
@@ -68,17 +70,10 @@ class TestJobNotificationMixin(object):
|
|||||||
'name': str,
|
'name': str,
|
||||||
'scm_type': str,
|
'scm_type': str,
|
||||||
'status': str},
|
'status': str},
|
||||||
'project_update': {'id': int, 'name': str, 'description': str, 'status': str, 'failed': bool},
|
|
||||||
'unified_job_template': {'description': str,
|
'unified_job_template': {'description': str,
|
||||||
'id': int,
|
'id': int,
|
||||||
'name': str,
|
'name': str,
|
||||||
'unified_job_type': str},
|
'unified_job_type': str}},
|
||||||
'source_workflow_job': {'description': str,
|
|
||||||
'elapsed': float,
|
|
||||||
'failed': bool,
|
|
||||||
'id': int,
|
|
||||||
'name': str,
|
|
||||||
'status': str}},
|
|
||||||
|
|
||||||
'timeout': int,
|
'timeout': int,
|
||||||
'type': str,
|
'type': str,
|
||||||
|
|||||||
118
awx/ui_next/package-lock.json
generated
118
awx/ui_next/package-lock.json
generated
@@ -4135,36 +4135,51 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@patternfly/patternfly": {
|
"@patternfly/patternfly": {
|
||||||
"version": "2.56.3",
|
"version": "2.66.0",
|
||||||
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-2.56.3.tgz",
|
"resolved": "https://registry.npmjs.org/@patternfly/patternfly/-/patternfly-2.66.0.tgz",
|
||||||
"integrity": "sha512-merUreEz4ul84s+OXwJ27AtMtcBdzExDX+Xn/T84OD6OAgG8iU1x1dnWdFBeEFKOlTpKxwjXxS/Zc8tSxpfRBw=="
|
"integrity": "sha512-fZMr2q9LZhVtKAEcDJ4rzcCGC6iN93mEQPoLlv2T9td5Hba1bLw8Bpgp5fdTm95Fv/++AY0PsdUPZUzh1cx7Sg=="
|
||||||
},
|
},
|
||||||
"@patternfly/react-core": {
|
"@patternfly/react-core": {
|
||||||
"version": "3.135.0",
|
"version": "3.140.11",
|
||||||
"resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-3.135.0.tgz",
|
"resolved": "https://registry.npmjs.org/@patternfly/react-core/-/react-core-3.140.11.tgz",
|
||||||
"integrity": "sha512-5UotimA2VUiYWt/v8j4x/z8MMyvbgXi7z7BKPzicIiKGwmREJCgQ+kf0eAqGUg/YjFLKcDKncoBrPNqVZ8Ykpg==",
|
"integrity": "sha512-841DeN5BTuUS02JfVXAAVJYtWY0HWc4ewqMD32Xog2MAR/pn74jzjnQOSQr4LUyVrH5QufB68SK4Alm2+IUzSw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@patternfly/react-icons": "^3.14.39",
|
"@patternfly/react-icons": "^3.15.3",
|
||||||
"@patternfly/react-styles": "^3.6.27",
|
"@patternfly/react-styles": "^3.7.4",
|
||||||
"@patternfly/react-tokens": "^2.7.25",
|
"@patternfly/react-tokens": "^2.8.4",
|
||||||
"emotion": "^9.2.9",
|
"emotion": "^9.2.9",
|
||||||
"exenv": "^1.2.2",
|
"exenv": "^1.2.2",
|
||||||
"focus-trap-react": "^4.0.1",
|
"focus-trap-react": "^4.0.1",
|
||||||
"tippy.js": "5.1.2"
|
"tippy.js": "5.1.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@patternfly/react-icons": {
|
||||||
|
"version": "3.15.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-3.15.4.tgz",
|
||||||
|
"integrity": "sha512-tOVirISoZDIn0bWYFctGN9B7Q8wQ19FaK4XIUD2sgIDRBzDbe9JWuqdef7ogJFF78eQnZNsWOci6nhvVCVF/zA==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/free-brands-svg-icons": "^5.8.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@patternfly/react-tokens": {
|
||||||
|
"version": "2.8.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-2.8.4.tgz",
|
||||||
|
"integrity": "sha512-GlLyutls0bG39Nwl/sv2FUkicwyRNrXQFso+e7Y4470+VOUtSsVSdQz+rTjgPxQ38olKPsSZdtEjqN9o2PbDiw=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@patternfly/react-icons": {
|
"@patternfly/react-icons": {
|
||||||
"version": "3.14.39",
|
"version": "3.15.4",
|
||||||
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-3.14.39.tgz",
|
"resolved": "https://registry.npmjs.org/@patternfly/react-icons/-/react-icons-3.15.4.tgz",
|
||||||
"integrity": "sha512-/1hhKEFRtvBYNa8BFRurqHdlUYYzdovmllwtEWcxye5lffDC1Ghco1NGQzjm0FtzkxX1hPFvw04HRR2jBBG8xQ==",
|
"integrity": "sha512-tOVirISoZDIn0bWYFctGN9B7Q8wQ19FaK4XIUD2sgIDRBzDbe9JWuqdef7ogJFF78eQnZNsWOci6nhvVCVF/zA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@fortawesome/free-brands-svg-icons": "^5.8.1"
|
"@fortawesome/free-brands-svg-icons": "^5.8.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@patternfly/react-styles": {
|
"@patternfly/react-styles": {
|
||||||
"version": "3.6.27",
|
"version": "3.7.4",
|
||||||
"resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-3.6.27.tgz",
|
"resolved": "https://registry.npmjs.org/@patternfly/react-styles/-/react-styles-3.7.4.tgz",
|
||||||
"integrity": "sha512-XGI+lR0/QIqkGnGHcnzbynR9JImTftDztsXBgaB0FoDu/DmPY4EABgtsF9HvfoAjsIg8KxRs32tqoXN3yN0TWg==",
|
"integrity": "sha512-D+wu0OIfWVgxWNShQhTK9cadw+KdMCoBYR8gbWjV9Q1aCsCEV/aL/x1nMyyaUQ3c2dqizHhujDG4z9jUZCmCcw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"camel-case": "^3.0.0",
|
"camel-case": "^3.0.0",
|
||||||
"css": "^2.2.3",
|
"css": "^2.2.3",
|
||||||
@@ -4174,9 +4189,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@patternfly/react-tokens": {
|
"@patternfly/react-tokens": {
|
||||||
"version": "2.7.25",
|
"version": "2.8.4",
|
||||||
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-2.7.25.tgz",
|
"resolved": "https://registry.npmjs.org/@patternfly/react-tokens/-/react-tokens-2.8.4.tgz",
|
||||||
"integrity": "sha512-04hRDWt07pyjLUO1VN9QbrPpQMJzjd+nQYp8vgoe6+mYBzw+D4banJeudZ1oTFii9hWV+mLEu6aiwPtTigPM1Q=="
|
"integrity": "sha512-GlLyutls0bG39Nwl/sv2FUkicwyRNrXQFso+e7Y4470+VOUtSsVSdQz+rTjgPxQ38olKPsSZdtEjqN9o2PbDiw=="
|
||||||
},
|
},
|
||||||
"@types/babel__core": {
|
"@types/babel__core": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
@@ -7047,9 +7062,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"csstype": {
|
"csstype": {
|
||||||
"version": "2.6.8",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.8.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz",
|
||||||
"integrity": "sha512-msVS9qTuMT5zwAGCVm4mxfrZ18BNc6Csd0oJAtiFMZ1FAx1CCvy2+5MDmYoix63LM/6NDbNtodCiGYGmFgO0dA=="
|
"integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q=="
|
||||||
},
|
},
|
||||||
"currently-unhandled": {
|
"currently-unhandled": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
@@ -9367,8 +9382,7 @@
|
|||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@@ -9389,14 +9403,12 @@
|
|||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -9411,20 +9423,17 @@
|
|||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
@@ -9541,8 +9550,7 @@
|
|||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
@@ -9554,7 +9562,6 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
@@ -9569,7 +9576,6 @@
|
|||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
@@ -9577,14 +9583,12 @@
|
|||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
@@ -9603,7 +9607,6 @@
|
|||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
@@ -9684,8 +9687,7 @@
|
|||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@@ -9697,7 +9699,6 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
@@ -9783,8 +9784,7 @@
|
|||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
@@ -9820,7 +9820,6 @@
|
|||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
@@ -9840,7 +9839,6 @@
|
|||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
@@ -9884,14 +9882,12 @@
|
|||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -15374,9 +15370,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react": {
|
"react": {
|
||||||
"version": "16.10.2",
|
"version": "16.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-16.10.2.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-16.13.0.tgz",
|
||||||
"integrity": "sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw==",
|
"integrity": "sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
@@ -15389,20 +15385,20 @@
|
|||||||
"integrity": "sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag=="
|
"integrity": "sha512-D7y9qZ05FbUh9blqECaJMdDwKluQiO3A9xB+fssd5jKM7YAXucRuEOlX32mJQumUvHUkHRHqXIPBjm6g0FW0Ag=="
|
||||||
},
|
},
|
||||||
"react-dom": {
|
"react-dom": {
|
||||||
"version": "16.10.2",
|
"version": "16.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.10.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.0.tgz",
|
||||||
"integrity": "sha512-kWGDcH3ItJK4+6Pl9DZB16BXYAZyrYQItU4OMy0jAkv5aNqc+mAKb4TpFtAteI6TJZu+9ZlNhaeNQSVQDHJzkw==",
|
"integrity": "sha512-y09d2c4cG220DzdlFkPTnVvGTszVvNpC73v+AaLGLHbkpy3SSgvYq8x0rNwPJ/Rk/CicTNgk0hbHNw1gMEZAXg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"scheduler": "^0.16.2"
|
"scheduler": "^0.19.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": {
|
"scheduler": {
|
||||||
"version": "0.16.2",
|
"version": "0.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.16.2.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.0.tgz",
|
||||||
"integrity": "sha512-BqYVWqwz6s1wZMhjFvLfVR5WXP7ZY32M/wYPo04CcuPM7XZEbV2TBNW7Z0UkguPTl0dWMA59VbNXxK6q+pHItg==",
|
"integrity": "sha512-xowbVaTPe9r7y7RUejcK73/j8tt2jfiyTednOvHbA8JoClvMYCp+r8QegLwK/n8zWQAtZb1fFnER4XLBZXrCxA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
"object-assign": "^4.1.1"
|
"object-assign": "^4.1.1"
|
||||||
|
|||||||
@@ -58,10 +58,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lingui/react": "^2.7.2",
|
"@lingui/react": "^2.7.2",
|
||||||
"@patternfly/patternfly": "^2.56.3",
|
"@patternfly/patternfly": "^2.66.0",
|
||||||
"@patternfly/react-core": "^3.135.0",
|
"@patternfly/react-core": "^3.140.11",
|
||||||
"@patternfly/react-icons": "^3.14.39",
|
"@patternfly/react-icons": "^3.15.4",
|
||||||
"@patternfly/react-tokens": "^2.7.25",
|
"@patternfly/react-tokens": "^2.8.4",
|
||||||
"ansi-to-html": "^0.6.11",
|
"ansi-to-html": "^0.6.11",
|
||||||
"axios": "^0.18.1",
|
"axios": "^0.18.1",
|
||||||
"codemirror": "^5.47.0",
|
"codemirror": "^5.47.0",
|
||||||
@@ -72,9 +72,9 @@
|
|||||||
"html-entities": "^1.2.1",
|
"html-entities": "^1.2.1",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"prop-types": "^15.6.2",
|
"prop-types": "^15.6.2",
|
||||||
"react": "^16.10.2",
|
"react": "^16.13.0",
|
||||||
"react-codemirror2": "^6.0.0",
|
"react-codemirror2": "^6.0.0",
|
||||||
"react-dom": "^16.10.2",
|
"react-dom": "^16.13.0",
|
||||||
"react-router-dom": "^5.1.2",
|
"react-router-dom": "^5.1.2",
|
||||||
"react-virtualized": "^9.21.1",
|
"react-virtualized": "^9.21.1",
|
||||||
"styled-components": "^4.2.0"
|
"styled-components": "^4.2.0"
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import { string, node, number } from 'prop-types';
|
import { string, node, number } from 'prop-types';
|
||||||
import { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core';
|
import { Split, SplitItem, TextListItemVariants } from '@patternfly/react-core';
|
||||||
import { DetailName, DetailValue } from '@components/DetailList';
|
import { DetailName, DetailValue } from '@components/DetailList';
|
||||||
|
import MultiButtonToggle from '@components/MultiButtonToggle';
|
||||||
import { yamlToJson, jsonToYaml, isJson } from '@util/yaml';
|
import { yamlToJson, jsonToYaml, isJson } from '@util/yaml';
|
||||||
import CodeMirrorInput from './CodeMirrorInput';
|
import CodeMirrorInput from './CodeMirrorInput';
|
||||||
import YamlJsonToggle from './YamlJsonToggle';
|
|
||||||
import { JSON_MODE, YAML_MODE } from './constants';
|
import { JSON_MODE, YAML_MODE } from './constants';
|
||||||
|
|
||||||
function getValueAsMode(value, mode) {
|
function getValueAsMode(value, mode) {
|
||||||
@@ -50,8 +50,9 @@ function VariablesDetail({ value, label, rows }) {
|
|||||||
</div>
|
</div>
|
||||||
</SplitItem>
|
</SplitItem>
|
||||||
<SplitItem>
|
<SplitItem>
|
||||||
<YamlJsonToggle
|
<MultiButtonToggle
|
||||||
mode={mode}
|
buttons={[[YAML_MODE, 'YAML'], [JSON_MODE, 'JSON']]}
|
||||||
|
value={mode}
|
||||||
onChange={newMode => {
|
onChange={newMode => {
|
||||||
try {
|
try {
|
||||||
setCurrentValue(getValueAsMode(currentValue, newMode));
|
setCurrentValue(getValueAsMode(currentValue, newMode));
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ describe('<VariablesDetail>', () => {
|
|||||||
const wrapper = shallow(
|
const wrapper = shallow(
|
||||||
<VariablesDetail value="---foo: bar" label="Variables" />
|
<VariablesDetail value="---foo: bar" label="Variables" />
|
||||||
);
|
);
|
||||||
wrapper.find('YamlJsonToggle').invoke('onChange')('javascript');
|
wrapper.find('MultiButtonToggle').invoke('onChange')('javascript');
|
||||||
const input = wrapper.find('Styled(CodeMirrorInput)');
|
const input = wrapper.find('Styled(CodeMirrorInput)');
|
||||||
expect(input.prop('mode')).toEqual('javascript');
|
expect(input.prop('mode')).toEqual('javascript');
|
||||||
expect(input.prop('value')).toEqual('{\n "foo": "bar"\n}');
|
expect(input.prop('value')).toEqual('{\n "foo": "bar"\n}');
|
||||||
|
|
||||||
wrapper.find('YamlJsonToggle').invoke('onChange')('yaml');
|
wrapper.find('MultiButtonToggle').invoke('onChange')('yaml');
|
||||||
const input2 = wrapper.find('Styled(CodeMirrorInput)');
|
const input2 = wrapper.find('Styled(CodeMirrorInput)');
|
||||||
expect(input2.prop('mode')).toEqual('yaml');
|
expect(input2.prop('mode')).toEqual('yaml');
|
||||||
expect(input2.prop('value')).toEqual('foo: bar\n');
|
expect(input2.prop('value')).toEqual('foo: bar\n');
|
||||||
@@ -53,7 +53,7 @@ describe('<VariablesDetail>', () => {
|
|||||||
<VariablesDetail value="---foo: bar" label="Variables" />
|
<VariablesDetail value="---foo: bar" label="Variables" />
|
||||||
);
|
);
|
||||||
act(() => {
|
act(() => {
|
||||||
wrapper.find('YamlJsonToggle').invoke('onChange')('javascript');
|
wrapper.find('MultiButtonToggle').invoke('onChange')('javascript');
|
||||||
});
|
});
|
||||||
wrapper.setProps({
|
wrapper.setProps({
|
||||||
value: '---bar: baz',
|
value: '---bar: baz',
|
||||||
@@ -73,7 +73,7 @@ describe('<VariablesDetail>', () => {
|
|||||||
test('should default empty json to "{}"', () => {
|
test('should default empty json to "{}"', () => {
|
||||||
const wrapper = mount(<VariablesDetail value="" label="Variables" />);
|
const wrapper = mount(<VariablesDetail value="" label="Variables" />);
|
||||||
act(() => {
|
act(() => {
|
||||||
wrapper.find('YamlJsonToggle').invoke('onChange')('javascript');
|
wrapper.find('MultiButtonToggle').invoke('onChange')('javascript');
|
||||||
});
|
});
|
||||||
wrapper.setProps({ value: '' });
|
wrapper.setProps({ value: '' });
|
||||||
const input = wrapper.find('Styled(CodeMirrorInput)');
|
const input = wrapper.find('Styled(CodeMirrorInput)');
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import { useField } from 'formik';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Split, SplitItem } from '@patternfly/react-core';
|
import { Split, SplitItem } from '@patternfly/react-core';
|
||||||
import { CheckboxField, FieldTooltip } from '@components/FormField';
|
import { CheckboxField, FieldTooltip } from '@components/FormField';
|
||||||
|
import MultiButtonToggle from '@components/MultiButtonToggle';
|
||||||
import { yamlToJson, jsonToYaml, isJson } from '@util/yaml';
|
import { yamlToJson, jsonToYaml, isJson } from '@util/yaml';
|
||||||
import CodeMirrorInput from './CodeMirrorInput';
|
import CodeMirrorInput from './CodeMirrorInput';
|
||||||
import YamlJsonToggle from './YamlJsonToggle';
|
|
||||||
import { JSON_MODE, YAML_MODE } from './constants';
|
import { JSON_MODE, YAML_MODE } from './constants';
|
||||||
|
|
||||||
const FieldHeader = styled.div`
|
const FieldHeader = styled.div`
|
||||||
@@ -43,8 +43,9 @@ function VariablesField({
|
|||||||
{tooltip && <FieldTooltip content={tooltip} />}
|
{tooltip && <FieldTooltip content={tooltip} />}
|
||||||
</SplitItem>
|
</SplitItem>
|
||||||
<SplitItem>
|
<SplitItem>
|
||||||
<YamlJsonToggle
|
<MultiButtonToggle
|
||||||
mode={mode}
|
buttons={[[YAML_MODE, 'YAML'], [JSON_MODE, 'JSON']]}
|
||||||
|
value={mode}
|
||||||
onChange={newMode => {
|
onChange={newMode => {
|
||||||
try {
|
try {
|
||||||
const newVal =
|
const newVal =
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { string, func, bool, number } from 'prop-types';
|
import { string, func, bool, number } from 'prop-types';
|
||||||
import { Button, Split, SplitItem } from '@patternfly/react-core';
|
import { Split, SplitItem } from '@patternfly/react-core';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { yamlToJson, jsonToYaml, isJson } from '@util/yaml';
|
import { yamlToJson, jsonToYaml, isJson } from '@util/yaml';
|
||||||
|
import MultiButtonToggle from '@components/MultiButtonToggle';
|
||||||
import CodeMirrorInput from './CodeMirrorInput';
|
import CodeMirrorInput from './CodeMirrorInput';
|
||||||
import ButtonGroup from './ButtonGroup';
|
|
||||||
import { JSON_MODE, YAML_MODE } from './constants';
|
import { JSON_MODE, YAML_MODE } from './constants';
|
||||||
|
|
||||||
function formatJson(jsonString) {
|
function formatJson(jsonString) {
|
||||||
return JSON.stringify(JSON.parse(jsonString), null, 2);
|
return JSON.stringify(JSON.parse(jsonString), null, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const SmallButton = styled(Button)`
|
|
||||||
padding: 3px 8px;
|
|
||||||
font-size: var(--pf-global--FontSize--xs);
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SplitItemRight = styled(SplitItem)`
|
const SplitItemRight = styled(SplitItem)`
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
`;
|
`;
|
||||||
@@ -47,40 +42,22 @@ function VariablesInput(props) {
|
|||||||
</label>
|
</label>
|
||||||
</SplitItem>
|
</SplitItem>
|
||||||
<SplitItemRight>
|
<SplitItemRight>
|
||||||
<ButtonGroup>
|
<MultiButtonToggle
|
||||||
<SmallButton
|
buttons={[[YAML_MODE, 'YAML'], [JSON_MODE, 'JSON']]}
|
||||||
onClick={() => {
|
value={mode}
|
||||||
if (mode === YAML_MODE) {
|
onChange={newMode => {
|
||||||
return;
|
try {
|
||||||
}
|
|
||||||
try {
|
|
||||||
onChange(jsonToYaml(value));
|
|
||||||
setMode(YAML_MODE);
|
|
||||||
} catch (err) {
|
|
||||||
onError(err.message);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
variant={mode === YAML_MODE ? 'primary' : 'secondary'}
|
|
||||||
>
|
|
||||||
YAML
|
|
||||||
</SmallButton>
|
|
||||||
<SmallButton
|
|
||||||
onClick={() => {
|
|
||||||
if (mode === JSON_MODE) {
|
if (mode === JSON_MODE) {
|
||||||
return;
|
onChange(jsonToYaml(value));
|
||||||
}
|
} else {
|
||||||
try {
|
|
||||||
onChange(yamlToJson(value));
|
onChange(yamlToJson(value));
|
||||||
setMode(JSON_MODE);
|
|
||||||
} catch (err) {
|
|
||||||
onError(err.message);
|
|
||||||
}
|
}
|
||||||
}}
|
setMode(newMode);
|
||||||
variant={mode === JSON_MODE ? 'primary' : 'secondary'}
|
} catch (err) {
|
||||||
>
|
onError(err.message);
|
||||||
JSON
|
}
|
||||||
</SmallButton>
|
}}
|
||||||
</ButtonGroup>
|
/>
|
||||||
</SplitItemRight>
|
</SplitItemRight>
|
||||||
</Split>
|
</Split>
|
||||||
<CodeMirrorInput
|
<CodeMirrorInput
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { oneOf, func } from 'prop-types';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import { Button } from '@patternfly/react-core';
|
|
||||||
import ButtonGroup from './ButtonGroup';
|
|
||||||
|
|
||||||
const SmallButton = styled(Button)`
|
|
||||||
padding: 3px 8px;
|
|
||||||
font-size: var(--pf-global--FontSize--xs);
|
|
||||||
`;
|
|
||||||
|
|
||||||
const YAML_MODE = 'yaml';
|
|
||||||
const JSON_MODE = 'javascript';
|
|
||||||
|
|
||||||
function YamlJsonToggle({ mode, onChange }) {
|
|
||||||
const setMode = newMode => {
|
|
||||||
if (mode !== newMode) {
|
|
||||||
onChange(newMode);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ButtonGroup>
|
|
||||||
<SmallButton
|
|
||||||
onClick={() => setMode(YAML_MODE)}
|
|
||||||
variant={mode === YAML_MODE ? 'primary' : 'secondary'}
|
|
||||||
>
|
|
||||||
YAML
|
|
||||||
</SmallButton>
|
|
||||||
<SmallButton
|
|
||||||
onClick={() => setMode(JSON_MODE)}
|
|
||||||
variant={mode === JSON_MODE ? 'primary' : 'secondary'}
|
|
||||||
>
|
|
||||||
JSON
|
|
||||||
</SmallButton>
|
|
||||||
</ButtonGroup>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
YamlJsonToggle.propTypes = {
|
|
||||||
mode: oneOf([YAML_MODE, JSON_MODE]).isRequired,
|
|
||||||
onChange: func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default YamlJsonToggle;
|
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { func, string } from 'prop-types';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import { Button } from '@patternfly/react-core';
|
||||||
|
import ButtonGroup from './ButtonGroup';
|
||||||
|
|
||||||
|
const SmallButton = styled(Button)`
|
||||||
|
padding: 3px 8px;
|
||||||
|
font-size: var(--pf-global--FontSize--xs);
|
||||||
|
`;
|
||||||
|
|
||||||
|
function MultiButtonToggle({ buttons, value, onChange }) {
|
||||||
|
const setValue = newValue => {
|
||||||
|
if (value !== newValue) {
|
||||||
|
onChange(newValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ButtonGroup>
|
||||||
|
{buttons &&
|
||||||
|
buttons.map(([buttonValue, buttonLabel]) => (
|
||||||
|
<SmallButton
|
||||||
|
key={buttonLabel}
|
||||||
|
onClick={() => setValue(buttonValue)}
|
||||||
|
variant={buttonValue === value ? 'primary' : 'secondary'}
|
||||||
|
>
|
||||||
|
{buttonLabel}
|
||||||
|
</SmallButton>
|
||||||
|
))}
|
||||||
|
</ButtonGroup>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonsPropType = {
|
||||||
|
isRequired: ({ buttons }) => {
|
||||||
|
if (!buttons) {
|
||||||
|
return new Error(
|
||||||
|
`The prop buttons is marked as required in MultiButtonToggle, but its value is '${buttons}'`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// We expect this data structure to look like:
|
||||||
|
// [[value(unrestricted type), label(string)], [value(unrestricted type), label(string)], ...]
|
||||||
|
if (
|
||||||
|
!Array.isArray(buttons) ||
|
||||||
|
buttons.length < 2 ||
|
||||||
|
buttons.reduce(
|
||||||
|
(prevVal, button) => prevVal || typeof button[1] !== 'string',
|
||||||
|
false
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return new Error(
|
||||||
|
`Invalid prop buttons supplied to MultiButtonToggle. Validation failed.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
MultiButtonToggle.propTypes = {
|
||||||
|
buttons: buttonsPropType.isRequired,
|
||||||
|
value: string.isRequired,
|
||||||
|
onChange: func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MultiButtonToggle;
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { mount } from 'enzyme';
|
||||||
|
import MultiButtonToggle from './MultiButtonToggle';
|
||||||
|
|
||||||
|
describe('<MultiButtonToggle />', () => {
|
||||||
|
let wrapper;
|
||||||
|
const onChange = jest.fn();
|
||||||
|
beforeAll(() => {
|
||||||
|
wrapper = mount(
|
||||||
|
<MultiButtonToggle
|
||||||
|
buttons={[['yaml', 'YAML'], ['json', 'JSON']]}
|
||||||
|
value="yaml"
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
afterAll(() => {
|
||||||
|
wrapper.unmount();
|
||||||
|
});
|
||||||
|
it('should render buttons successfully', () => {
|
||||||
|
const buttons = wrapper.find('Button');
|
||||||
|
expect(buttons.length).toBe(2);
|
||||||
|
expect(buttons.at(0).props().variant).toBe('primary');
|
||||||
|
expect(buttons.at(1).props().variant).toBe('secondary');
|
||||||
|
});
|
||||||
|
it('should call onChange function when button clicked', () => {
|
||||||
|
const buttons = wrapper.find('Button');
|
||||||
|
buttons.at(1).simulate('click');
|
||||||
|
expect(onChange).toHaveBeenCalledWith('json');
|
||||||
|
});
|
||||||
|
});
|
||||||
1
awx/ui_next/src/components/MultiButtonToggle/index.js
Normal file
1
awx/ui_next/src/components/MultiButtonToggle/index.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { default } from './MultiButtonToggle';
|
||||||
@@ -37,7 +37,7 @@ To use this collection in AWX, you should create a custom virtual environment in
|
|||||||
to set the job template `extra_vars` to include `ansible_python_interpreter`
|
to set the job template `extra_vars` to include `ansible_python_interpreter`
|
||||||
to be the Python in that virtual environment.
|
to be the Python in that virtual environment.
|
||||||
|
|
||||||
## Running Tests
|
## Running Unit Tests
|
||||||
|
|
||||||
Tests to verify compatibility with the most recent AWX code are
|
Tests to verify compatibility with the most recent AWX code are
|
||||||
in `awx_collection/test/awx`. These tests require that Python packages
|
in `awx_collection/test/awx`. These tests require that Python packages
|
||||||
@@ -71,6 +71,30 @@ pip install -e .
|
|||||||
PYTHONPATH=awx_collection:$PYTHONPATH py.test awx_collection/test/awx/
|
PYTHONPATH=awx_collection:$PYTHONPATH py.test awx_collection/test/awx/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Running Integration tests Tests
|
||||||
|
|
||||||
|
The integration tests require a virtualenv with `ansible` >= 2.9 and `tower_cli`.
|
||||||
|
The collection must first be installed, which can be done using `make install_collection`.
|
||||||
|
You also need a configuration file at `~/.tower_cli.cfg` or
|
||||||
|
`/etc/tower/tower_cli.cfg` with the credentials for accessing tower. This can
|
||||||
|
be populated using `tower-cli`:
|
||||||
|
|
||||||
|
```
|
||||||
|
tower-cli config host $HOST
|
||||||
|
tower-cli config username $USERNAME
|
||||||
|
tower-cli config password $PASSWORD
|
||||||
|
# This tells the tower-cli not to veriffy the ssl certs in the tower, if your tower has good certs you should leave this to true
|
||||||
|
tower-cli config verify_ssl false
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally you can run the tests:
|
||||||
|
|
||||||
|
```
|
||||||
|
# ansible-test must be run from the directory in which the collection is installed
|
||||||
|
cd ~/.ansible/collections/ansible_collections/awx/awx/
|
||||||
|
ansible-test integration
|
||||||
|
```
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
The build target `make build_collection` will template out a `galaxy.yml` file
|
The build target `make build_collection` will template out a `galaxy.yml` file
|
||||||
|
|||||||
@@ -0,0 +1,539 @@
|
|||||||
|
---
|
||||||
|
- name: create a tempdir for an SSH key
|
||||||
|
local_action: shell mktemp -d
|
||||||
|
register: tempdir
|
||||||
|
|
||||||
|
- name: Generate a local SSH key
|
||||||
|
local_action: "shell ssh-keygen -b 2048 -t rsa -f {{ tempdir.stdout }}/id_rsa -q -N 'passphrase'"
|
||||||
|
|
||||||
|
- name: Read the generated key
|
||||||
|
set_fact:
|
||||||
|
ssh_key_data: "{{ lookup('file', tempdir.stdout + '/id_rsa') }}"
|
||||||
|
|
||||||
|
- name: Create a User-specific credential
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential
|
||||||
|
organization: Default
|
||||||
|
user: admin
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a User-specific credential
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential
|
||||||
|
organization: Default
|
||||||
|
user: admin
|
||||||
|
state: absent
|
||||||
|
kind: ssh
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid SSH credential
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
description: An example SSH credential
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
become_method: sudo
|
||||||
|
become_username: superuser
|
||||||
|
become_password: supersecret
|
||||||
|
ssh_key_data: "{{ ssh_key_data }}"
|
||||||
|
ssh_key_unlock: "passphrase"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid SSH credential from lookup source
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential from lookup source
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
description: An example SSH credential from lookup source
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
become_method: sudo
|
||||||
|
become_username: superuser
|
||||||
|
become_password: supersecret
|
||||||
|
ssh_key_data: "{{ lookup('file', tempdir.stdout + '/id_rsa') }}"
|
||||||
|
ssh_key_unlock: "passphrase"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid SSH credential from file source
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential from file source
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
description: An example SSH credential from file source
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
become_method: sudo
|
||||||
|
become_username: superuser
|
||||||
|
become_password: supersecret
|
||||||
|
ssh_key_data: "{{ tempdir.stdout }}/id_rsa"
|
||||||
|
ssh_key_unlock: "passphrase"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
- "result is not failed"
|
||||||
|
- "'ssh_key_data should be a string, not a path to a file.' in result.deprecations[0].msg"
|
||||||
|
|
||||||
|
- name: Create an invalid SSH credential (passphrase required)
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
username: joe
|
||||||
|
ssh_key_data: "{{ ssh_key_data }}"
|
||||||
|
ignore_errors: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is failed"
|
||||||
|
- "'must be set when SSH key is encrypted' in result.msg"
|
||||||
|
|
||||||
|
- name: Create an invalid SSH credential (Organization not found)
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential
|
||||||
|
organization: Missing Organization
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
username: joe
|
||||||
|
ignore_errors: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is failed"
|
||||||
|
- "'The requested object could not be found' in result.msg"
|
||||||
|
|
||||||
|
- name: Delete an SSH credential
|
||||||
|
tower_credential:
|
||||||
|
name: SSH Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: ssh
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid Vault credential
|
||||||
|
tower_credential:
|
||||||
|
name: Vault Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: vault
|
||||||
|
description: An example Vault credential
|
||||||
|
vault_password: secret-vault
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid Vault credential w/ kind=ssh (deprecated)
|
||||||
|
tower_credential:
|
||||||
|
name: Vault Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: ssh
|
||||||
|
description: An example Vault credential
|
||||||
|
vault_password: secret-vault
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Vault credential
|
||||||
|
tower_credential:
|
||||||
|
name: Vault Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: vault
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid Network credential
|
||||||
|
tower_credential:
|
||||||
|
name: Network Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: net
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
authorize: true
|
||||||
|
authorize_password: authorize-me
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Network credential
|
||||||
|
tower_credential:
|
||||||
|
name: Network Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: net
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid SCM credential
|
||||||
|
tower_credential:
|
||||||
|
name: SCM Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: scm
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
ssh_key_data: "{{ ssh_key_data }}"
|
||||||
|
ssh_key_unlock: "passphrase"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete an SCM credential
|
||||||
|
tower_credential:
|
||||||
|
name: SCM Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: scm
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid AWS credential
|
||||||
|
tower_credential:
|
||||||
|
name: AWS Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: aws
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
security_token: aws-token
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete an AWS credential
|
||||||
|
tower_credential:
|
||||||
|
name: AWS Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: aws
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid VMWare credential
|
||||||
|
tower_credential:
|
||||||
|
name: VMWare Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: vmware
|
||||||
|
host: https://example.org
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete an VMWare credential
|
||||||
|
tower_credential:
|
||||||
|
name: VMWare Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: vmware
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid Satellite6 credential
|
||||||
|
tower_credential:
|
||||||
|
name: Satellite6 Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: satellite6
|
||||||
|
host: https://example.org
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Satellite6 credential
|
||||||
|
tower_credential:
|
||||||
|
name: Satellite6 Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: satellite6
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid CloudForms credential
|
||||||
|
tower_credential:
|
||||||
|
name: CloudForms Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: cloudforms
|
||||||
|
host: https://example.org
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a CloudForms credential
|
||||||
|
tower_credential:
|
||||||
|
name: CloudForms Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: cloudforms
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid GCE credential
|
||||||
|
tower_credential:
|
||||||
|
name: GCE Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: gce
|
||||||
|
username: joe
|
||||||
|
project: ABC123
|
||||||
|
ssh_key_data: "{{ ssh_key_data }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a GCE credential
|
||||||
|
tower_credential:
|
||||||
|
name: GCE Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: gce
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid AzureRM credential
|
||||||
|
tower_credential:
|
||||||
|
name: AzureRM Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: azure_rm
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
subscription: some-subscription
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid AzureRM credential with a tenant
|
||||||
|
tower_credential:
|
||||||
|
name: AzureRM Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: azure_rm
|
||||||
|
client: some-client
|
||||||
|
secret: some-secret
|
||||||
|
tenant: some-tenant
|
||||||
|
subscription: some-subscription
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete an AzureRM credential
|
||||||
|
tower_credential:
|
||||||
|
name: AzureRM Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: azure_rm
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid OpenStack credential
|
||||||
|
tower_credential:
|
||||||
|
name: OpenStack Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: openstack
|
||||||
|
host: https://keystone.example.org
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
project: tenant123
|
||||||
|
domain: some-domain
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a OpenStack credential
|
||||||
|
tower_credential:
|
||||||
|
name: OpenStack Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: openstack
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid RHV credential
|
||||||
|
tower_credential:
|
||||||
|
name: RHV Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: rhv
|
||||||
|
host: https://example.org
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete an RHV credential
|
||||||
|
tower_credential:
|
||||||
|
name: RHV Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: rhv
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid Insights credential
|
||||||
|
tower_credential:
|
||||||
|
name: Insights Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: insights
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete an Insights credential
|
||||||
|
tower_credential:
|
||||||
|
name: Insights Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: insights
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a valid Tower-to-Tower credential
|
||||||
|
tower_credential:
|
||||||
|
name: Tower Credential
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
kind: tower
|
||||||
|
host: https://tower.example.org
|
||||||
|
username: joe
|
||||||
|
password: secret
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Tower-to-Tower credential
|
||||||
|
tower_credential:
|
||||||
|
name: Tower Credential
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
kind: tower
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_credential:
|
||||||
|
name: test-credential
|
||||||
|
description: Credential Description
|
||||||
|
kind: ssh
|
||||||
|
organization: test-non-existing-org
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='Failed to update credential, organization not found: The requested object could not be found.'"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
- name: Add Tower credential type
|
||||||
|
tower_credential_type:
|
||||||
|
description: Credential type for Test
|
||||||
|
name: test-credential-type
|
||||||
|
kind: cloud
|
||||||
|
inputs: {"fields": [{"type": "string", "id": "username", "label": "Username"}, {"secret": true, "type": "string", "id": "password", "label": "Password"}], "required": ["username", "password"]}
|
||||||
|
injectors: {"extra_vars": {"test": "foo"}}
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Remove a Tower credential type
|
||||||
|
tower_credential_type:
|
||||||
|
name: test-credential-type
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
- name: Generate an inventory name
|
||||||
|
set_fact:
|
||||||
|
inv_name: "inv-for-group-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||||
|
|
||||||
|
- name: Create an Inventory
|
||||||
|
tower_inventory:
|
||||||
|
name: "{{ inv_name }}"
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create a Group
|
||||||
|
tower_group:
|
||||||
|
name: Some Group
|
||||||
|
inventory: "{{ inv_name }}"
|
||||||
|
state: present
|
||||||
|
variables:
|
||||||
|
foo: bar
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Group
|
||||||
|
tower_group:
|
||||||
|
name: Some Group
|
||||||
|
inventory: "{{ inv_name }}"
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_group:
|
||||||
|
name: test-group
|
||||||
|
description: Group Description
|
||||||
|
inventory: test-non-existing-inventory
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='Failed to update the group, inventory not found: The requested object could not be found.' or
|
||||||
|
result.msg =='The inventories test-non-existing-inventory was not found on the Tower server'"
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
- name: Generate an inventory name
|
||||||
|
set_fact:
|
||||||
|
inv_name: "inv-for-group-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||||
|
|
||||||
|
- name: Create an Inventory
|
||||||
|
tower_inventory:
|
||||||
|
name: "{{ inv_name }}"
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create a Host
|
||||||
|
tower_host:
|
||||||
|
name: "some-host"
|
||||||
|
inventory: "{{ inv_name }}"
|
||||||
|
state: present
|
||||||
|
variables:
|
||||||
|
foo: bar
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Host
|
||||||
|
tower_host:
|
||||||
|
name: "some-host"
|
||||||
|
inventory: "{{ inv_name }}"
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_host:
|
||||||
|
name: test-host
|
||||||
|
description: Host Description
|
||||||
|
inventory: test-non-existing-inventory
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='The inventories test-non-existing-inventory was not found on the Tower server' or
|
||||||
|
result.msg =='Failed to update host, inventory not found: The requested object could not be found.'"
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
---
|
||||||
|
- name: Clean up any pre-existing test Inventory
|
||||||
|
tower_inventory:
|
||||||
|
name: my-inventory
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
|
||||||
|
- name: Create an Inventory
|
||||||
|
tower_inventory:
|
||||||
|
name: my-inventory
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Test Inventory module idempotency
|
||||||
|
tower_inventory:
|
||||||
|
name: my-inventory
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is not changed"
|
||||||
|
|
||||||
|
- name: Fail Change Regular to Smart
|
||||||
|
tower_inventory:
|
||||||
|
name: my-inventory
|
||||||
|
organization: Default
|
||||||
|
kind: smart
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is failed"
|
||||||
|
|
||||||
|
- name: Delete an Inventory
|
||||||
|
tower_inventory:
|
||||||
|
name: my-inventory
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Non-Existent Inventory
|
||||||
|
tower_inventory:
|
||||||
|
name: my-inventory
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is not changed"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_inventory:
|
||||||
|
name: test-inventory
|
||||||
|
description: Inventory Description
|
||||||
|
organization: test-non-existing-org
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is not changed"
|
||||||
|
- "result.msg =='Failed to update inventory, organization not found: The requested object could not be found.'
|
||||||
|
or result.msg =='The organizations test-non-existing-org was not found on the Tower server'"
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
- name: Add a Tower credential
|
||||||
|
tower_credential:
|
||||||
|
description: Credentials for Openstack Test project
|
||||||
|
name: openstack-test-credential
|
||||||
|
kind: openstack
|
||||||
|
organization: Default
|
||||||
|
project: Test
|
||||||
|
username: admin
|
||||||
|
host: https://example.org:5000
|
||||||
|
password: passw0rd
|
||||||
|
domain: test
|
||||||
|
|
||||||
|
- name: Add a Tower inventory
|
||||||
|
tower_inventory:
|
||||||
|
description: Test inventory
|
||||||
|
organization: Default
|
||||||
|
name: openstack-test-inventory
|
||||||
|
|
||||||
|
- name: Create a source inventory
|
||||||
|
tower_inventory_source:
|
||||||
|
name: "source-test-inventory {{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||||
|
description: Source for Test inventory
|
||||||
|
inventory: openstack-test-inventory
|
||||||
|
credential: openstack-test-credential
|
||||||
|
overwrite: true
|
||||||
|
update_on_launch: true
|
||||||
|
source_vars:
|
||||||
|
private: false
|
||||||
|
source: openstack
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete the source inventory
|
||||||
|
tower_inventory_source:
|
||||||
|
name: "{{ result.name }}"
|
||||||
|
description: Source for Test inventory
|
||||||
|
inventory: openstack-test-inventory
|
||||||
|
credential: openstack-test-credential
|
||||||
|
overwrite: true
|
||||||
|
update_on_launch: true
|
||||||
|
source_vars:
|
||||||
|
private: false
|
||||||
|
source: openstack
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
- name: Launch a Job Template
|
||||||
|
tower_job_launch:
|
||||||
|
job_template: "Demo Job Template"
|
||||||
|
register: job
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "job is changed"
|
||||||
|
|
||||||
|
- name: Cancel the job
|
||||||
|
tower_job_cancel:
|
||||||
|
job_id: "{{ job.id }}"
|
||||||
|
register: results
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- results is changed
|
||||||
|
|
||||||
|
- name: Cancel an already canceled job (assert failure)
|
||||||
|
tower_job_cancel:
|
||||||
|
job_id: "{{ job.id }}"
|
||||||
|
fail_if_not_running: true
|
||||||
|
register: results
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- results is failed
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_job_cancel:
|
||||||
|
job_id: 9999999999
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='Unable to cancel job_id/9999999999: The requested object could not be found.'
|
||||||
|
or result.msg =='Unable to find job with id 9999999999'"
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
---
|
||||||
|
- name: Launch a Job Template
|
||||||
|
tower_job_launch:
|
||||||
|
job_template: "Demo Job Template"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
- "result.status == 'pending'"
|
||||||
|
|
||||||
|
- name: Wait for a job template to complete
|
||||||
|
tower_job_wait:
|
||||||
|
job_id: "{{ result.id }}"
|
||||||
|
max_interval: 10
|
||||||
|
timeout: 120
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is not changed"
|
||||||
|
- "result.status == 'successful'"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_job_launch:
|
||||||
|
job_template: "Non Existing Job Template"
|
||||||
|
inventory: "Test Inventory"
|
||||||
|
credential: "Test Credential"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='Unable to launch job, job_template/Non Existing Job Template was not found: The requested object could not be found.'
|
||||||
|
or result.msg == 'The inventories Test Inventory was not found on the Tower server'"
|
||||||
|
|
||||||
|
- name: Create a Job Template for testing prompt on launch
|
||||||
|
tower_job_template:
|
||||||
|
name: "Demo Job Template - ask inventory and credential"
|
||||||
|
project: Demo Project
|
||||||
|
playbook: hello_world.yml
|
||||||
|
job_type: run
|
||||||
|
ask_credential: true
|
||||||
|
ask_inventory: true
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Launch job template with inventory and credential for prompt on launch
|
||||||
|
tower_job_launch:
|
||||||
|
job_template: "Demo Job Template - ask inventory and credential"
|
||||||
|
inventory: "Demo Inventory"
|
||||||
|
credential: "Demo Credential"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
- "result.status == 'pending'"
|
||||||
|
|
||||||
|
- name: Create a project for testing extra_vars
|
||||||
|
tower_project:
|
||||||
|
name: test-playbooks
|
||||||
|
organization: Default
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/test-playbooks
|
||||||
|
|
||||||
|
- name: Create a Job Template for testing extra_vars
|
||||||
|
tower_job_template:
|
||||||
|
name: "Demo Job Template - extra_vars"
|
||||||
|
project: test-playbooks
|
||||||
|
playbook: debug.yml
|
||||||
|
job_type: run
|
||||||
|
state: present
|
||||||
|
inventory: "Demo Inventory"
|
||||||
|
extra_vars:
|
||||||
|
foo: bar
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Launch job template with inventory and credential for prompt on launch
|
||||||
|
tower_job_launch:
|
||||||
|
job_template: "Demo Job Template - extra_vars"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Get the job
|
||||||
|
tower_job_list:
|
||||||
|
query: {"id": "{{result.id}}"}
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- '{"foo": "bar"} | to_json in result.results[0].extra_vars'
|
||||||
|
|
||||||
|
- name: Delete the job
|
||||||
|
tower_project:
|
||||||
|
name: "Demo Job Template - extra_vars"
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
- name: Launch a Job Template
|
||||||
|
tower_job_launch:
|
||||||
|
job_template: "Demo Job Template"
|
||||||
|
register: job
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "job is changed"
|
||||||
|
- "job.status == 'pending'"
|
||||||
|
|
||||||
|
- name: List jobs w/ a matching primary key
|
||||||
|
tower_job_list:
|
||||||
|
query: {"id": "{{ job.id }}"}
|
||||||
|
register: matching_jobs
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "{{ matching_jobs.count }} == 1"
|
||||||
|
|
||||||
|
- name: List failed jobs (which don't exist)
|
||||||
|
tower_job_list:
|
||||||
|
status: failed
|
||||||
|
query: {"id": "{{ job.id }}"}
|
||||||
|
register: successful_jobs
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "{{ successful_jobs.count }} == 0"
|
||||||
|
|
||||||
|
- name: Get ALL result pages!
|
||||||
|
tower_job_list:
|
||||||
|
all_pages: true
|
||||||
|
register: all_page_query
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- 'not all_page_query.next'
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
- name: Create an SCM Credential
|
||||||
|
tower_credential:
|
||||||
|
name: SCM Credential for JT
|
||||||
|
organization: Default
|
||||||
|
kind: scm
|
||||||
|
|
||||||
|
- name: Create a Demo Project
|
||||||
|
tower_project:
|
||||||
|
name: Job Template Test Project
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/ansible-tower-samples.git
|
||||||
|
scm_credential: SCM Credential for JT
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Create a Job Template
|
||||||
|
tower_job_template:
|
||||||
|
name: "hello-world {{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||||
|
project: Job Template Test Project
|
||||||
|
inventory: Demo Inventory
|
||||||
|
playbook: hello_world.yml
|
||||||
|
credential: Demo Credential
|
||||||
|
job_type: run
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
- name: Launch a Job Template
|
||||||
|
tower_job_launch:
|
||||||
|
job_template: "Demo Job Template"
|
||||||
|
register: job
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "job is changed"
|
||||||
|
- "job.status == 'pending'"
|
||||||
|
|
||||||
|
- name: Wait for the Job to finish
|
||||||
|
tower_job_wait:
|
||||||
|
job_id: "{{ job.id }}"
|
||||||
|
timeout: 60
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_job_wait:
|
||||||
|
job_id: "99999999"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='Unable to wait, no job_id 99999999 found: The requested object could not be found.'"
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
- name: Create a Label
|
||||||
|
tower_label:
|
||||||
|
name: important
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_label:
|
||||||
|
name: "Test Label"
|
||||||
|
organization: "Non existing org"
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg == 'Failed to update label, organization not found: The requested object could not be found.'"
|
||||||
|
|
||||||
|
# TODO: Deleting labels doesn't seem to work currently
|
||||||
@@ -0,0 +1,206 @@
|
|||||||
|
---
|
||||||
|
- name: Create Slack notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification1
|
||||||
|
organization: Default
|
||||||
|
notification_type: slack
|
||||||
|
token: a_token
|
||||||
|
channels:
|
||||||
|
- general
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Delete Slack notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification1
|
||||||
|
organization: Default
|
||||||
|
notification_type: slack
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Add webhook notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification2
|
||||||
|
organization: Default
|
||||||
|
notification_type: webhook
|
||||||
|
url: http://www.example.com/hook
|
||||||
|
headers:
|
||||||
|
X-Custom-Header: value123
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Delete webhook notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification2
|
||||||
|
organization: Default
|
||||||
|
notification_type: webhook
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Add email notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification3
|
||||||
|
organization: Default
|
||||||
|
notification_type: email
|
||||||
|
username: user
|
||||||
|
password: s3cr3t
|
||||||
|
sender: tower@example.com
|
||||||
|
recipients:
|
||||||
|
- user1@example.com
|
||||||
|
host: smtp.example.com
|
||||||
|
port: 25
|
||||||
|
use_tls: false
|
||||||
|
use_ssl: false
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Delete email notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification3
|
||||||
|
organization: Default
|
||||||
|
notification_type: email
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Add twilio notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification4
|
||||||
|
organization: Default
|
||||||
|
notification_type: twilio
|
||||||
|
account_token: a_token
|
||||||
|
account_sid: a_sid
|
||||||
|
from_number: '+15551112222'
|
||||||
|
to_numbers:
|
||||||
|
- '+15553334444'
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Delete twilio notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification4
|
||||||
|
organization: Default
|
||||||
|
notification_type: twilio
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Add PagerDuty notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification5
|
||||||
|
organization: Default
|
||||||
|
notification_type: pagerduty
|
||||||
|
token: a_token
|
||||||
|
subdomain: sub
|
||||||
|
client_name: client
|
||||||
|
service_key: a_key
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Delete PagerDuty notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification5
|
||||||
|
organization: Default
|
||||||
|
notification_type: pagerduty
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Add HipChat notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification6
|
||||||
|
organization: Default
|
||||||
|
notification_type: hipchat
|
||||||
|
token: a_token
|
||||||
|
message_from: user1
|
||||||
|
api_url: https://hipchat.example.com
|
||||||
|
color: red
|
||||||
|
rooms:
|
||||||
|
- room-A
|
||||||
|
notify: true
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Delete HipChat notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification6
|
||||||
|
organization: Default
|
||||||
|
notification_type: hipchat
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Add IRC notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification7
|
||||||
|
organization: Default
|
||||||
|
notification_type: irc
|
||||||
|
nickname: tower
|
||||||
|
password: s3cr3t
|
||||||
|
targets:
|
||||||
|
- user1
|
||||||
|
port: 8080
|
||||||
|
server: irc.example.com
|
||||||
|
use_ssl: false
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Delete IRC notification
|
||||||
|
tower_notification:
|
||||||
|
name: notification7
|
||||||
|
organization: Default
|
||||||
|
notification_type: irc
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
---
|
||||||
|
- name: Generate an org name
|
||||||
|
set_fact:
|
||||||
|
org_name: "org-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||||
|
|
||||||
|
- name: Make sure {{ org_name }} is not there
|
||||||
|
tower_organization:
|
||||||
|
name: "{{ org_name }}"
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: "Create a new organization"
|
||||||
|
tower_organization:
|
||||||
|
name: "{{ org_name }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that: "result is changed"
|
||||||
|
|
||||||
|
- name: "Make sure making the same org is not a change"
|
||||||
|
tower_organization:
|
||||||
|
name: "{{ org_name }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is not changed"
|
||||||
|
|
||||||
|
- name: "Try adding a bad custom_virtualenv"
|
||||||
|
tower_organization:
|
||||||
|
name: "{{ org_name }}"
|
||||||
|
custom_virtualenv: "/does/not/exit"
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is failed"
|
||||||
|
|
||||||
|
- name: "Pass in all parameters"
|
||||||
|
tower_organization:
|
||||||
|
name: "{{ org_name }}"
|
||||||
|
description: "A description"
|
||||||
|
custom_virtualenv: ""
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: "Change the description"
|
||||||
|
tower_organization:
|
||||||
|
name: "{{ org_name }}"
|
||||||
|
description: "A new description"
|
||||||
|
custom_virtualenv: ""
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: "Remove the organization"
|
||||||
|
tower_organization:
|
||||||
|
name: "{{ org_name }}"
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: "Remove a missing organization"
|
||||||
|
tower_organization:
|
||||||
|
name: "{{ org_name }}"
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is not changed"
|
||||||
|
|
||||||
|
# Test behaviour common to all tower modules
|
||||||
|
- name: Check that SSL is available
|
||||||
|
tower_organization:
|
||||||
|
name: Default
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that: result is not changed
|
||||||
|
|
||||||
|
- name: Check that SSL is available and verify_ssl is enabled (task must fail)
|
||||||
|
tower_organization:
|
||||||
|
name: Default
|
||||||
|
validate_certs: true
|
||||||
|
environment:
|
||||||
|
TOWER_CERTIFICATE: /dev/null # force check failure
|
||||||
|
ignore_errors: true
|
||||||
|
register: check_ssl_is_used
|
||||||
|
|
||||||
|
- name: Check that connection failed
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- check_ssl_is_used is failed
|
||||||
|
|
||||||
|
- name: Check that verify_ssl is disabled (task must not fail)
|
||||||
|
tower_organization:
|
||||||
|
name: Default
|
||||||
|
validate_certs: false
|
||||||
|
environment:
|
||||||
|
TOWER_CERTIFICATE: /dev/null # should not fail because verify_ssl is disabled
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
---
|
||||||
|
- name: Delete old git project from any previous test runs
|
||||||
|
tower_project:
|
||||||
|
name: "git project"
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Create an SCM Credential
|
||||||
|
tower_credential:
|
||||||
|
name: SCM Credential for Project
|
||||||
|
organization: Default
|
||||||
|
kind: scm
|
||||||
|
|
||||||
|
- name: Create a git project without credentials without waiting
|
||||||
|
tower_project:
|
||||||
|
name: "git project"
|
||||||
|
organization: Default
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/test-playbooks
|
||||||
|
wait: false
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is changed
|
||||||
|
|
||||||
|
- name: Recreate the project to validate not changed
|
||||||
|
tower_project:
|
||||||
|
name: "git project"
|
||||||
|
organization: Default
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/test-playbooks
|
||||||
|
wait: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- result is not changed
|
||||||
|
|
||||||
|
- name: Create organizations
|
||||||
|
tower_organization:
|
||||||
|
name: TestOrg
|
||||||
|
|
||||||
|
- name: Create credential
|
||||||
|
tower_credential:
|
||||||
|
kind: scm
|
||||||
|
name: TestCred
|
||||||
|
organization: TestOrg
|
||||||
|
|
||||||
|
register: new_credentials
|
||||||
|
|
||||||
|
- name: Generate random project name appender
|
||||||
|
set_fact:
|
||||||
|
project_name_rand: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||||
|
|
||||||
|
- name: Create a new test project in check_mode
|
||||||
|
tower_project:
|
||||||
|
name: "TestProject {{ project_name_rand }}"
|
||||||
|
organization: TestOrg
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/test-playbooks
|
||||||
|
scm_credential: TestCred
|
||||||
|
check_mode: true
|
||||||
|
|
||||||
|
- name: Create a new test project
|
||||||
|
tower_project:
|
||||||
|
name: "TestProject {{ project_name_rand }}"
|
||||||
|
organization: TestOrg
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/test-playbooks
|
||||||
|
scm_credential: TestCred
|
||||||
|
register: result
|
||||||
|
|
||||||
|
# If this fails it may be because the check_mode task actually already created
|
||||||
|
# the project, or it could be because the module actually failed somehow
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg when given non-existing org as param
|
||||||
|
tower_project:
|
||||||
|
name: "TestProject {{ project_name_rand }}"
|
||||||
|
organization: Non Existing Org
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/test-playbooks
|
||||||
|
scm_credential: TestCred
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg == 'The organizations Non Existing Org was not found on the Tower server' or
|
||||||
|
result.msg == 'Failed to update project, organization not found: Non Existing Org'"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg when given non-existing credential as param
|
||||||
|
tower_project:
|
||||||
|
name: "TestProject {{ project_name_rand }}"
|
||||||
|
organization: TestOrg
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/test-playbooks
|
||||||
|
scm_credential: Non Existing Credential
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='The credentials Non Existing Credential was not found on the Tower server' or
|
||||||
|
result.msg =='Failed to update project, credential not found: Non Existing Credential'"
|
||||||
|
|
||||||
|
- name: Delete the test project
|
||||||
|
tower_project:
|
||||||
|
name: "TestProject {{ project_name_rand }}"
|
||||||
|
organization: TestOrg
|
||||||
|
state: absent
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
- name: get tower host variable
|
||||||
|
shell: tower-cli config host | cut -d ' ' -f2
|
||||||
|
register: host
|
||||||
|
|
||||||
|
- name: get tower username variable
|
||||||
|
shell: tower-cli config username | cut -d ' ' -f2
|
||||||
|
register: username
|
||||||
|
|
||||||
|
- name: get tower password variable
|
||||||
|
shell: tower-cli config password | cut -d ' ' -f2
|
||||||
|
register: password
|
||||||
|
|
||||||
|
- name: Fetch project_base_dir
|
||||||
|
uri:
|
||||||
|
url: "{{ host.stdout }}/api/v2/config/"
|
||||||
|
user: "{{ username.stdout }}"
|
||||||
|
password: "{{ password.stdout }}"
|
||||||
|
validate_certs: false
|
||||||
|
return_content: true
|
||||||
|
force_basic_auth: true
|
||||||
|
register: awx_config
|
||||||
|
|
||||||
|
- tower_inventory:
|
||||||
|
name: localhost
|
||||||
|
organization: Default
|
||||||
|
|
||||||
|
- tower_host:
|
||||||
|
name: localhost
|
||||||
|
inventory: localhost
|
||||||
|
variables:
|
||||||
|
ansible_connection: local
|
||||||
|
|
||||||
|
- name: create an unused SSH / Machine credential
|
||||||
|
tower_credential:
|
||||||
|
name: dummy
|
||||||
|
kind: ssh
|
||||||
|
ssh_key_data: |
|
||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEIIUl6R1xgzR6siIUArz4XBPtGZ09aetma2eWf1v3uYymoAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAENJNjgeZDAh/+BY860s0yqrLDprXJflY0GvHIr7lX3ieCtrzOMCVU
|
||||||
|
QWzw35pc5tvuP34SSi0ZE1E+7cVMDDOF3w==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
|
organization: Default
|
||||||
|
|
||||||
|
- name: Disable bubblewrap
|
||||||
|
command: tower-cli setting modify AWX_PROOT_ENABLED false
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: Create a directory for manual project
|
||||||
|
vars:
|
||||||
|
project_base_dir: "{{ awx_config.json.project_base_dir }}"
|
||||||
|
command: tower-cli ad_hoc launch --wait --inventory localhost
|
||||||
|
--credential dummy --module-name command
|
||||||
|
--module-args "mkdir -p {{ project_base_dir }}/{{ project_dir_name }}"
|
||||||
|
always:
|
||||||
|
- name: enable bubblewrap
|
||||||
|
command: tower-cli setting modify AWX_PROOT_ENABLED true
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
- name: generate random string for project
|
||||||
|
set_fact:
|
||||||
|
rand_string: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
|
||||||
|
- name: Generate manual project dir name
|
||||||
|
set_fact:
|
||||||
|
project_name: "manual project {{ rand_string }}"
|
||||||
|
|
||||||
|
- name: Generate manual project dir name
|
||||||
|
set_fact:
|
||||||
|
project_dir_name: "proj_{{ rand_string }}"
|
||||||
|
|
||||||
|
- name: create a project directory for manual project
|
||||||
|
import_tasks: create_project_dir.yml
|
||||||
|
|
||||||
|
- name: Create a manual project
|
||||||
|
tower_project:
|
||||||
|
name: "{{ project_name }}"
|
||||||
|
organization: Default
|
||||||
|
scm_type: manual
|
||||||
|
local_path: "{{ project_dir_name }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a manual project
|
||||||
|
tower_project:
|
||||||
|
name: "{{ project_name }}"
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
- name: Export all Tower assets
|
||||||
|
tower_receive:
|
||||||
|
all: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is successful"
|
||||||
|
|
||||||
|
- name: Extract names from output
|
||||||
|
set_fact:
|
||||||
|
object_names: "{{ result.assets | map(attribute='name') | list }}"
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is successful"
|
||||||
|
- "'Default' in object_names"
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
---
|
||||||
|
- name: Create a User
|
||||||
|
tower_user:
|
||||||
|
first_name: Joe
|
||||||
|
last_name: User
|
||||||
|
username: joe
|
||||||
|
password: "{{ 65535 | random | to_uuid }}"
|
||||||
|
email: joe@example.org
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Add Joe to the update role of the default Project
|
||||||
|
tower_role:
|
||||||
|
user: joe
|
||||||
|
role: update
|
||||||
|
project: Demo Project
|
||||||
|
state: "{{ item }}"
|
||||||
|
register: result
|
||||||
|
with_items:
|
||||||
|
- "present"
|
||||||
|
- "absent"
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a User
|
||||||
|
tower_user:
|
||||||
|
username: joe
|
||||||
|
email: joe@example.org
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
- name: Test no parameters
|
||||||
|
tower_send:
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is failed"
|
||||||
|
|
||||||
|
- name: Create user json
|
||||||
|
set_fact:
|
||||||
|
user:
|
||||||
|
- username: "jowestco"
|
||||||
|
first_name: "John"
|
||||||
|
last_name: "Westcott"
|
||||||
|
asset_type: "user"
|
||||||
|
email: "john.westcott.iv@redhat.com"
|
||||||
|
|
||||||
|
- name: Test a new import of asset
|
||||||
|
tower_send:
|
||||||
|
assets: "{{ user | to_json() }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Test an existing import of asset
|
||||||
|
tower_send:
|
||||||
|
assets: "{{ user | to_json() }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is successful"
|
||||||
|
- "result is not changed"
|
||||||
|
|
||||||
|
- name: Change an existing asset
|
||||||
|
tower_send:
|
||||||
|
assets: "{{ user | combine({'last_name': 'Westcott IV'}) | to_json() }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Ensure the organization is not created
|
||||||
|
tower_organization:
|
||||||
|
name: "Red Hat"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Create organization json
|
||||||
|
set_fact:
|
||||||
|
organization:
|
||||||
|
- asset_type: organization
|
||||||
|
name: "Red Hat"
|
||||||
|
|
||||||
|
- name: Create temp file
|
||||||
|
tempfile:
|
||||||
|
state: file
|
||||||
|
register: my_temp_file
|
||||||
|
|
||||||
|
- name: Drop down a file to import
|
||||||
|
copy:
|
||||||
|
dest: "{{ my_temp_file.path }}"
|
||||||
|
content: "{{ organization | to_nice_json() }}"
|
||||||
|
|
||||||
|
- name: Create org via files
|
||||||
|
tower_send:
|
||||||
|
files: "{{ my_temp_file.path }}"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Remove Temp File
|
||||||
|
file:
|
||||||
|
path: "{{ my_temp_file.path }}"
|
||||||
|
state: absent
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
---
|
||||||
|
- name: Set the value of AWX_PROOT_SHOW_PATHS to a baseline
|
||||||
|
tower_settings:
|
||||||
|
name: AWX_PROOT_SHOW_PATHS
|
||||||
|
value: '["/var/lib/awx/projects/"]'
|
||||||
|
|
||||||
|
- name: Set the value of AWX_PROOT_SHOW_PATHS to get an error back from Tower
|
||||||
|
tower_settings:
|
||||||
|
settings:
|
||||||
|
AWX_PROOT_SHOW_PATHS:
|
||||||
|
'not': 'a valid'
|
||||||
|
'tower': 'setting'
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is failed"
|
||||||
|
|
||||||
|
- name: Set the value of AWX_PROOT_SHOW_PATHS
|
||||||
|
tower_settings:
|
||||||
|
name: AWX_PROOT_SHOW_PATHS
|
||||||
|
value: '["/var/lib/awx/projects/", "/tmp"]'
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Attempt to set the value of AWX_PROOT_BASE_PATH to what it already is
|
||||||
|
tower_settings:
|
||||||
|
name: AWX_PROOT_BASE_PATH
|
||||||
|
value: /tmp
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ result }}"
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is not changed"
|
||||||
|
|
||||||
|
- name: Apply a single setting via settings
|
||||||
|
tower_settings:
|
||||||
|
name: AWX_PROOT_SHOW_PATHS
|
||||||
|
value: '["/var/lib/awx/projects/", "/var/tmp"]'
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Apply multiple setting via settings with no change
|
||||||
|
tower_settings:
|
||||||
|
settings:
|
||||||
|
AWX_PROOT_BASE_PATH: /tmp
|
||||||
|
AWX_PROOT_SHOW_PATHS: ["/var/lib/awx/projects/", "/var/tmp"]
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- debug:
|
||||||
|
msg: "{{ result }}"
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is not changed"
|
||||||
|
|
||||||
|
- name: Apply multiple setting via settings with change
|
||||||
|
tower_settings:
|
||||||
|
settings:
|
||||||
|
AWX_PROOT_BASE_PATH: /tmp
|
||||||
|
AWX_PROOT_SHOW_PATHS: []
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
---
|
||||||
|
- name: Attempt to add a Tower team to a non-existant Organization
|
||||||
|
tower_team:
|
||||||
|
name: Test Team
|
||||||
|
organization: Missing Organization
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Assert a meaningful error was provided for the failed Tower team creation
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- result is failed
|
||||||
|
- "result.msg =='Failed to update team, organization not found: The requested object could not be found.' or
|
||||||
|
result.msg =='The organizations Missing Organization was not found on the Tower server'"
|
||||||
|
|
||||||
|
- name: Create a Tower team
|
||||||
|
tower_team:
|
||||||
|
name: Test Team
|
||||||
|
organization: Default
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Tower team
|
||||||
|
tower_team:
|
||||||
|
name: Test Team
|
||||||
|
organization: Default
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_team:
|
||||||
|
name: Test Team
|
||||||
|
organization: Non Existing Org
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='Failed to update team, organization not found: The requested object could not be found.' or
|
||||||
|
result.msg =='The organizations Non Existing Org was not found on the Tower server'"
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
---
|
||||||
|
- name: Create a User
|
||||||
|
tower_user:
|
||||||
|
first_name: Joe
|
||||||
|
last_name: User
|
||||||
|
username: joe
|
||||||
|
password: "{{ 65535 | random | to_uuid }}"
|
||||||
|
email: joe@example.org
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a User
|
||||||
|
tower_user:
|
||||||
|
username: joe
|
||||||
|
email: joe@example.org
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create an Auditor
|
||||||
|
tower_user:
|
||||||
|
first_name: Joe
|
||||||
|
last_name: Auditor
|
||||||
|
username: joe
|
||||||
|
password: "{{ 65535 | random | to_uuid }}"
|
||||||
|
email: joe@example.org
|
||||||
|
state: present
|
||||||
|
auditor: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete an Auditor
|
||||||
|
tower_user:
|
||||||
|
username: joe
|
||||||
|
email: joe@example.org
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Create a Superuser
|
||||||
|
tower_user:
|
||||||
|
first_name: Joe
|
||||||
|
last_name: Super
|
||||||
|
username: joe
|
||||||
|
password: "{{ 65535 | random | to_uuid }}"
|
||||||
|
email: joe@example.org
|
||||||
|
state: present
|
||||||
|
superuser: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a Superuser
|
||||||
|
tower_user:
|
||||||
|
username: joe
|
||||||
|
email: joe@example.org
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Test tower SSL parameter
|
||||||
|
tower_user:
|
||||||
|
first_name: Joe
|
||||||
|
last_name: User
|
||||||
|
username: joe
|
||||||
|
password: "{{ 65535 | random | to_uuid }}"
|
||||||
|
email: joe@example.org
|
||||||
|
state: present
|
||||||
|
validate_certs: true
|
||||||
|
tower_host: http://foo.invalid
|
||||||
|
ignore_errors: true
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "'Unable to resolve tower_host' in result.msg or
|
||||||
|
'Can not verify ssl with non-https protocol' in result.exception"
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
---
|
||||||
|
- name: Create an SCM Credential
|
||||||
|
tower_credential:
|
||||||
|
name: SCM Credential for JT
|
||||||
|
organization: Default
|
||||||
|
kind: scm
|
||||||
|
|
||||||
|
- name: Create a Demo Project
|
||||||
|
tower_project:
|
||||||
|
name: Job Template Test Project
|
||||||
|
organization: Default
|
||||||
|
state: present
|
||||||
|
scm_type: git
|
||||||
|
scm_url: https://github.com/ansible/ansible-tower-samples.git
|
||||||
|
scm_credential: SCM Credential for JT
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: Create a Job Template
|
||||||
|
tower_job_template:
|
||||||
|
name: my-job-1
|
||||||
|
project: Job Template Test Project
|
||||||
|
inventory: Demo Inventory
|
||||||
|
playbook: hello_world.yml
|
||||||
|
credential: Demo Credential
|
||||||
|
job_type: run
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create a second Job Template
|
||||||
|
tower_job_template:
|
||||||
|
name: my-job-2
|
||||||
|
project: Job Template Test Project
|
||||||
|
inventory: Demo Inventory
|
||||||
|
playbook: hello_world.yml
|
||||||
|
credential: Demo Credential
|
||||||
|
job_type: run
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add a Survey to second Job Template
|
||||||
|
tower_job_template:
|
||||||
|
name: my-job-2
|
||||||
|
project: Job Template Test Project
|
||||||
|
inventory: Demo Inventory
|
||||||
|
playbook: hello_world.yml
|
||||||
|
credential: Demo Credential
|
||||||
|
job_type: run
|
||||||
|
state: present
|
||||||
|
survey_enabled: true
|
||||||
|
survey_spec: '{"spec": [{"index": 0, "question_name": "my question?", "default": "mydef", "variable": "myvar", "type": "text", "required": false}], "description": "test", "name": "test"}'
|
||||||
|
|
||||||
|
|
||||||
|
- name: Create a workflow job template
|
||||||
|
tower_workflow_template:
|
||||||
|
name: my-workflow
|
||||||
|
schema: '[{"success": [{"job_template": "my-job-1"}], "job_template": "my-job-2"}]'
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Delete a workflow job template
|
||||||
|
tower_workflow_template:
|
||||||
|
name: my-workflow
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result is changed"
|
||||||
|
|
||||||
|
- name: Check module fails with correct msg
|
||||||
|
tower_workflow_template:
|
||||||
|
name: my-workflow
|
||||||
|
organization: Non Existing Organization
|
||||||
|
schema: '[{"success": [{"job_template": "my-job-1"}], "job_template": "my-job-2"}]'
|
||||||
|
register: result
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- "result.msg =='Failed to update organization source,organization not found: The requested object could not be found.'"
|
||||||
Reference in New Issue
Block a user