diff --git a/plugins/modules/role_user_assignment.py b/plugins/modules/role_user_assignment.py index c089574c..e00cb1c8 100644 --- a/plugins/modules/role_user_assignment.py +++ b/plugins/modules/role_user_assignment.py @@ -93,6 +93,30 @@ user: bob state: present +- name: Custom organization-scoped role (content_type shared.organization; name can be anything) + ansible.platform.role_user_assignment: + role_definition: MyCustomOrgViewRole + object_ids: + - "Default Organization" + user: bob + state: present + +- name: Custom team-scoped role (content_type shared.team) + ansible.platform.role_user_assignment: + role_definition: MyCustomTeamViewRole + object_ids: + - "42" + user: anna + state: present + +- name: Inventory role by primary key (content_type awx.inventory) when the inventories API is available + ansible.platform.role_user_assignment: + role_definition: Organization Inventory Admin + object_ids: + - "1" + user: bob + state: present + ... ''' @@ -186,16 +210,17 @@ def main(): if user_ansible_id is not None: kwargs['user_ansible_id'] = user_ansible_id - role_map = { - 'Team': 'teams', - 'Organization': 'organizations', - } + raw_content_type = role_definition.get('content_type') or '' + content_suffix = raw_content_type.split('.')[-1] if '.' in raw_content_type else raw_content_type - entity_type = next(( - mapped - for prefix, mapped in role_map.items() - if role_definition_str.startswith(prefix) - ), None) + endpoint_map = { + 'organization': 'organizations', + 'team': 'teams', + 'inventory': 'inventories', + 'credential': 'credentials', + 'project': 'projects' + } + entity_type = endpoint_map.get(content_suffix, f"{content_suffix}s") if content_suffix else None object_param = object_ids or object_id role_args = { diff --git a/tests/integration/targets/role_user_assignments_test/tasks/main.yml b/tests/integration/targets/role_user_assignments_test/tasks/main.yml index 12519883..7ea7bee0 100644 --- a/tests/integration/targets/role_user_assignments_test/tasks/main.yml +++ b/tests/integration/targets/role_user_assignments_test/tasks/main.yml @@ -9,6 +9,8 @@ username: "GW-Collection-Test-RoleUserAssignments-{{ test_id }}" organization_name: "GW-Collection-Test-Organization-{{ test_id }}" name_prefix: "GW-Collection-Test-Team-{{ test_id }}" + custom_role_name: "GW-Custom-RoleUser-{{ test_id }}" + custom_team_role_name: "GW-Custom-RoleUser-Team-{{ test_id }}" - name: Run Tests module_defaults: @@ -223,6 +225,126 @@ that: - team2_admin_role_assignment_check is not changed + - name: Create custom org-scoped role (shared.organization) + ansible.platform.role_definition: + name: "{{ custom_role_name }}" + description: "Custom role for role_user_assignment content_type resolution test (organization)" + content_type: "shared.organization" + permissions: + - "shared.view_organization" + state: present + register: custom_role + + - name: Assert custom org role definition was created + ansible.builtin.assert: + that: + - custom_role is changed + + - name: Assign custom role to user on organization (object_ids by id) + ansible.platform.role_user_assignment: &custom_user_org_assignment + role_definition: "{{ custom_role_name }}" + user: "{{ user4.id }}" + object_ids: + - "{{ org.id }}" + state: present + register: custom_user_role_assignment + + - name: Assert custom role user assignment changed the system + ansible.builtin.assert: + that: + - custom_user_role_assignment is changed + + - name: Assign custom role to user on organization (idempotent check) + ansible.platform.role_user_assignment: *custom_user_org_assignment + register: custom_user_role_assignment_idem + + - name: Assert custom role user assignment idempotent re-run is unchanged + ansible.builtin.assert: + that: + - custom_user_role_assignment_idem is not changed + + - name: Query API for custom role user assignment + ansible.builtin.uri: + url: "{{ gateway_hostname }}api/gateway/v1/role_user_assignments/?role_definition={{ custom_role.id }}&user={{ user4.id }}" + user: "{{ gateway_username }}" + password: "{{ gateway_password }}" + force_basic_auth: true + validate_certs: "{{ gateway_validate_certs | bool }}" + return_content: true + register: custom_user_assignment_query + + - name: Assert custom role user assignment exists in API + ansible.builtin.assert: + that: + - custom_user_assignment_query.json.count | int > 0 + fail_msg: >- + No role_user_assignment found for custom role id {{ custom_role.id }} and user id {{ user4.id }}. + + - name: Create custom team-scoped role (shared.team) + ansible.platform.role_definition: + name: "{{ custom_team_role_name }}" + description: "Custom role for role_user_assignment content_type resolution test (team)" + content_type: "shared.team" + permissions: + - "shared.view_team" + state: present + register: custom_team_role + failed_when: >- + custom_team_role is failed and + 'Creating custom roles for teams is disabled' not in custom_team_role.msg | default('') + + - name: Assert custom team role definition was created + ansible.builtin.assert: + that: + - custom_team_role is changed + when: custom_team_role is defined and custom_team_role.id is defined + + - name: Assign custom team role to user on team (object_ids by id) + ansible.platform.role_user_assignment: &custom_user_team_assignment + role_definition: "{{ custom_team_role_name }}" + user: "{{ user.id }}" + object_ids: + - "{{ team1.id }}" + state: present + register: custom_team_user_role_assignment + when: custom_team_role is defined and custom_team_role.id is defined + + - name: Assert custom team role user assignment changed the system + ansible.builtin.assert: + that: + - custom_team_user_role_assignment is changed + when: custom_team_role is defined and custom_team_role.id is defined + + - name: Assign custom team role to user (idempotent check) + ansible.platform.role_user_assignment: *custom_user_team_assignment + register: custom_team_user_role_assignment_idem + when: custom_team_role is defined and custom_team_role.id is defined + + - name: Assert custom team role user assignment idempotent re-run is unchanged + ansible.builtin.assert: + that: + - custom_team_user_role_assignment_idem is not changed + when: custom_team_role is defined and custom_team_role.id is defined + + - name: Query API for custom team role user assignment + ansible.builtin.uri: + url: "{{ gateway_hostname }}api/gateway/v1/role_user_assignments/?role_definition={{ custom_team_role.id }}&user={{ user.id }}" + user: "{{ gateway_username }}" + password: "{{ gateway_password }}" + force_basic_auth: true + validate_certs: "{{ gateway_validate_certs | bool }}" + return_content: true + register: custom_team_user_assignment_query + when: custom_team_role is defined and custom_team_role.id is defined + + - name: Assert custom team role user assignment exists in API + ansible.builtin.assert: + that: + - custom_team_user_assignment_query.json.count | int > 0 + fail_msg: >- + No role_user_assignment found for custom team role id {{ custom_team_role.id }} and user id {{ user.id }}. + when: custom_team_role is defined and custom_team_role.id is defined + - name: Assign Platform Auditor by Role User Assignments ansible.platform.role_user_assignment: &platform_auditor_assignment role_definition: Platform Auditor @@ -348,6 +470,61 @@ # # always: # Always Cleanup + - name: Remove custom team role user assignment if test created it + ansible.platform.role_user_assignment: + role_definition: "{{ custom_team_role_name }}" + user: "{{ user.id }}" + object_ids: + - "{{ team1.id }}" + state: absent + when: custom_team_role is defined and custom_team_role.id is defined and team1 is defined + register: custom_team_user_assignment_delete + failed_when: >- + custom_team_user_assignment_delete is failed and + 'Not found' not in custom_team_user_assignment_delete.msg | default('') and + 'does not exist' not in custom_team_user_assignment_delete.msg | default('') + + - name: Delete custom team role definition + ansible.platform.role_definition: + name: "{{ custom_team_role_name }}" + content_type: "shared.team" + permissions: + - "shared.view_team" + state: absent + when: custom_team_role is defined and custom_team_role.id is defined + register: custom_team_role_delete + failed_when: >- + custom_team_role_delete is failed and + 'Not found' not in custom_team_role_delete.msg | default('') and + 'does not exist' not in custom_team_role_delete.msg | default('') + + - name: Remove custom org role user assignment if test created it + ansible.platform.role_user_assignment: + role_definition: "{{ custom_role_name }}" + user: "{{ user4.id }}" + object_ids: + - "{{ org.id }}" + state: absent + when: custom_role is defined + register: custom_user_assignment_delete + failed_when: >- + custom_user_assignment_delete is failed and + 'Not found' not in custom_user_assignment_delete.msg | default('') and + 'does not exist' not in custom_user_assignment_delete.msg | default('') + + - name: Delete custom org role definition + ansible.platform.role_definition: + name: "{{ custom_role_name }}" + content_type: "shared.organization" + permissions: + - "shared.view_organization" + state: absent + register: custom_role_delete + failed_when: >- + custom_role_delete is failed and + 'Not found' not in custom_role_delete.msg | default('') and + 'does not exist' not in custom_role_delete.msg | default('') + - name: Delete users ansible.platform.user: username: "{{ item }}"