diff --git a/awx_collection/plugins/modules/tower_role.py b/awx_collection/plugins/modules/tower_role.py index eab7c3d250..d360110d7a 100644 --- a/awx_collection/plugins/modules/tower_role.py +++ b/awx_collection/plugins/modules/tower_role.py @@ -42,31 +42,81 @@ options: - Team that the role acts on. - For example, make someone a member or an admin of a team. - Members of a team implicitly receive the permissions that the team has. + - Deprecated, use 'target_teams'. type: str + target_teams: + description: + - Team that the role acts on. + - For example, make someone a member or an admin of a team. + - Members of a team implicitly receive the permissions that the team has. + type: list + elements: str inventory: description: - Inventory the role acts on. + - Deprecated, use 'inventories'. type: str + inventories: + description: + - Inventory the role acts on. + type: list + elements: str job_template: description: - The job template the role acts on. + - Deprecated, use 'job_templates'. type: str + job_templates: + description: + - The job template the role acts on. + type: list + elements: str workflow: description: - The workflow job template the role acts on. + - Deprecated, use 'workflows'. type: str + workflows: + description: + - The workflow job template the role acts on. + type: list + elements: str credential: description: - Credential the role acts on. + - Deprecated, use 'credentials'. type: str + credentials: + description: + - Credential the role acts on. + type: list + elements: str organization: description: - Organization the role acts on. + - Deprecated, use 'organizations'. + type: str + organizations: + description: + - Organization the role acts on. + type: list + elements: str + lookup_organization: + description: + - Organization the inventories, job templates, projects, or workflows the items exists in. + - Used to help lookup the object, for organizaiton roles see organization. + - If not provided, will lookup by name only, which does not work with duplicates. type: str project: description: - Project the role acts on. + - Deprecated, use 'projects'. type: str + projects: + description: + - Project the role acts on. + type: list + elements: str state: description: - Desired state. @@ -101,11 +151,17 @@ def main(): "workflow_admin", "notification_admin", "job_template_admin"], required=True), target_team=dict(), inventory=dict(), + inventories=dict(type='list', elements='str'), job_template=dict(), + job_templates=dict(type='list', elements='str'), workflow=dict(), + workflows=dict(type='list', elements='str'), credential=dict(), + credentials=dict(type='list', elements='str'), organization=dict(), + lookup_organization=dict(), project=dict(), + projects=dict(type='list', elements='str'), state=dict(choices=['present', 'absent'], default='present'), ) @@ -117,41 +173,85 @@ def main(): module.json_output['role'] = role_type - # Lookup data for all the objects specified in params - params = module.params.copy() + # Deal with legacy parameters + resource_list_param_keys = { + 'credentials': 'credential', + 'inventories': 'inventory', + 'job_templates': 'job_template', + 'target_teams': 'target_team', + 'organizations': 'organization', + 'projects': 'project', + 'target_teams': 'target_team', + 'workflows': 'workflow' + } + # Remove Project after testing resource_param_keys = ( - 'user', 'team', - 'target_team', 'inventory', 'job_template', 'workflow', 'credential', 'organization', 'project' + 'user', 'team', 'lookup_organization' ) - resource_data = {} - for param in resource_param_keys: - endpoint = module.param_to_endpoint(param) - resource_name = params.get(param) - if resource_name: - resource = module.get_exactly_one(module.param_to_endpoint(param), resource_name) - resource_data[param] = resource + resources = {} + for resource_group in resource_list_param_keys: + if module.params.get(resource_group) is not None: + resources.setdefault(resource_group, []).extend(module.params.get(resource_group)) + if module.params.get(resource_list_param_keys[resource_group]) is not None: + resources.setdefault(resource_group, []).append(module.params.get(resource_list_param_keys[resource_group])) + for resource_group in resource_param_keys: + if module.params.get(resource_group) is not None: + resources[resource_group] = module.params.get(resource_group) + # Change workflows and target_teams key to its endpoint name. + if 'workflows' in resources: + resources['workflow_job_templates'] = resources.pop('workflows') + if 'target_teams' in resources: + resources['teams'] = resources.pop('target_teams') + # Set lookup data to use + lookup_data = {} + if 'lookup_organization' in resources: + lookup_data['organization'] = module.resolve_name_to_id('organizations', resources['lookup_organization']) + resources.pop('lookup_organization') + + # Lookup actor data # separate actors from resources actor_data = {} for key in ('user', 'team'): - if key in resource_data: - actor_data[key] = resource_data.pop(key) + if key in resources: + if key == 'user': + lookup_data_populated = {} + else: + lookup_data_populated = lookup_data + # Attempt to look up project based on the provided name or ID and lookup data + actor_data[key] = module.get_one('{0}s'.format(key), name_or_id=resources[key], data=lookup_data_populated) + resources.pop(key) + + # Lookup Resources + resource_data = {} + for key in resources: + for resource in resources[key]: + # Attempt to look up project based on the provided name or ID and lookup data + if key in resources: + if key == 'organizations': + lookup_data_populated = {} + else: + lookup_data_populated = lookup_data + + resource_data.setdefault(key, []).append(module.get_one(key, name_or_id=resource, data=lookup_data_populated)) # build association agenda associations = {} for actor_type, actor in actor_data.items(): - for resource_type, resource in resource_data.items(): - resource_roles = resource['summary_fields']['object_roles'] - if role_field not in resource_roles: - available_roles = ', '.join(list(resource_roles.keys())) - module.fail_json(msg='Resource {0} has no role {1}, available roles: {2}'.format( - resource['url'], role_field, available_roles - ), changed=False) - role_data = resource_roles[role_field] - endpoint = '/roles/{0}/{1}/'.format(role_data['id'], module.param_to_endpoint(actor_type)) - associations.setdefault(endpoint, []) - associations[endpoint].append(actor['id']) + for key in resource_data: + for resource in resource_data[key]: + resource_roles = resource['summary_fields']['object_roles'] + if role_field not in resource_roles: + available_roles = ', '.join(list(resource_roles.keys())) + module.fail_json(msg='Resource {0} has no role {1}, available roles: {2}'.format( + resource['url'], role_field, available_roles + ), changed=False) + role_data = resource_roles[role_field] + endpoint = '/roles/{0}/{1}/'.format(role_data['id'], module.param_to_endpoint(actor_type)) + associations.setdefault(endpoint, []) + associations[endpoint].append(actor['id']) + # Stopped improvements # perform associations for association_endpoint, new_association_list in associations.items():