Make tower_inventory_source org optional, add tests

This commit is contained in:
AlanCoding
2019-10-31 09:24:41 -04:00
parent a2fee252f9
commit 24eae09ed9
3 changed files with 96 additions and 16 deletions

View File

@@ -40,7 +40,7 @@ options:
organization: organization:
description: description:
- Organization the inventory belongs to. - Organization the inventory belongs to.
reguired: True type: str
source: source:
description: description:
- Types of inventory source. - Types of inventory source.
@@ -229,7 +229,7 @@ def main():
overwrite_vars=dict(type='bool', required=False), overwrite_vars=dict(type='bool', required=False),
update_on_launch=dict(type='bool', required=False), update_on_launch=dict(type='bool', required=False),
update_cache_timeout=dict(type='int', required=False), update_cache_timeout=dict(type='int', required=False),
organization=dict(required=True), organization=dict(type='str'),
state=dict(choices=['present', 'absent'], default='present'), state=dict(choices=['present', 'absent'], default='present'),
) )
@@ -255,21 +255,25 @@ def main():
if module.params.get('description'): if module.params.get('description'):
params['description'] = module.params.get('description') params['description'] = module.params.get('description')
try: if organization:
org_res = tower_cli.get_resource('organization') try:
org = org_res.get(name=organization) org_res = tower_cli.get_resource('organization')
except (exc.NotFound) as excinfo: org = org_res.get(name=organization)
module.fail_json( except (exc.NotFound) as excinfo:
msg='Failed to get organization,' module.fail_json(
'organization not found: {0}'.format(excinfo), msg='Failed to get organization,'
changed=False 'organization not found: {0}'.format(excinfo),
) changed=False
)
org_id = org['id']
else:
org_id = None # interpreted as not provided
if module.params.get('credential'): if module.params.get('credential'):
credential_res = tower_cli.get_resource('credential') credential_res = tower_cli.get_resource('credential')
try: try:
credential = credential_res.get( credential = credential_res.get(
name=module.params.get('credential'), organization=org['id']) name=module.params.get('credential'), organization=org_id)
params['credential'] = credential['id'] params['credential'] = credential['id']
except (exc.NotFound) as excinfo: except (exc.NotFound) as excinfo:
module.fail_json( module.fail_json(
@@ -282,7 +286,7 @@ def main():
source_project_res = tower_cli.get_resource('project') source_project_res = tower_cli.get_resource('project')
try: try:
source_project = source_project_res.get( source_project = source_project_res.get(
name=module.params.get('source_project'), organization=org['id']) name=module.params.get('source_project'), organization=org_id)
params['source_project'] = source_project['id'] params['source_project'] = source_project['id']
except (exc.NotFound) as excinfo: except (exc.NotFound) as excinfo:
module.fail_json( module.fail_json(
@@ -295,7 +299,7 @@ def main():
source_script_res = tower_cli.get_resource('inventory_script') source_script_res = tower_cli.get_resource('inventory_script')
try: try:
script = source_script_res.get( script = source_script_res.get(
name=module.params.get('source_script'), organization=org['id']) name=module.params.get('source_script'), organization=org_id)
params['source_script'] = script['id'] params['source_script'] = script['id']
except (exc.NotFound) as excinfo: except (exc.NotFound) as excinfo:
module.fail_json( module.fail_json(
@@ -306,7 +310,7 @@ def main():
try: try:
inventory_res = tower_cli.get_resource('inventory') inventory_res = tower_cli.get_resource('inventory')
params['inventory'] = inventory_res.get(name=inventory, organization=org['id'])['id'] params['inventory'] = inventory_res.get(name=inventory, organization=org_id)['id']
except (exc.NotFound) as excinfo: except (exc.NotFound) as excinfo:
module.fail_json( module.fail_json(
msg='Failed to update inventory source, ' msg='Failed to update inventory source, '

View File

@@ -4,6 +4,7 @@ import datetime
import importlib import importlib
from contextlib import redirect_stdout from contextlib import redirect_stdout
from unittest import mock from unittest import mock
import logging
from requests.models import Response from requests.models import Response
@@ -13,6 +14,9 @@ from awx.main.tests.functional.conftest import _request
from awx.main.models import Organization, Project, Inventory, Credential, CredentialType from awx.main.models import Organization, Project, Inventory, Credential, CredentialType
logger = logging.getLogger('awx.main.tests')
def sanitize_dict(din): def sanitize_dict(din):
'''Sanitize Django response data to purge it of internal types '''Sanitize Django response data to purge it of internal types
so it may be used to cast a requests response object so it may be used to cast a requests response object
@@ -34,13 +38,22 @@ def sanitize_dict(din):
@pytest.fixture @pytest.fixture
def run_module(): def run_module(request):
def rf(module_name, module_params, request_user): def rf(module_name, module_params, request_user):
def new_request(self, method, url, **kwargs): def new_request(self, method, url, **kwargs):
kwargs_copy = kwargs.copy() kwargs_copy = kwargs.copy()
if 'data' in kwargs: if 'data' in kwargs:
kwargs_copy['data'] = json.loads(kwargs['data']) kwargs_copy['data'] = json.loads(kwargs['data'])
if 'params' in kwargs and method == 'GET':
# query params for GET are handled a bit differently by
# tower-cli and python requests as opposed to REST framework APIRequestFactory
kwargs_copy.setdefault('data', {})
if isinstance(kwargs['params'], dict):
kwargs_copy['data'].update(kwargs['params'])
elif isinstance(kwargs['params'], list):
for k, v in kwargs['params']:
kwargs_copy['data'][k] = v
# make request # make request
rf = _request(method.lower()) rf = _request(method.lower())
@@ -53,6 +66,13 @@ def run_module():
sanitize_dict(py_data) sanitize_dict(py_data)
resp._content = bytes(json.dumps(django_response.data), encoding='utf8') resp._content = bytes(json.dumps(django_response.data), encoding='utf8')
resp.status_code = django_response.status_code resp.status_code = django_response.status_code
if request.config.getoption('verbose') > 0:
logger.info('{} {} by {}, code:{}'.format(
method, '/api/' + url.split('/api/')[1],
request_user.username, resp.status_code
))
return resp return resp
stdout_buffer = io.StringIO() stdout_buffer = io.StringIO()

View File

@@ -0,0 +1,56 @@
import pytest
from awx.main.models import Organization, Inventory, InventorySource
@pytest.mark.django_db
def test_create_inventory_source_implied_org(run_module, admin_user):
org = Organization.objects.create(name='test-org')
inv = Inventory.objects.create(name='test-inv', organization=org)
result = run_module('tower_inventory_source', dict(
name='Test Inventory Source',
inventory='test-inv',
source='ec2',
state='present'
), admin_user)
assert result.pop('changed', None), result
inv_src = InventorySource.objects.get(name='Test Inventory Source')
assert inv_src.inventory == inv
result.pop('invocation')
assert result == {
"inventory_source": "Test Inventory Source",
"state": "present",
"id": inv_src.id,
}
@pytest.mark.django_db
def test_create_inventory_source_multiple_orgs(run_module, admin_user):
org = Organization.objects.create(name='test-org')
inv = Inventory.objects.create(name='test-inv', organization=org)
# make another inventory by same name in another org
org2 = Organization.objects.create(name='test-org-number-two')
Inventory.objects.create(name='test-inv', organization=org2)
result = run_module('tower_inventory_source', dict(
name='Test Inventory Source',
inventory='test-inv',
source='ec2',
organization='test-org',
state='present'
), admin_user)
assert result.pop('changed', None), result
inv_src = InventorySource.objects.get(name='Test Inventory Source')
assert inv_src.inventory == inv
result.pop('invocation')
assert result == {
"inventory_source": "Test Inventory Source",
"state": "present",
"id": inv_src.id,
}