Skip to content

Commit

Permalink
Added support to collection for named urls
Browse files Browse the repository at this point in the history
  • Loading branch information
john-westcott-iv committed Jul 6, 2023
1 parent 3624fe2 commit caca1b3
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 24 deletions.
69 changes: 45 additions & 24 deletions awx_collection/plugins/module_utils/controller_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from ansible.module_utils.six.moves import StringIO
from ansible.module_utils.six.moves.urllib.error import HTTPError
from ansible.module_utils.six.moves.http_cookiejar import CookieJar
from ansible.module_utils.six.moves.urllib.parse import urlparse, urlencode
from ansible.module_utils.six.moves.urllib.parse import urlparse, urlencode, quote
from ansible.module_utils.six.moves.configparser import ConfigParser, NoOptionError
from socket import getaddrinfo, IPPROTO_TCP
import time
Expand Down Expand Up @@ -381,29 +381,51 @@ def get_all_endpoint(self, endpoint, *args, **kwargs):

def get_one(self, endpoint, name_or_id=None, allow_none=True, check_exists=False, **kwargs):
new_kwargs = kwargs.copy()
if name_or_id:
name_field = self.get_name_field_from_endpoint(endpoint)
new_data = kwargs.get('data', {}).copy()
if name_field in new_data:
self.fail_json(msg="You can't specify the field {0} in your search data if using the name_or_id field".format(name_field))
response = None

try:
new_data['or__id'] = int(name_or_id)
new_data['or__{0}'.format(name_field)] = name_or_id
except ValueError:
# If we get a value error, then we didn't have an integer so we can just pass and fall down to the fail
new_data[name_field] = name_or_id
new_kwargs['data'] = new_data

response = self.get_endpoint(endpoint, **new_kwargs)
if response['status_code'] != 200:
fail_msg = "Got a {0} response when trying to get one from {1}".format(response['status_code'], endpoint)
if 'detail' in response.get('json', {}):
fail_msg += ', detail: {0}'.format(response['json']['detail'])
self.fail_json(msg=fail_msg)

if 'count' not in response['json'] or 'results' not in response['json']:
self.fail_json(msg="The endpoint did not provide count and results")
# A named URL is pretty unique so if we have a ++ in the name then lets start by looking for that
# This also needs to go first because if there was data passed in kwargs and we do the next lookup first there may be results
if name_or_id is not None and '++' in name_or_id:
# Maybe someone gave us a named URL so lets see if we get anything from that.
url_quoted_name = quote(name_or_id, safe="+")
named_endpoint = '{0}/{1)/'.format(endpoint, url_quoted_name)
named_response = self.get_endpoint(named_endpoint)

if named_response['status_code'] == 200 and 'json' in named_response:
# We found a named item but we expect to deal with a list view so mock that up
response = {
'json': {
'count': 1,
'results': [named_response['json']],
}
}

# Since we didn't have a named URL, lets try and find it with a general search
if response is None:
if name_or_id:
name_field = self.get_name_field_from_endpoint(endpoint)
new_data = kwargs.get('data', {}).copy()
if name_field in new_data:
self.fail_json(msg="You can't specify the field {0} in your search data if using the name_or_id field".format(name_field))

try:
new_data['or__id'] = int(name_or_id)
new_data['or__{0}'.format(name_field)] = name_or_id
except ValueError:
# If we get a value error, then we didn't have an integer so we can just pass and fall down to the fail
new_data[name_field] = name_or_id
new_kwargs['data'] = new_data

response = self.get_endpoint(endpoint, **new_kwargs)

if response['status_code'] != 200:
fail_msg = "Got a {0} response when trying to get one from {1}".format(response['status_code'], endpoint)
if 'detail' in response.get('json', {}):
fail_msg += ', detail: {0}'.format(response['json']['detail'])
self.fail_json(msg=fail_msg)

if 'count' not in response['json'] or 'results' not in response['json']:
self.fail_json(msg="The endpoint did not provide count and results")

if response['json']['count'] == 0:
if allow_none:
Expand All @@ -421,7 +443,6 @@ def get_one(self, endpoint, name_or_id=None, allow_none=True, check_exists=False
self.fail_wanted_one(response, endpoint, new_kwargs.get('data'))

if check_exists:
name_field = self.get_name_field_from_endpoint(endpoint)
self.json_output['id'] = response['json']['results'][0]['id']
self.exit_json(**self.json_output)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
- name: Generate a random string for test
set_fact:
test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}"
when: test_id is not defined

- include_tasks:
file: test_named_reference.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
- block:
- name: generate random string for project
set_fact:
org_name: "AWX-Collection-tests-organization-org-{{ test_id }}"
cred: "AWX-Collection-tests-job_template-cred-{{ test_id }}"
inv: "AWX-Collection-tests-job_template-inv-{{ test_id }}"
proj: "AWX-Collection-tests-job_template-proj-{{ test_id }}"
jt: "AWX-Collection-tests-job_template-jt-{{ test_id }}"

- name: "Create a new organization"
organization:
name: "{{ org_name }}"
galaxy_credentials:
- Ansible Galaxy

- name: Create an inventory
inventory:
name: "{{ inv }}"
organization: "{{ org_name }}"

- name: Create a Demo Project
project:
name: "{{ proj }}"
organization: "{{ org_name }}"
state: present
scm_type: git
scm_url: https://github.com/ansible/ansible-tower-samples.git

- name: Create Credential
credential:
name: "{{ cred }}"
organization: "{{ org_name }}"
credential_type: Machine

- name: Create Job Template
job_template:
name: "{{ jt }}"
project: "{{ proj }}++{{ org_name }}"
inventory: "{{ inv }}++{{ org_name }}"
playbook: hello_world.yml
credentials:
- "{{ cred }}++Machine+ssh++"
job_type: run
state: present

always:
- name: Delete the Job Template
job_template:
name: "{{ jt }}"
state: absent

- name: Delete the Demo Project
project:
name: "{{ proj }}++{{ org_name }}"
state: absent

- name: Delete Credential
credential:
name: "{{ cred }}++Machine+ssh++{{ org_name }}"
credential_type: Machine
state: absent

- name: Delete the inventory
inventory:
name: "{{ inv }}++{{ org_name }}"
organization: "{{ org_name }}"
state: absent

- name: Remove the organization
organization:
name: "{{ org_name }}"
state: absent

0 comments on commit caca1b3

Please sign in to comment.