diff --git a/README.md b/README.md
index 39c586b..598d9b4 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# Equinix Ansible Collection
-[![Ansible Galaxy](https://img.shields.io/badge/galaxy-equinix.cloud-660198.svg?style=flat)](https://galaxy.ansible.com/equinix/cloud/)
+[![Ansible Galaxy](https://img.shields.io/badge/galaxy-equinix.cloud-660198.svg?style=flat)](https://galaxy.ansible.com/equinix/cloud/)
![Tests](https://img.shields.io/github/actions/workflow/status/equinix-labs/ansible-collection-equinix/integration-tests.yml?branch=main)
The Ansible Collection Equinix contains various plugins for managing Equinix services.
@@ -26,11 +26,14 @@ Name | Description |
[equinix.cloud.metal_ip_assignment](./docs/modules/metal_ip_assignment.md)|Manage Equinix Metal IP assignments|
[equinix.cloud.metal_organization](./docs/modules/metal_organization.md)|Lookup a single organization by ID in Equinix Metal|
[equinix.cloud.metal_project](./docs/modules/metal_project.md)|Manage Projects in Equinix Metal|
+[equinix.cloud.metal_project_ssh_key](./docs/modules/metal_project_ssh_key.md)|Manage a project ssh key in Equinix Metal|
[equinix.cloud.metal_reserved_ip_block](./docs/modules/metal_reserved_ip_block.md)|Create/delete blocks of reserved IP addresses in a project.|
[equinix.cloud.metal_ssh_key](./docs/modules/metal_ssh_key.md)|Manage personal SSH keys in Equinix Metal|
+[equinix.cloud.metal_project_ssh_key](./docs/modules/metal_project_ssh_key.md)|Manage project SSH keys in Equinix Metal|
[equinix.cloud.metal_vlan](./docs/modules/metal_vlan.md)|Manage a VLAN resource in Equinix Metal|
+
### Info Modules
Modules for retrieving information about existing Equinix infrastructure.
@@ -45,7 +48,10 @@ Name | Description |
[equinix.cloud.metal_operating_system_info](./docs/modules/metal_operating_system_info.md)|Gather information about Operating Systems available for devices in Equinix Metal|
[equinix.cloud.metal_organization_info](./docs/modules/metal_organization_info.md)|Gather information about Equinix Metal organizations|
[equinix.cloud.metal_project_info](./docs/modules/metal_project_info.md)|Gather information about Equinix Metal projects|
+[equinix.cloud.metal_project_ssh_key_info](./docs/modules/metal_project_ssh_key_info.md)|Gather project SSH keys.|
[equinix.cloud.metal_reserved_ip_block_info](./docs/modules/metal_reserved_ip_block_info.md)|Gather list of reserved IP blocks|
+[equinix.cloud.metal_ssh_key_info](./docs/modules/metal_ssh_key_info.md)|Gather personal SSH keys|list project SSH keys
+[equinix.cloud.metal_project_ssh_key_info](./docs/modules/metal_project_ssh_key_info.md)|Gather project SSH keys|
[equinix.cloud.metal_ssh_key_info](./docs/modules/metal_ssh_key_info.md)|Gather personal SSH keys|
[equinix.cloud.metal_vlan_info](./docs/modules/metal_vlan_info.md)|Gather VLANs.|
diff --git a/docs/modules/metal_project_ssh_key.md b/docs/modules/metal_project_ssh_key.md
new file mode 100644
index 0000000..ed47b60
--- /dev/null
+++ b/docs/modules/metal_project_ssh_key.md
@@ -0,0 +1,73 @@
+# metal_project_ssh_key
+
+Manage project ssh key in Equinix Metal. Read more about personal and project SSH keys in [Equinix Metal documentation](https://deploy.equinix.com/developers/docs/metal/accounts/ssh-keys/#personal-keys-vs-project-keys). You can use *id* or *label* to lookup a project SSH key. If you want to create new resource, you must provide *name*, *public_key* and *project_id*.
+
+
+- [Examples](#examples)
+- [Parameters](#parameters)
+- [Return Values](#return-values)
+
+## Examples
+
+```yaml
+- name: Create new project project ssh_key
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_ssh_key:
+ name: "test_key"
+ public_key: "ssh-dss AAAAB3NzaC1kc3MAAACBAPLEVntPO3L7VUbEwWZ2ErkQJ3KJ8o9kFXJrPcpvVfdNag4jIhQDqbtAUgUy6BclhhbfH9l5nlGTprrpEFkxm/GL91qJUX6xrPkDMjMqx2wSKa4YraReOrCOfkqqEkC3o3G/gYSuvTzLgp2rmPiflypftZyzNM4JZT8jDwFGotJhAAAAFQDPk43bayONtUxjkAcOf+6zP1qb6QAAAIBZHHH0tIlth5ot+Xa/EYuB/M4qh77EkrWUbER0Kki7suskw/ffdKQ0y/v+ZhoAHtBU7BeE3HmP98Vrha1i4cOU+A7DCqV+lK/a+5LoEpua0M2M+VzNSGluYuV4qGpAOxNh3mxUi2R7yXxheN1oks1ROJ/bqkF4BJQXU9Nv49GkZgAAAIByWcsFeOitvzyDaNJOZzEHv9fqGuj0L3maRVWb6O47HGzlMzniIy8WjL2dfgm2/ek+NxVR/yFnYTKDPr6+0uqSD/cb4eHaFbIj7v+k7H8hA1Ioz+duJ1ONAjn6KwneXxOXu15bYIR49P7Go0s9jCdSAP/r9NE5TnE3yiRiQzgEzw== tomk@node"
+ project_id: "local.project_id"
+
+```
+
+```yaml
+- name: Remove project ssh_key by id
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_ssh_key:
+ id: "eef49903-7a09-4ca1-af67-4087c29ab5b6"
+ state: absent
+
+```
+
+
+
+
+
+
+
+
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `id` |
`str` | Optional | UUID of the ssh_key. |
+| `name` | `str` | Optional | The name of the ssh_key. **(Updatable)** |
+| `public_key` | `str` | Optional | The public key of the project ssh_key. **(Updatable)** |
+| `project_id` | `str` | Optional | The ID of parent project. **(Updatable)** |
+
+
+
+
+
+
+## Return Values
+
+- `metal_project_ssh_key` - The module object
+
+ - Sample Response:
+ ```json
+
+ {
+ "fingerprint": "98:9c:35:ed:f9:75:5b:52:e2:70:50:22:ea:77:5b:b6",
+ "id": "eef49903-7a09-4ca1-af67-4087c29ab5b6",
+ "public_key": "ssh-dss AAAAB3NzaC1kc3MAAACBAPLEVntPO3L7VUbEwWZ2ErkQJ3KJ8o9kFXJrPcpvVfdNag4jIhQDqbtAUgUy6BclhhbfH9l5nlGTprrpEFkxm/GL91qJUX6xrPkDMjMqx2wSKa4YraReOrCOfkqqEkC3o3G/gYSuvTzLgp2rmPiflypftZyzNM4JZT8jDwFGotJhAAAAFQDPk43bayONtUxjkAcOf+6zP1qb6QAAAIBZHHH0tIlth5ot+Xa/EYuB/M4qh77EkrWUbER0Kki7suskw/ffdKQ0y/v+ZhoAHtBU7BeE3HmP98Vrha1i4cOU+A7DCqV+lK/a+5LoEpua0M2M+VzNSGluYuV4qGpAOxNh3mxUi2R7yXxheN1oks1ROJ/bqkF4BJQXU9Nv49GkZgAAAIByWcsFeOitvzyDaNJOZzEHv9fqGuj0L3maRVWb6O47HGzlMzniIy8WjL2dfgm2/ek+NxVR/yFnYTKDPr6+0uqSD/cb4eHaFbIj7v+k7H8hA1Ioz+duJ1ONAjn6KwneXxOXu15bYIR49P7Go0s9jCdSAP/r9NE5TnE3yiRiQzgEzw== tomk@xps",
+ "name": "test_key",
+ "project_id": "local.project_id"
+ }
+
+ ```
+
+
diff --git a/docs/modules/metal_project_ssh_key_info.md b/docs/modules/metal_project_ssh_key_info.md
new file mode 100644
index 0000000..10bd318
--- /dev/null
+++ b/docs/modules/metal_project_ssh_key_info.md
@@ -0,0 +1,73 @@
+# metal_project_ssh_key_info
+
+Gather project SSH keys. Read more about project vs project SSH keys in [Equinix Metal documentation](https://metal.equinix.com/developers/docs/accounts/ssh-keys/#personal-keys-vs-project-keys).
+
+
+- [Examples](#examples)
+- [Parameters](#parameters)
+- [Return Values](#return-values)
+
+## Examples
+
+```yaml
+
+- set_fact:
+ desired_name_substring: "tkarasek"
+
+- name: list project ssh keys
+ equinix.cloud.metal_project_ssh_key_info:
+ register: ssh_keys_listed
+
+- name: filter found ssh keys
+ set_fact:
+ both_ssh_keys_listed: "{{ ssh_keys_listed.resources | selectattr('name', 'match', desired_name_substring) }}"
+
+```
+
+
+
+
+
+
+
+
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `name` | `str` | **Required** | Name to search for in existing keys. |
+
+
+
+
+
+
+## Return Values
+
+- `resources` - Found resources
+
+ - Sample Response:
+ ```json
+
+ [
+ {
+ "fingerprint": "70:c1:73:8b:3f:2f:a4:18:ea:4d:79:13:52:7b:c4:3e",
+ "id": "6edfcbc2-17e5-4221-9eac-2f40dbe60daf",
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt5gwVMhwcCrxyxpMEKwiS0xgit3PIIEgVXt6SQHc8eONq0mYJJ5TOBNTnySqXd9RtSv/Jbf5Aq9BzBGWeoZ6sZfKwh984Ip35StJtjXtyIOlY3skovndtupBIwlGXgX/WQzyLr+G/+Yu9/nhdxQi801PDZnDvKoeomM0rMD29nV+m0ud+GrtsAt6VFul2PxqpypZ1TYviyED6IKo7rgQsQDkE9QHcNdfT1FZWiJbfP7o8TIurQJcAXg+MtLoc8rKKcxFMeZ9FSydgtTC7nP1h558RtECGWiUgaBPI7TpBmcdMtbEfAiBoGT17GWnT8qmy2u5xnEKPD9Qft4w4fjfpw==",
+ "label": "tkarasek",
+ "project_id": local.project_id
+ },
+ {
+ "fingerprint": "ba:70:af:b3:0f:0e:7f:e5:eb:97:e2:27:b1:f5:6f:94",
+ "id": "d00c596d-b42a-44a7-ac14-e299b85e73d3",
+ "key": "ssh-dss AAAAB3NzaC1kc3MAAACBAOpXVtmc0Bla98bt0o5/Zj7sb4mHIukgVFZu7F32R3VK1cEKB4rEE8uS0oLS/qMRLue45TWVJwRMYGlPjt3p/VyraelxoyJZLuITIsqa5hBc9w0oTlB5Bmbkn16umW96WCaWEoq/aitpocbRChTiP5biI6FyQTQlIHDaYzBDOi11AAAAFQDUXy7cmuzphDpJSYYTiudiUhVokwAAAIEAyUQ9m8qL/1HPkFe6jbXAvtSSmW27F4c+G2xR5HizaHQzXgBOxPcsOsY17KTU+Ddbg+OF9soWNwSpm9pyVjVmNGqH3S8R1pwvuJF/O2Asy1m6wpWhbPw8JdEBW7WHoptBpfuzJoS2LOzJUEmUu4Eb+xS237KG1d1BVny/49KAoH0AAACBAJKBSsm9Xey0fUN6vYtTQgoYeGxxj/LqAIAOs/TpCxZDntly860y/SzHYai8x48k4t7whENY1CJ41fpMcPlz8xIsrNP3326Wbr0ExwOIvJKAVN1YLYqF8NXWzaVrjo5WbSeI8PiWTYemvLAujVxZssIrApTZBhp55nnwge6K1zTG tomk@air",
+ "label": "ansible-integration-test-ssh_key-ztiapihf-ssh_key1_renamed",
+ "project_id": local.project_id
+ }
+ ]
+
+ ```
+
+
diff --git a/plugins/module_utils/metal/api_routes.py b/plugins/module_utils/metal/api_routes.py
index 1b1d1cb..48b302d 100644
--- a/plugins/module_utils/metal/api_routes.py
+++ b/plugins/module_utils/metal/api_routes.py
@@ -91,6 +91,10 @@ def get_routes(mpc):
('metal_ssh_key', action.LIST): spec_types.Specs(
equinix_metal.SSHKeysApi(mpc).find_ssh_keys,
),
+ ('metal_project_ssh_key', action.LIST): spec_types.Specs(
+ equinix_metal.SSHKeysApi(mpc).find_project_ssh_keys,
+ {'id': 'project_id'}
+ ),
('metal_organization', action.LIST): spec_types.Specs(
equinix_metal.OrganizationsApi(mpc).find_organizations,
{'personal': 'personal', 'with_projects': 'with_projects'},
@@ -130,7 +134,6 @@ def get_routes(mpc):
equinix_metal.VLANsApi(mpc).delete_virtual_network,
),
-
# CREATORS
('metal_device', action.CREATE): spec_types.Specs(
equinix_metal.DevicesApi(mpc).create_device,
@@ -162,6 +165,11 @@ def get_routes(mpc):
{},
equinix_metal.SSHKeyCreateInput,
),
+ ('metal_project_ssh_key', action.CREATE): spec_types.Specs(
+ equinix_metal.SSHKeysApi(mpc).create_project_ssh_key,
+ {'id': 'project_id'},
+ equinix_metal.SSHKeyCreateInput,
+ ),
('metal_vlan', action.CREATE): spec_types.Specs(
equinix_metal.VLANsApi(mpc).create_virtual_network,
{'id': 'project_id'},
diff --git a/plugins/modules/metal_project_ssh_key.py b/plugins/modules/metal_project_ssh_key.py
new file mode 100644
index 0000000..8f89673
--- /dev/null
+++ b/plugins/modules/metal_project_ssh_key.py
@@ -0,0 +1,213 @@
+#!/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: Manage project ssh key in Equinix Metal. Read more about personal and
+ project SSH keys in [Equinix Metal documentation](https://deploy.equinix.com/developers/docs/metal/accounts/ssh-keys/#personal-keys-vs-project-keys).
+ You can use *id* or *label* to lookup a project SSH key. If you want to create new
+ resource, you must provide *name*, *public_key* and *project_id*.
+module: metal_project_ssh_key
+notes: []
+options:
+ id:
+ description:
+ - UUID of the ssh_key.
+ required: false
+ type: str
+ name:
+ description:
+ - The name of the ssh_key.
+ required: false
+ type: str
+ project_id:
+ description:
+ - The ID of parent project.
+ required: false
+ type: str
+ public_key:
+ description:
+ - The public key of the project ssh_key.
+ required: false
+ type: str
+requirements: null
+short_description: Manage a project ssh key in Equinix Metal
+'''
+EXAMPLES = '''
+- name: Create new project project ssh_key
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_ssh_key:
+ name: test_key
+ public_key: ssh-dss AAAAB3NzaC1kc3MAAACBAPLEVntPO3L7VUbEwWZ2ErkQJ3KJ8o9kFXJrPcpvVfdNag4jIhQDqbtAUgUy6BclhhbfH9l5nlGTprrpEFkxm/GL91qJUX6xrPkDMjMqx2wSKa4YraReOrCOfkqqEkC3o3G/gYSuvTzLgp2rmPiflypftZyzNM4JZT8jDwFGotJhAAAAFQDPk43bayONtUxjkAcOf+6zP1qb6QAAAIBZHHH0tIlth5ot+Xa/EYuB/M4qh77EkrWUbER0Kki7suskw/ffdKQ0y/v+ZhoAHtBU7BeE3HmP98Vrha1i4cOU+A7DCqV+lK/a+5LoEpua0M2M+VzNSGluYuV4qGpAOxNh3mxUi2R7yXxheN1oks1ROJ/bqkF4BJQXU9Nv49GkZgAAAIByWcsFeOitvzyDaNJOZzEHv9fqGuj0L3maRVWb6O47HGzlMzniIy8WjL2dfgm2/ek+NxVR/yFnYTKDPr6+0uqSD/cb4eHaFbIj7v+k7H8hA1Ioz+duJ1ONAjn6KwneXxOXu15bYIR49P7Go0s9jCdSAP/r9NE5TnE3yiRiQzgEzw==
+ tomk@node
+ project_id: b8c6c653-3c96-446e-987e-9c4d12f25353
+- name: Remove project ssh_key by id
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_ssh_key:
+ id: eef49903-7a09-4ca1-af67-4087c29ab5b6
+ state: absent
+'''
+RETURN = '''
+metal_project_ssh_key:
+ description: The module object
+ returned: always
+ sample:
+ - "\n{\n \"fingerprint\": \"98:9c:35:ed:f9:75:5b:52:e2:70:50:22:ea:77:5b:b6\",\n\
+ \ \"id\": \"eef49903-7a09-4ca1-af67-4087c29ab5b6\",\n \"public_key\": \"ssh-dss\
+ \ AAAAB3NzaC1kc3MAAACBAPLEVntPO3L7VUbEwWZ2ErkQJ3KJ8o9kFXJrPcpvVfdNag4jIhQDqbtAUgUy6BclhhbfH9l5nlGTprrpEFkxm/GL91qJUX6xrPkDMjMqx2wSKa4YraReOrCOfkqqEkC3o3G/gYSuvTzLgp2rmPiflypftZyzNM4JZT8jDwFGotJhAAAAFQDPk43bayONtUxjkAcOf+6zP1qb6QAAAIBZHHH0tIlth5ot+Xa/EYuB/M4qh77EkrWUbER0Kki7suskw/ffdKQ0y/v+ZhoAHtBU7BeE3HmP98Vrha1i4cOU+A7DCqV+lK/a+5LoEpua0M2M+VzNSGluYuV4qGpAOxNh3mxUi2R7yXxheN1oks1ROJ/bqkF4BJQXU9Nv49GkZgAAAIByWcsFeOitvzyDaNJOZzEHv9fqGuj0L3maRVWb6O47HGzlMzniIy8WjL2dfgm2/ek+NxVR/yFnYTKDPr6+0uqSD/cb4eHaFbIj7v+k7H8hA1Ioz+duJ1ONAjn6KwneXxOXu15bYIR49P7Go0s9jCdSAP/r9NE5TnE3yiRiQzgEzw==\
+ \ tomk@xps\",\n \"name\": \"test_key\",\n \"project_id\": \"b8c6c653-3c96-446e-987e-9c4d12f25353\"\
+ \n}\n"
+ 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,
+ get_diff,
+ getSpecDocMeta,
+)
+
+
+MODULE_NAME = "metal_project_ssh_key"
+METAL_SSH_KEY = "metal_ssh_key"
+
+module_spec = dict(
+ id=SpecField(
+ type=FieldType.string,
+ description=["UUID of the ssh_key."],
+ ),
+ label=SpecField(
+ type=FieldType.string,
+ description=["The name of the ssh_key."],
+ editable=True,
+ ),
+ key=SpecField(
+ type=FieldType.string,
+ description=["The public key of the project ssh_key."],
+ editable=True,
+ ),
+ project_id=SpecField(
+ type=FieldType.string,
+ description=["The ID of parent project."],
+ editable=True,
+ ),
+)
+
+
+specdoc_examples = [
+ """
+- name: Create new project project ssh_key
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_ssh_key:
+ label: "test_key"
+ key: "ssh-dss AAAAB3NzaC1kc3MAAACBAPLEVntPO3L7VUbEwWZ2ErkQJ3KJ8o9kFXJrPcpvVfdNag4jIhQDqbtAUgUy6BclhhbfH9l5nlGTprrpEFkxm/GL91qJUX6xrPkDMjMqx2wSKa4YraReOrCOfkqqEkC3o3G/gYSuvTzLgp2rmPiflypftZyzNM4JZT8jDwFGotJhAAAAFQDPk43bayONtUxjkAcOf+6zP1qb6QAAAIBZHHH0tIlth5ot+Xa/EYuB/M4qh77EkrWUbER0Kki7suskw/ffdKQ0y/v+ZhoAHtBU7BeE3HmP98Vrha1i4cOU+A7DCqV+lK/a+5LoEpua0M2M+VzNSGluYuV4qGpAOxNh3mxUi2R7yXxheN1oks1ROJ/bqkF4BJQXU9Nv49GkZgAAAIByWcsFeOitvzyDaNJOZzEHv9fqGuj0L3maRVWb6O47HGzlMzniIy8WjL2dfgm2/ek+NxVR/yFnYTKDPr6+0uqSD/cb4eHaFbIj7v+k7H8hA1Ioz+duJ1ONAjn6KwneXxOXu15bYIR49P7Go0s9jCdSAP/r9NE5TnE3yiRiQzgEzw== tomk@node"
+ project_id: "b8c6c653-3c96-446e-987e-9c4d12f25353"
+""",
+ """
+- name: Remove project ssh_key by id
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_ssh_key:
+ id: "eef49903-7a09-4ca1-af67-4087c29ab5b6"
+ state: absent
+""",
+]
+
+result_sample = [
+ """
+{
+ "fingerprint": "98:9c:35:ed:f9:75:5b:52:e2:70:50:22:ea:77:5b:b6",
+ "id": "eef49903-7a09-4ca1-af67-4087c29ab5b6",
+ "key": "ssh-dss AAAAB4NzaC1kc3MAAACBAPLEVntPO3L7VUbEwWZ2ErkQJ3KJ8o9kFXJrPcpvVfdNag4jIhQDqbtAUgUy6BclhhbfH9l5nlGTprrpEFkxm/GL91qJUX6xrPkDMjMqx2wSKa4YraReOrCOfkqqEkC3o3G/gYSuvTzLgp2rmPiflypftZyzNM4JZT8jDwFGotJhAAAAFQDPk43bayONtUxjkAcOf+6zP1qb6QAAAIBZHHH0tIlth5ot+Xa/EYuB/M4qh77EkrWUbER0Kki7suskw/ffdKQ0y/v+ZhoAHtBU7BeE3HmP98Vrha1i4cOU+A7DCqV+lK/a+5LoEpua0M2M+VzNSGluYuV4qGpAOxNh3mxUi2R7yXxheN1oks1ROJ/bqkF4BJQXU9Nv49GkZgAAAIByWcsFeOitvzyDaNJOZzEHv9fqGuj0L3maRVWb6O47HGzlMzniIy8WjL2dfgm2/ek+NxVR/yFnYTKDPr6+0uqSD/cb4eHaFbIj7v+k7H8hA1Ioz+duJ1ONAjn6KwneXxOXu15bYIR49P7Go0s9jCdSAP/r9NE5TnE3yiRiQzgEzw== tomk@xps",
+ "label": "test_key",
+ "project_id": "b8c6c653-3c96-446e-987e-9c4d12f25353"
+}
+"""
+]
+
+MUTABLE_ATTRIBUTES = [k for k, v in module_spec.items() if v.editable]
+
+SPECDOC_META = getSpecDocMeta(
+ short_description="Manage a project ssh key in Equinix Metal",
+ description=(
+ "Manage project ssh key in Equinix Metal. "
+ "Read more about personal and project SSH keys in [Equinix Metal documentation](https://deploy.equinix.com/developers/docs/metal/accounts/ssh-keys/#personal-keys-vs-project-keys). "
+ "You can use *id* or *label* to lookup a project SSH key. "
+ "If you want to create new resource, you must provide *label*, *key* and *project_id*."
+ ),
+ examples=specdoc_examples,
+ options=module_spec,
+ return_values={
+ MODULE_NAME: SpecReturnValue(
+ description="The module object",
+ type=FieldType.dict,
+ sample=result_sample,
+ ),
+ },
+)
+
+
+def main():
+ module = EquinixModule(
+ argument_spec=SPECDOC_META.ansible_spec,
+ required_one_of=[("label", "id")],
+ required_together=[("label", "key")],
+ )
+ state = module.params.get("state")
+ changed = False
+
+ try:
+ module.params_syntax_check()
+ if module.params.get("id"):
+ tolerate_not_found = state == "absent"
+ fetched = module.get_by_id(METAL_SSH_KEY, tolerate_not_found)
+ else:
+ fetched = module.get_one_from_list(
+ MODULE_NAME,
+ ["key"],
+ )
+
+ if fetched:
+ module.params["id"] = fetched["id"]
+ if state == "present":
+ diff = get_diff(module.params, fetched, MUTABLE_ATTRIBUTES)
+ if diff:
+ fetched = module.update_by_id(diff, METAL_SSH_KEY)
+ changed = True
+
+ else:
+ module.delete_by_id(METAL_SSH_KEY)
+ changed = True
+ else:
+ if state == "present":
+ fetched = module.create(MODULE_NAME)
+ changed = True
+ else:
+ fetched = {}
+ except Exception as e:
+ tb = traceback.format_exc()
+ module.fail_json(msg=f"Error in {MODULE_NAME}: {to_native(e)}", exception=tb)
+
+ fetched.update({"changed": changed})
+ module.exit_json(**fetched)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/plugins/modules/metal_project_ssh_key_info.py b/plugins/modules/metal_project_ssh_key_info.py
new file mode 100644
index 0000000..46d5e64
--- /dev/null
+++ b/plugins/modules/metal_project_ssh_key_info.py
@@ -0,0 +1,145 @@
+#!/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 project SSH keys. Read more about project vs project SSH keys
+ in [Equinix Metal documentation](https://metal.equinix.com/developers/docs/accounts/ssh-keys/#personal-keys-vs-project-keys).
+module: metal_project_ssh_key_info
+notes: []
+options:
+ name:
+ description:
+ - Name to search for in existing keys.
+ required: true
+ type: str
+requirements: null
+short_description: Gather project SSH keys.
+'''
+EXAMPLES = '''
+- set_fact:
+ desired_name_substring: tkarasek
+- name: list project ssh keys
+ equinix.cloud.metal_project_ssh_key_info: null
+ register: ssh_keys_listed
+- name: filter found ssh keys
+ set_fact:
+ both_ssh_keys_listed: '{{ ssh_keys_listed.resources | selectattr(''name'', ''match'',
+ desired_name_substring) }}'
+'''
+RETURN = '''
+resources:
+ description: Found resources
+ returned: always
+ sample:
+ - "\n[\n {\n \"fingerprint\": \"70:c1:73:8b:3f:2f:a4:18:ea:4d:79:13:52:7b:c4:3e\"\
+ ,\n \"id\": \"6edfcbc2-17e5-4221-9eac-2f40dbe60daf\",\n \"key\"\
+ : \"ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt5gwVMhwcCrxyxpMEKwiS0xgit3PIIEgVXt6SQHc8eONq0mYJJ5TOBNTnySqXd9RtSv/Jbf5Aq9BzBGWeoZ6sZfKwh984Ip35StJtjXtyIOlY3skovndtupBIwlGXgX/WQzyLr+G/+Yu9/nhdxQi801PDZnDvKoeomM0rMD29nV+m0ud+GrtsAt6VFul2PxqpypZ1TYviyED6IKo7rgQsQDkE9QHcNdfT1FZWiJbfP7o8TIurQJcAXg+MtLoc8rKKcxFMeZ9FSydgtTC7nP1h558RtECGWiUgaBPI7TpBmcdMtbEfAiBoGT17GWnT8qmy2u5xnEKPD9Qft4w4fjfpw==\"\
+ ,\n \"label\": \"tkarasek\",\n \"project_id\": b8c6c653-3c96-446e-987e-9c4d12f25353\n\
+ \ },\n {\n \"fingerprint\": \"ba:70:af:b3:0f:0e:7f:e5:eb:97:e2:27:b1:f5:6f:94\"\
+ ,\n \"id\": \"d00c596d-b42a-44a7-ac14-e299b85e73d3\",\n \"key\"\
+ : \"ssh-dss AAAAB3NzaC1kc3MAAACBAOpXVtmc0Bla98bt0o5/Zj7sb4mHIukgVFZu7F32R3VK1cEKB4rEE8uS0oLS/qMRLue45TWVJwRMYGlPjt3p/VyraelxoyJZLuITIsqa5hBc9w0oTlB5Bmbkn16umW96WCaWEoq/aitpocbRChTiP5biI6FyQTQlIHDaYzBDOi11AAAAFQDUXy7cmuzphDpJSYYTiudiUhVokwAAAIEAyUQ9m8qL/1HPkFe6jbXAvtSSmW27F4c+G2xR5HizaHQzXgBOxPcsOsY17KTU+Ddbg+OF9soWNwSpm9pyVjVmNGqH3S8R1pwvuJF/O2Asy1m6wpWhbPw8JdEBW7WHoptBpfuzJoS2LOzJUEmUu4Eb+xS237KG1d1BVny/49KAoH0AAACBAJKBSsm9Xey0fUN6vYtTQgoYeGxxj/LqAIAOs/TpCxZDntly860y/SzHYai8x48k4t7whENY1CJ41fpMcPlz8xIsrNP3326Wbr0ExwOIvJKAVN1YLYqF8NXWzaVrjo5WbSeI8PiWTYemvLAujVxZssIrApTZBhp55nnwge6K1zTG\
+ \ tomk@air\",\n \"label\": \"ansible-integration-test-ssh_key-ztiapihf-ssh_key1_renamed\"\
+ ,\n \"project_id\": b8c6c653-3c96-446e-987e-9c4d12f25353\n }\n]\n"
+ type: dict
+'''
+
+# End
+
+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,
+)
+
+module_spec = dict(
+ label=SpecField(
+ type=FieldType.string,
+ description=["Name to search for in existing keys."],
+ required=False,
+ ),
+ project_id=SpecField(
+ type=FieldType.string,
+ description=["Name of the project for listing project keys."],
+ required=False,
+ ),
+)
+
+specdoc_examples = [
+ """
+
+- set_fact:
+ desired_name_substring: "tkarasek"
+
+- name: list project ssh keys
+ equinix.cloud.metal_project_ssh_key_info:
+ register: ssh_keys_listed
+
+- name: filter found ssh keys
+ set_fact:
+ both_ssh_keys_listed: "{{ ssh_keys_listed.resources | selectattr('label', 'match', desired_name_substring) }}"
+""",
+]
+
+result_sample = [
+ """
+[
+ {
+ "fingerprint": "70:c1:73:8b:3f:2f:a4:18:ea:4d:79:13:52:7b:c4:3e",
+ "id": "6edfcbc2-17e5-4221-9eac-2f40dbe60daf",
+ "key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt5gwVMhwcCrxyxpMEKwiS0xgit3PIIEgVXt6SQHc8eONq0mYJJ5TOBNTnySqXd9RtSv/Jbf5Aq9BzBGWeoZ6sZfKwh984Ip35StJtjXtyIOlY3skovndtupBIwlGXgX/WQzyLr+G/+Yu9/nhdxQi801PDZnDvKoeomM0rMD29nV+m0ud+GrtsAt6VFul2PxqpypZ1TYviyED6IKo7rgQsQDkE9QHcNdfT1FZWiJbfP7o8TIurQJcAXg+MtLoc8rKKcxFMeZ9FSydgtTC7nP1h558RtECGWiUgaBPI7TpBmcdMtbEfAiBoGT17GWnT8qmy2u5xnEKPD9Qft4w4fjfpw==",
+ "label": "tkarasek",
+ "project_id": b8c6c653-3c96-446e-987e-9c4d12f25353
+ },
+ {
+ "fingerprint": "ba:70:af:b3:0f:0e:7f:e5:eb:97:e2:27:b1:f5:6f:94",
+ "id": "d00c596d-b42a-44a7-ac14-e299b85e73d3",
+ "key": "ssh-dss AAAAB3NzaC1kc3MAAACBAOpXVtmc0Bla98bt0o5/Zj7sb4mHIukgVFZu7F32R3VK1cEKB4rEE8uS0oLS/qMRLue45TWVJwRMYGlPjt3p/VyraelxoyJZLuITIsqa5hBc9w0oTlB5Bmbkn16umW96WCaWEoq/aitpocbRChTiP5biI6FyQTQlIHDaYzBDOi11AAAAFQDUXy7cmuzphDpJSYYTiudiUhVokwAAAIEAyUQ9m8qL/1HPkFe6jbXAvtSSmW27F4c+G2xR5HizaHQzXgBOxPcsOsY17KTU+Ddbg+OF9soWNwSpm9pyVjVmNGqH3S8R1pwvuJF/O2Asy1m6wpWhbPw8JdEBW7WHoptBpfuzJoS2LOzJUEmUu4Eb+xS237KG1d1BVny/49KAoH0AAACBAJKBSsm9Xey0fUN6vYtTQgoYeGxxj/LqAIAOs/TpCxZDntly860y/SzHYai8x48k4t7whENY1CJ41fpMcPlz8xIsrNP3326Wbr0ExwOIvJKAVN1YLYqF8NXWzaVrjo5WbSeI8PiWTYemvLAujVxZssIrApTZBhp55nnwge6K1zTG tomk@air",
+ "label": "ansible-integration-test-ssh_key-ztiapihf-ssh_key1_renamed",
+ "project_id": b8c6c653-3c96-446e-987e-9c4d12f25353
+ }
+]
+""",
+]
+
+SPECDOC_META = getSpecDocMeta(
+ short_description="Gather project SSH keys.",
+ description=(
+ "Gather project SSH keys. Read more about project vs project SSH keys in [Equinix Metal documentation](https://metal.equinix.com/developers/docs/accounts/ssh-keys/#personal-keys-vs-project-keys)."
+ ),
+ examples=specdoc_examples,
+ options=module_spec,
+ return_values={
+ "resources": SpecReturnValue(
+ description="Found resources",
+ type=FieldType.dict,
+ sample=result_sample,
+ ),
+ },
+)
+
+
+def main():
+ module = EquinixModule(
+ argument_spec=SPECDOC_META.ansible_spec,
+ is_info=True,
+ )
+ try:
+ module.params_syntax_check()
+ return_value = {"resources": module.get_list("metal_project_ssh_key")}
+ except Exception as e:
+ tr = traceback.format_exc()
+ module.fail_json(msg=to_native(e), exception=tr)
+ module.exit_json(**return_value)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/integration/targets/metal_project/tasks/main.yml b/tests/integration/targets/metal_project/tasks/main.yml
index de41a4e..dc78a74 100644
--- a/tests/integration/targets/metal_project/tasks/main.yml
+++ b/tests/integration/targets/metal_project/tasks/main.yml
@@ -60,13 +60,13 @@
- assert:
that:
- - "second_project_listed.resources | length == 1"
+ - "second_project_listed.resources | length == 1"
- name: list both projects
equinix.cloud.metal_project_info:
name: "{{ test_prefix }}"
register: both_projects_listed
-
+
- assert:
that:
- "both_projects_listed.resources | length == 2"
@@ -80,7 +80,7 @@
equinix.cloud.metal_project:
id: "{{ second_project.id }}"
state: absent
-
+
always:
- name: Announce teardown start
debug:
diff --git a/tests/integration/targets/metal_project_ssh_key/tasks/main.yml b/tests/integration/targets/metal_project_ssh_key/tasks/main.yml
new file mode 100644
index 0000000..0aa475e
--- /dev/null
+++ b/tests/integration/targets/metal_project_ssh_key/tasks/main.yml
@@ -0,0 +1,140 @@
+- name: metal_project_ssh_key
+ module_defaults:
+ equinix.cloud.metal_project_ssh_key:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_device:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_project_ssh_key_info:
+ metal_api_token: '{{ metal_api_token }}'
+ metal_ua_prefix: '{{ metal_ua_prefix }}'
+ equinix.cloud.metal_project:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_project_info:
+ metal_api_token: '{{ metal_api_token }}'
+ block:
+ - set_fact:
+ test_resource_name_prefix: 'ansible-integration-test-ssh_key'
+ - set_fact:
+ unique_id: "{{ lookup('community.general.random_string', upper=false, numbers=false, special=false) }}"
+ - set_fact:
+ test_prefix: "{{ test_resource_name_prefix }}-{{ unique_id }}"
+ - set_fact:
+ test_key: "ssh-dss AAAAB3NzaC1kc3MAAACBAOpXVtmc0Bla98bt0o5/Zj7sb4mHIukgVFZu7F32R3VK1cEKB4rEE8uS0oLS/qMRLue45TWVJwRMYGlPjt3p/VyraelxoyJZLuITIsqa5hBc9w0oTlB5Bmbkn16umW96WCaWEoq/aitpocbRChTiP5biI6FyQTQlIHDaYzBDOi11AAAAFQDUXy7cmuzphDpJSYYTiudiUhVokwAAAIEAyUQ9m8qL/1HPkFe6jbXAvtSSmW27F4c+G2xR5HizaHQzXgBOxPcsOsY17KTU+Ddbg+OF9soWNwSpm9pyVjVmNGqH3S8R1pwvuJF/O2Asy1m6wpWhbPw8JdEBW7WHoptBpfuzJoS2LOzJUEmUu4Eb+xS237KG1d1BVny/49KAoH0AAACBAJKBSsm9Xey0fUN6vYtTQgoYeGxxj/LqAIAOs/TpCxZDntly860y/SzHYai8x48k4t7whENY1CJ41fpMcPlz8xIsrNP3326Wbr0ExwOIvJKAVN1YLYqF8NXWzaVrjo5WbSeI8PiWTYemvLAujVxZssIrApTZBhp55nnwge6K1zTG tomk@air"
+ - set_fact:
+ test_key2: "ssh-dss AAAAB3NzaC1kc3MAAACBAPWcHWkA06LxBQ67WmNsp1+aZMwNNz9v67pftePlQg94Z1cU4s/5j5S/Fknj7gapWw/ouiOYqXhC2p/hC9/1ARY15t0aHYqLjRhWzs3j8miL1YyXYjqLPLDtgNpX9E09We5ogjbYCB8CCtZrujm/MB6NWvX+T4uG8C/g66I4/bGdAAAAFQDa4SS+q9aQK/XwiqnWpFpAEY74TQAAAIEAklEfXCf1qbUvTquHhtNVKTiKm+qGRsqxnLnu7aduzU81JDFzveF/agkE5x30olTvKECb1PAziDmt63z/obO3Da8TUz0QVdqv81pNWU5JUNiTB8d3rDJU3B66DA6GI305W8qyt0AGUNGR3rDIzNpZY958faBg+TaILRg8ZFNh0PAAAACAdUhJS6bl5M5sQr6XNilHa0nOTk/PB54faGWWMq7zQvxUKJKsDklNTc0MCPjRppyuokbQ6297tq8pEEFqUAyllMvAf75X7DsBQivLzbNuzp41NqFdS/Oka+T1ypRD7mT6g0Kg8yCVYD2ti874wyTpV9riUUaoItveEF3AdC9AzmI= tomk@air"
+
+ - name: create project for test
+ equinix.cloud.metal_project:
+ name: "{{ test_prefix }}-project"
+ register: project
+
+ - assert:
+ that:
+ - project.name == '{{ test_prefix }}-project'
+
+ - name: create first project ssh_key for test
+ equinix.cloud.metal_project_ssh_key:
+ label: "{{ test_prefix }}-ssh_key1"
+ key: "{{ test_key }}"
+ project_id: "{{ project.id }}"
+ register: first_ssh_key
+
+ - name: create first ssh_key for test again, to check idempotence
+ equinix.cloud.metal_project_ssh_key:
+ label: "{{ test_prefix }}-ssh_key1"
+ key: "{{ test_key }}"
+ project_id: "{{ project.id }}"
+ register: first_ssh_key_2
+
+ - assert:
+ that:
+ - first_ssh_key.label == '{{ test_prefix }}-ssh_key1'
+ - first_ssh_key.key == "{{ test_key }}"
+ - first_ssh_key_2.changed == false
+
+ - name: update ssh_key label
+ equinix.cloud.metal_project_ssh_key:
+ id: "{{ first_ssh_key.id }}"
+ key: "{{ test_key }}"
+ label: "{{ test_prefix }}-ssh_key1_renamed"
+
+ - name: fetch updated ssh_key
+ equinix.cloud.metal_project_ssh_key:
+ id: "{{ first_ssh_key.id }}"
+ register: first_ssh_key_updated
+
+ - assert:
+ that:
+ - first_ssh_key_updated.label == '{{ test_prefix }}-ssh_key1_renamed'
+ - first_ssh_key.key == "{{ test_key }}"
+
+ - name: create second ssh_key for test
+ equinix.cloud.metal_project_ssh_key:
+ label: "{{ test_prefix }}-ssh_key2"
+ key: "{{ test_key2 }}"
+ project_id: "{{ project.id }}"
+ register: second_ssh_key
+
+ - name: list ssh_keys
+ equinix.cloud.metal_project_ssh_key_info:
+ project_id: "{{ project.id }}"
+ register: ssh_keys_listed
+
+ - debug:
+ msg: "{{ ssh_keys_listed.resources }}"
+
+ - debug:
+ msg: 'ssh_keys_listed.resources | selectattr("label", "equalto", "{{ test_prefix }}-ssh_key2")'
+
+ - assert:
+ that:
+ - 'ssh_keys_listed.resources | selectattr("label", "equalto", "{{ test_prefix }}-ssh_key2") | length == 1'
+
+ - name: list test ssh keys
+ set_fact:
+ both_ssh_keys_listed: "{{ ssh_keys_listed.resources | selectattr('label', 'match', test_prefix) }}"
+
+ - assert:
+ that:
+ - "both_ssh_keys_listed | length == 2"
+
+ - name: delete second ssh_key
+ equinix.cloud.metal_project_ssh_key:
+ id: "{{ second_ssh_key.id }}"
+ state: absent
+
+ - name: check that deleting nonexistent resource doesn't err
+ equinix.cloud.metal_project_ssh_key:
+ id: "{{ second_ssh_key.id }}"
+ state: absent
+
+ always:
+ - name: Announce teardown start
+ debug:
+ msg: "***** TESTING COMPLETE. COMMENCE TEARDOWN *****"
+
+ - name: list ssh_keys
+ equinix.cloud.metal_project_ssh_key_info:
+ project_id: "{{ project.id }}"
+ register: ssh_keys_listed
+
+ - name: delete test ssh_keys
+ equinix.cloud.metal_project_ssh_key:
+ id: "{{ item.id }}"
+ project_id: "{{ project.id }}"
+ state: absent
+ loop: "{{ ssh_keys_listed.resources }}"
+ when: "test_prefix in item.label"
+ ignore_errors: yes
+
+ - name: list test projects
+ equinix.cloud.metal_project_info:
+ 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