diff --git a/awx_collection/plugins/modules/tower_inventory.py b/awx_collection/plugins/modules/tower_inventory.py index 7f03645e01..20093038c7 100644 --- a/awx_collection/plugins/modules/tower_inventory.py +++ b/awx_collection/plugins/modules/tower_inventory.py @@ -48,7 +48,11 @@ options: type: str host_filter: description: - - The host_filter field. Only useful when C(kind=smart). + - The host_filter field. Only useful when C(kind=smart). + type: str + insights_credential: + description: + - Credentials to be used by hosts belonging to this inventory when accessing Red Hat Insights API. type: str state: description: @@ -84,6 +88,7 @@ def main(): variables=dict(type='dict'), kind=dict(choices=['', 'smart'], default=''), host_filter=dict(), + insights_credential=dict(), state=dict(choices=['present', 'absent'], default='present'), ) @@ -98,6 +103,7 @@ def main(): state = module.params.get('state') kind = module.params.get('kind') host_filter = module.params.get('host_filter') + insights_credential = module.params.get('insights_credential') # Attempt to look up the related items the user specified (these will fail the module if not found) org_id = module.resolve_name_to_id('organizations', organization) @@ -125,6 +131,8 @@ def main(): inventory_fields['description'] = description if variables is not None: inventory_fields['variables'] = json.dumps(variables) + if insights_credential is not None: + inventory_fields['insights_credential'] = module.resolve_name_to_id('credentials', insights_credential) # We need to perform a check to make sure you are not trying to convert a regular inventory into a smart one. if inventory and inventory['kind'] == '' and inventory_fields['kind'] == 'smart': diff --git a/awx_collection/test/awx/test_inventory.py b/awx_collection/test/awx/test_inventory.py index 2ba52ac0a2..f4b3ad54c5 100644 --- a/awx_collection/test/awx/test_inventory.py +++ b/awx_collection/test/awx/test_inventory.py @@ -3,20 +3,25 @@ __metaclass__ = type import pytest -from awx.main.models import Inventory - +from awx.main.models import Inventory, Credential +from awx.main.tests.functional.conftest import insights_credential, credentialtype_insights @pytest.mark.django_db -def test_inventory_create(run_module, admin_user, organization): +def test_inventory_create(run_module, admin_user, organization, insights_credential): + # Create an insights credential + result = run_module('tower_inventory', { 'name': 'foo-inventory', 'organization': organization.name, 'variables': {'foo': 'bar', 'another-foo': {'barz': 'bar2'}}, + 'insights_credential': insights_credential.name, 'state': 'present' }, admin_user) + assert not result.get('failed', False), result.get('msg', result) inv = Inventory.objects.get(name='foo-inventory') assert inv.variables == '{"foo": "bar", "another-foo": {"barz": "bar2"}}' + assert inv.insights_credential.name == insights_credential.name result.pop('module_args', None) result.pop('invocation', None) @@ -28,7 +33,6 @@ def test_inventory_create(run_module, admin_user, organization): assert inv.organization_id == organization.id - @pytest.mark.django_db def test_invalid_smart_inventory_create(run_module, admin_user, organization): result = run_module('tower_inventory', { diff --git a/awx_collection/tests/integration/targets/tower_inventory/tasks/main.yml b/awx_collection/tests/integration/targets/tower_inventory/tasks/main.yml index a4e3424ea6..f8aa76fb36 100644 --- a/awx_collection/tests/integration/targets/tower_inventory/tasks/main.yml +++ b/awx_collection/tests/integration/targets/tower_inventory/tasks/main.yml @@ -1,101 +1,142 @@ --- +- name: Generate a test ID + set_fact: + test_id: "{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" + - name: Generate names set_fact: - inv_name1: "AWX-Collection-tests-tower_inventory-inv1-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" - inv_name2: "AWX-Collection-tests-tower_inventory-inv2-{{ lookup('password', '/dev/null chars=ascii_letters length=16') }}" + inv_name1: "AWX-Collection-tests-tower_inventory-inv1-{{ test_id }}" + inv_name2: "AWX-Collection-tests-tower_inventory-inv2-{{ test_id }}" + cred_name1: "AWX-Collection-tests-tower_inventory-cred1-{{ test_id }}" -- name: Create an Inventory - tower_inventory: - name: "{{ inv_name1 }}" - organization: Default - state: present - register: result +- block: + - name: Create an Insights Credential + tower_credential: + name: "{{ cred_name1 }}" + organization: Default + kind: insights + inputs: + username: joe + password: secret + state: present + register: result -- assert: - that: - - "result is changed" + - assert: + that: + - "result is changed" -- name: Test Inventory module idempotency - tower_inventory: - name: "{{ inv_name1 }}" - organization: Default - state: present - register: result + - name: Create an Inventory + tower_inventory: + name: "{{ inv_name1 }}" + organization: Default + insights_credential: "{{ cred_name1 }}" + state: present + register: result -- assert: - that: - - "result is not changed" + - assert: + that: + - "result is changed" -- name: Fail Change Regular to Smart - tower_inventory: - name: "{{ inv_name1 }}" - organization: Default - kind: smart - register: result - ignore_errors: true + - meta: end_play -- assert: - that: - - "result is failed" + - name: Test Inventory module idempotency + tower_inventory: + name: "{{ inv_name1 }}" + organization: Default + insights_credential: "{{ cred_name1 }}" + state: present + register: result -- name: Create a smart inventory - tower_inventory: - name: "{{ inv_name2 }}" - organization: Default - kind: smart - host_filter: name=foo - register: result + - assert: + that: + - "result is not changed" -- assert: - that: - - "result is changed" + - name: Fail Change Regular to Smart + tower_inventory: + name: "{{ inv_name1 }}" + organization: Default + kind: smart + register: result + ignore_errors: true -- name: Delete a smart inventory - tower_inventory: - name: "{{ inv_name2 }}" - organization: Default - kind: smart - host_filter: name=foo - state: absent - register: result + - assert: + that: + - "result is failed" -- assert: - that: - - "result is changed" + - name: Create a smart inventory + tower_inventory: + name: "{{ inv_name2 }}" + organization: Default + kind: smart + host_filter: name=foo + register: result -- name: Delete an Inventory - tower_inventory: - name: "{{ inv_name1 }}" - organization: Default - state: absent - register: result + - assert: + that: + - "result is changed" -- assert: - that: - - "result is changed" + - name: Delete a smart inventory + tower_inventory: + name: "{{ inv_name2 }}" + organization: Default + kind: smart + host_filter: name=foo + state: absent + register: result -- name: Delete a Non-Existent Inventory - tower_inventory: - name: "{{ inv_name1 }}" - organization: Default - state: absent - register: result + - assert: + that: + - "result is changed" -- assert: - that: - - "result is not changed" + - name: Delete an Inventory + tower_inventory: + name: "{{ inv_name1 }}" + organization: Default + state: absent + register: result -- 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 changed" -- 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'" + - name: Delete a Non-Existent Inventory + tower_inventory: + name: "{{ inv_name1 }}" + 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'" + always: + - name: Delete Inventories + tower_inventory: + name: "{{ item }}" + organization: Default + state: absent + loop: + - "{{ inv_name1 }}" + - "{{ inv_name2 }}" + + - name: Delete Insights Credential + tower_credential: + name: "{{ cred_name1 }}" + organization: "Default" + kind: insights + state: absent