diff --git a/README.md b/README.md index 1606226..ed62a2e 100755 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ Name | Description | [equinix.cloud.metal_project_ssh_key_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/v0.6.2/docs/modules/metal_project_ssh_key_info.md)|Gather project SSH keys.| [equinix.cloud.metal_reserved_ip_block_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/v0.6.2/docs/modules/metal_reserved_ip_block_info.md)|Gather list of reserved IP blocks| [equinix.cloud.metal_ssh_key_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/v0.6.2/docs/modules/metal_ssh_key_info.md)|Gather personal SSH keys| +[equinix.cloud.metal_user_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/v0.6.2/docs/modules/metal_user_info.md)|Gather information about the current user for Equinix Metal| [equinix.cloud.metal_virtual_circuit_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/v0.6.2/docs/modules/metal_virtual_circuit_info.md)|Gather information about Equinix Metal Virtual Circuits| [equinix.cloud.metal_vlan_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/v0.6.2/docs/modules/metal_vlan_info.md)|Gather VLANs.| [equinix.cloud.metal_vrf_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/v0.6.2/docs/modules/metal_vrf_info.md)|Gather VRFs| diff --git a/docs/modules/metal_user_info.md b/docs/modules/metal_user_info.md new file mode 100644 index 0000000..68c8537 --- /dev/null +++ b/docs/modules/metal_user_info.md @@ -0,0 +1,89 @@ +# metal_user_info + +Gather information about the current user for Equinix Metal + + +- [Examples](#examples) +- [Parameters](#parameters) +- [Return Values](#return-values) + +## Examples + +```yaml +- name: Gather information about the current current user + hosts: localhost + tasks: + - equinix.cloud.metal_user_info: + metal_api_token: "{{ lookup('env', 'METAL_API_TOKEN') }}" + register: result + + - debug: + var: result + +``` + + + + + + + + + + +## Parameters + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `metal_api_token` |
`str`
|
**Required**
| The Equinix Metal API token to use. | + + + + + + +## Return Values + + + +### Sample Response for user +```json +{ + "avatar_thumb_url": "https://www.gravatar.com/avatar/49d55cbf53f2dae15bfa4c3a3fb884f9?d=mm", + "avatar_url": "https://www.gravatar.com/avatar/49d55cbf53f2dae15bfa4c3a3fb884f9?d=mm", + "created_at": "2019-08-24T14:15:22Z", + "customdata": {}, + "default_organization_id": "7498eaa8-62af-4757-81e0-959250fc9cd5", + "default_project_id": null, + "email": "john.doe@email.com", + "emails": [ + { + "href": "string" + } + ], + "features": [], + "first_name": "John", + "full_name": "John Doe", + "href": "/metal/v1/users/497f6eca-6276-4993-bfeb-53cbbbba6f08", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "language": null, + "last_login_at": "2019-08-24T14:15:22Z", + "last_name": "Doe", + "mailing_address": null, + "max_projects": 0, + "number_of_ssh_keys": 0, + "opt_in": false, + "opt_in_updated_at": null, + "originating_idp": "Equinix", + "phone_number": null, + "restricted": false, + "short_id": "497f6eca", + "social_accounts": {}, + "timezone": "America/New_York", + "two_factor_auth": "", + "updated_at": "2019-08-24T14:15:22Z", + "verification_stage": "verified" +} +``` + + diff --git a/plugins/module_utils/metal/api_routes.py b/plugins/module_utils/metal/api_routes.py index 6260fff..aabeb54 100644 --- a/plugins/module_utils/metal/api_routes.py +++ b/plugins/module_utils/metal/api_routes.py @@ -84,6 +84,9 @@ def get_routes(mpc): ('metal_virtual_circuit_vrf', action.GET): spec_types.Specs( equinix_metal.InterconnectionsApi(mpc).get_virtual_circuit, ), + ('metal_user', action.GET): spec_types.Specs( + equinix_metal.UsersApi(mpc).find_current_user, + ), # LISTERS ('metal_project_device', action.LIST): spec_types.Specs( diff --git a/plugins/module_utils/metal/metal_api.py b/plugins/module_utils/metal/metal_api.py index 8a82d23..a2ef23c 100644 --- a/plugins/module_utils/metal/metal_api.py +++ b/plugins/module_utils/metal/metal_api.py @@ -136,6 +136,27 @@ def extract_ids_from_projects_hrefs(resource: dict): 'ip_ranges': 'ip_ranges', } +METAL_USER_RESPONSE_ATTRIBUTE_MAP = { + 'avatar_thumb_url': 'avatar_thumb_url', + 'avatar_url': 'avatar_url', + 'created_at': 'created_at', + 'customdata': 'customdata', + 'default_organization_id': 'default_organization_id', + 'email': 'email', + 'emails': 'emails', + 'first_name': 'first_name', + 'full_name': 'full_name', + 'href': 'href', + 'id': 'id', + 'last_login_at': 'last_login_at', + 'last_name': 'last_name', + 'max_projects': 'max_projects', + 'short_id': 'short_id', + 'timezone': 'timezone', + 'two_factor_auth': 'two_factor_auth', + 'updated_at': 'updated_at' +} + LIST_KEYS = [ 'projects', 'devices', @@ -153,6 +174,7 @@ def extract_ids_from_projects_hrefs(resource: dict): 'sessions', # metal_bgp_session_info 'plans', 'virtual_circuits', + 'users', ] @@ -362,6 +384,8 @@ def get_attribute_mapper(resource_type): return METAL_PLAN_RESPONSE_ATTRIBUTE_MAP elif resource_type in virtual_circuit_resources: return METAL_VIRTUAL_CIRCUIT_RESPONSE_ATTRIBUTE_MAP + elif resource_type == 'metal_user': + return METAL_USER_RESPONSE_ATTRIBUTE_MAP else: raise NotImplementedError("No mapper for resource type %s" % resource_type) diff --git a/plugins/modules/metal_user_info.py b/plugins/modules/metal_user_info.py new file mode 100644 index 0000000..ce8179e --- /dev/null +++ b/plugins/modules/metal_user_info.py @@ -0,0 +1,177 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# DOCUMENTATION, EXAMPLES, and RETURN are generated by +# ansible_specdoc. Do not edit them directly. + +DOCUMENTATION = ''' +author: Equinix DevRel Team (@equinix) +description: Gather information about the current user for Equinix Metal +module: metal_user_info +notes: [] +options: + metal_api_token: + description: + - The Equinix Metal API token to use. + required: true + type: str +requirements: null +short_description: Gather information about the current user for Equinix Metal +''' +EXAMPLES = ''' +- name: Gather information about the current current user + hosts: localhost + tasks: + - equinix.cloud.metal_user_info: + metal_api_token: '{{ lookup(''env'', ''METAL_API_TOKEN'') }}' + register: result + - debug: + var: result +''' +RETURN = ''' +user: + description: Information about the current user. + returned: always + sample: + - avatar_thumb_url: https://www.gravatar.com/avatar/49d55cbf53f2dae15bfa4c3a3fb884f9?d=mm + avatar_url: https://www.gravatar.com/avatar/49d55cbf53f2dae15bfa4c3a3fb884f9?d=mm + created_at: '2019-08-24T14:15:22Z' + customdata: {} + default_organization_id: 7498eaa8-62af-4757-81e0-959250fc9cd5 + email: john.doe@email.com + emails: + - href: string + first_name: John + full_name: John Doe + href: /metal/v1/users/497f6eca-6276-4993-bfeb-53cbbbba6f08 + id: 497f6eca-6276-4993-bfeb-53cbbbba6f08 + last_login_at: '2019-08-24T14:15:22Z' + last_name: Doe + max_projects: 0 + short_id: 497f6eca + timezone: America/New_York + two_factor_auth: '' + updated_at: '2019-08-24T14:15:22Z' + type: dict +''' + +# End of generated documentation + +from ansible.module_utils._text import to_native +from ansible_specdoc.objects import ( + SpecField, + FieldType, + SpecReturnValue, +) +import traceback + +from ansible_collections.equinix.cloud.plugins.module_utils.equinix import ( + EquinixModule, + getSpecDocMeta, +) + +# Define module specifications +module_spec = dict( + metal_api_token=SpecField( + type=FieldType.string, + description=['The Equinix Metal API token to use.'], + required=True, + no_log=True, + ), + metal_api_url=SpecField( + type=FieldType.string, + description=['The Equinix Metal API URL to use.'], + required=True, + ), +) + +# Define examples for the module documentation +specdoc_examples = [ + ''' +- name: Gather information about the current current user + hosts: localhost + tasks: + - equinix.cloud.metal_user_info: + metal_api_token: "{{ lookup('env', 'METAL_API_TOKEN') }}" + register: result + + - debug: + var: result +''', +] + +# Define return values for the module documentation +return_values = [ + { + "avatar_thumb_url": "https://www.gravatar.com/avatar/49d55cbf53f2dae15bfa4c3a3fb884f9?d=mm", + "avatar_url": "https://www.gravatar.com/avatar/49d55cbf53f2dae15bfa4c3a3fb884f9?d=mm", + "created_at": "2019-08-24T14:15:22Z", + "customdata": {}, + "default_organization_id": "7498eaa8-62af-4757-81e0-959250fc9cd5", + "email": "john.doe@email.com", + "emails": [ + { + "href": "string" + } + ], + "first_name": "John", + "full_name": "John Doe", + "href": "/metal/v1/users/497f6eca-6276-4993-bfeb-53cbbbba6f08", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_login_at": "2019-08-24T14:15:22Z", + "last_name": "Doe", + "max_projects": 0, + "short_id": "497f6eca", + "timezone": "America/New_York", + "two_factor_auth": "", + "updated_at": "2019-08-24T14:15:22Z" + } +] + +# Define the metadata for SpecDoc +SPECDOC_META = getSpecDocMeta( + short_description='Gather information about the current user for Equinix Metal', + description='Gather information about the current user for Equinix Metal', + examples=specdoc_examples, + options=module_spec, + return_values={ + "user": SpecReturnValue( + description='Information about the current user.', + type=FieldType.dict, + sample=return_values, + ), + }, +) + +def main(): + # Create an instance of EquinixModule with provided specifications + module = EquinixModule( + argument_spec=SPECDOC_META.ansible_spec, + is_info=True, + ) + try: + # Check for syntax validity in provided parameters + module.params_syntax_check() + + # Setting the id parameter to 'current_user' ensures the module fetches the correct information + # Since the id parameter is required by 'get_by_id', we need to set it to a value + module.params["id"] = "current_user" + + # Fetch the current user's information using the get_by_id method + result = module.get_by_id("metal_user") + + # Prepare the return value with the fetched user information + return_value = {"user": result} + except Exception as e: + # Capture any exception and fail the module execution with the error message + tr = traceback.format_exc() + module.fail_json(msg=to_native(e), exception=tr) + + # Exit the module with the return value + module.exit_json(**return_value) + + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt index deecf1c..cc5494f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ equinix-metal==0.9.0 ansible-specdoc>=0.0.13 pydantic >= 2 +requests diff --git a/tests/integration/targets/metal_user_info/tasks/main.yml b/tests/integration/targets/metal_user_info/tasks/main.yml new file mode 100644 index 0000000..32cfe3c --- /dev/null +++ b/tests/integration/targets/metal_user_info/tasks/main.yml @@ -0,0 +1,59 @@ +- name: metal_user_info + module_defaults: + equinix.cloud.metal_user_info: + metal_api_token: '{{ metal_api_token }}' + equinix.cloud.metal_project: + metal_api_token: '{{ metal_api_token }}' + equinix.cloud.metal_project_info: + metal_api_token: '{{ metal_api_token }}' + metal_ua_prefix: '{{ metal_ua_prefix }}' + block: + - set_fact: + test_prefix: 'ansible-integration-test' + + - name: gather current user info + equinix.cloud.metal_user_info: + metal_api_token: '{{ metal_api_token }}' + register: user_info + + - debug: + msg: "User info: {{ user_info.user }}" + + - assert: + that: + - user_info.user.avatar_thumb_url is defined + - user_info.user.avatar_url is defined + - user_info.user.created_at is defined + - user_info.user.customdata is defined + - user_info.user.default_organization_id is defined + - user_info.user.email is defined + - user_info.user.emails is defined + - user_info.user.first_name is defined + - user_info.user.full_name is defined + - user_info.user.href is defined + - user_info.user.id is defined + - user_info.user.last_login_at is defined + - user_info.user.last_name is defined + - user_info.user.max_projects is defined + - user_info.user.short_id is defined + - user_info.user.timezone is defined + - user_info.user.two_factor_auth is defined + - user_info.user.updated_at is defined + + always: + - name: Announce teardown start + debug: + msg: "***** TESTING COMPLETE. COMMENCE TEARDOWN *****" + + - name: list test projects + equinix.cloud.metal_project_info: + metal_api_token: '{{ metal_api_token }}' + name: "{{ test_prefix }}" + register: test_projects_listed + + - name: delete test projects + equinix.cloud.metal_project: + id: "{{ item.id }}" + state: absent + loop: "{{ test_projects_listed.resources }}" + ignore_errors: yes