diff --git a/README.md b/README.md
index 61f9719..e0c2215 100755
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
This is repository for Ansible collection registered in Ansible Galaxy as [equinix.cloud](https://galaxy.ansible.com/ui/repo/published/equinix/cloud/). The collection contains various plugins for managing Equinix services.
-For users transitioning from the [equinix.metal collection](https://github.com/equinix/ansible-collection-metal), please refer to our [Migration Guide](MIGRATION.md) for detailed instructions on migrating to this collection (`equinix.cloud`).
+For users transitioning from the [equinix.metal collection](https://github.com/equinix/ansible-collection-metal), please refer to our [Migration Guide](MIGRATION.MD) for detailed instructions on migrating to this collection (`equinix.cloud`).
## Ansible version compatibility
@@ -23,18 +23,20 @@ Modules for managing Equinix infrastructure.
Name | Description |
--- | ------------ |
-[equinix.cloud.metal_connection](./docs/modules/metal_connection.md)|Manage an Interconnection in Equinix Metal|
-[equinix.cloud.metal_device](./docs/modules/metal_device.md)|Create, update, or delete Equinix Metal devices|
-[equinix.cloud.metal_gateway](./docs/modules/metal_gateway.md)|Manage Metal Gateway in Equinix Metal|
-[equinix.cloud.metal_hardware_reservation](./docs/modules/metal_hardware_reservation.md)|Lookup a single hardware_reservation by ID in Equinix Metal|
-[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_vlan](./docs/modules/metal_vlan.md)|Manage a VLAN resource in Equinix Metal|
-[equinix.cloud.metal_vrf](./docs/modules/metal_vrf.md)|Manage a VRF resource in Equinix Metal|
+[equinix.cloud.metal_bgp_session](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_bgp_session.md)|Manage BGP sessions in Equinix Metal|
+[equinix.cloud.metal_connection](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_connection.md)|Manage an Interconnection in Equinix Metal|
+[equinix.cloud.metal_device](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_device.md)|Create, update, or delete Equinix Metal devices|
+[equinix.cloud.metal_gateway](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_gateway.md)|Manage Metal Gateway in Equinix Metal|
+[equinix.cloud.metal_hardware_reservation](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_hardware_reservation.md)|Lookup a single hardware_reservation by ID in Equinix Metal|
+[equinix.cloud.metal_ip_assignment](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_ip_assignment.md)|Manage Equinix Metal IP assignments|
+[equinix.cloud.metal_organization](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_organization.md)|Lookup a single organization by ID in Equinix Metal|
+[equinix.cloud.metal_project](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_project.md)|Manage Projects in Equinix Metal|
+[equinix.cloud.metal_project_bgp_config](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_project_bgp_config.md)|Manage BGP Config for Equinix Metal Project|
+[equinix.cloud.metal_project_ssh_key](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_project_ssh_key.md)|Manage a project ssh key in Equinix Metal|
+[equinix.cloud.metal_reserved_ip_block](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_reserved_ip_block.md)|Create/delete blocks of reserved IP addresses in a project.|
+[equinix.cloud.metal_ssh_key](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_ssh_key.md)|Manage personal SSH keys in Equinix Metal|
+[equinix.cloud.metal_vlan](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_vlan.md)|Manage a VLAN resource in Equinix Metal|
+[equinix.cloud.metal_vrf](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_vrf.md)|Manage a VRF resource in Equinix Metal|
### Info Modules
@@ -43,21 +45,22 @@ Modules for retrieving information about existing Equinix infrastructure.
Name | Description |
--- | ------------ |
-[equinix.cloud.metal_available_ips_info](./docs/modules/metal_available_ips_info.md)|Get list of avialable IP addresses from a reserved IP block|
-[equinix.cloud.metal_connection_info](./docs/modules/metal_connection_info.md)|Gather information about Interconnections|
-[equinix.cloud.metal_device_info](./docs/modules/metal_device_info.md)|Select list of Equinix Metal devices|
-[equinix.cloud.metal_gateway_info](./docs/modules/metal_gateway_info.md)|Gather information about Metal Gateways|
-[equinix.cloud.metal_hardware_reservation_info](./docs/modules/metal_hardware_reservation_info.md)|Gather information about Equinix Metal hardware_reservations|
-[equinix.cloud.metal_ip_assignment_info](./docs/modules/metal_ip_assignment_info.md)|Gather IP address assignments for a device|
-[equinix.cloud.metal_metro_info](./docs/modules/metal_metro_info.md)|Gather information about Equinix Metal metros|
-[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|
-[equinix.cloud.metal_vlan_info](./docs/modules/metal_vlan_info.md)|Gather VLANs.|
-[equinix.cloud.metal_vrf_info](./docs/modules/metal_vrf_info.md)|Gather VRFs|
+[equinix.cloud.metal_available_ips_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_available_ips_info.md)|Get list of avialable IP addresses from a reserved IP block|
+[equinix.cloud.metal_bgp_session_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_bgp_session_info.md)|Gather information BGP sessions in Equinix Metal|
+[equinix.cloud.metal_connection_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_connection_info.md)|Gather information about Interconnections|
+[equinix.cloud.metal_device_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_device_info.md)|Select list of Equinix Metal devices|
+[equinix.cloud.metal_gateway_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_gateway_info.md)|Gather information about Metal Gateways|
+[equinix.cloud.metal_hardware_reservation_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_hardware_reservation_info.md)|Gather information about Equinix Metal hardware_reservations|
+[equinix.cloud.metal_ip_assignment_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_ip_assignment_info.md)|Gather IP address assignments for a device|
+[equinix.cloud.metal_metro_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_metro_info.md)|Gather information about Equinix Metal metros|
+[equinix.cloud.metal_operating_system_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_operating_system_info.md)|Gather information about Operating Systems available for devices in Equinix Metal|
+[equinix.cloud.metal_organization_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_organization_info.md)|Gather information about Equinix Metal organizations|
+[equinix.cloud.metal_project_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_project_info.md)|Gather information about Equinix Metal projects|
+[equinix.cloud.metal_project_ssh_key_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/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/0.3.0/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/0.3.0/docs/modules/metal_ssh_key_info.md)|Gather personal SSH keys|
+[equinix.cloud.metal_vlan_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_vlan_info.md)|Gather VLANs.|
+[equinix.cloud.metal_vrf_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_vrf_info.md)|Gather VRFs|
### Inventory Plugins
@@ -66,7 +69,7 @@ Dynamically add Equinix infrastructure to an Ansible inventory.
Name |
--- |
-[equinix.cloud.metal_device](./docs/inventory/metal_device.rst)|
+[equinix.cloud.metal_device](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/inventory/metal_device.md)|
@@ -83,7 +86,7 @@ The Python module dependencies are not installed by `ansible-galaxy`. They can
be manually installed using pip:
```shell
-pip install -r https://raw.githubusercontent.com/equinix-labs/ansible-collection-equinix/main/requirements.txt
+pip install -r https://raw.githubusercontent.com/equinix-labs/ansible-collection-equinix/0.3.0/requirements.txt
```
## Usage
diff --git a/docs/modules/metal_bgp_session.md b/docs/modules/metal_bgp_session.md
new file mode 100644
index 0000000..1db1ee0
--- /dev/null
+++ b/docs/modules/metal_bgp_session.md
@@ -0,0 +1,80 @@
+# metal_bgp_session
+
+Manage BGP sessions in Equinix Metal.Create, update or delete BGP session. To look up an existing session, pass only the *id* attribute.
+
+
+- [Examples](#examples)
+- [Parameters](#parameters)
+- [Return Values](#return-values)
+
+## Examples
+
+```yaml
+- name: Start first test bgp session
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session:
+ device_id: 8ea9837a-6d19-4607-b166-f7f7bb04b022
+ address_family: ipv6
+ default_route: true
+
+```
+
+```yaml
+- name: Delete bgp session
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session:
+ id: 1273edef-39af-4df0-85bb-02a847a484d1
+ state: absent
+
+```
+
+
+
+
+
+
+
+
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `id` |
`str` | Optional | UUID of the BGP session to look up |
+| `device_id` | `str` | Optional | Device ID for the BGP session |
+| `address_family` | `str` | Optional | BGP session address family, "ipv4" or "ipv6" |
+| `default_route` | `bool` | Optional | Boolean flag to set the default route policy. False by default. |
+
+
+
+
+
+
+## Return Values
+
+- `metal_bgp_session` - The module object
+
+ - Sample Response:
+ ```json
+
+ [
+ {
+ "address_family": "ipv4",
+ "default_route": true,
+ "device_id": "2066d33e-7c43-4d78-87a3-aaa434913f7f",
+ "id": "fc2d43e6-d606-47f7-9611-9d77aee443b5"
+ },
+ {
+ "address_family": "ipv6",
+ "default_route": true,
+ "device_id": "bfab58c0-0723-49aa-a64e-6caf1b8ea2e2",
+ "id": "277d4a7a-82dd-4e7c-bf79-8a1de6882982"
+ }
+ ]
+
+ ```
+
+
diff --git a/docs/modules/metal_bgp_session_info.md b/docs/modules/metal_bgp_session_info.md
new file mode 100644
index 0000000..b384557
--- /dev/null
+++ b/docs/modules/metal_bgp_session_info.md
@@ -0,0 +1,62 @@
+# metal_bgp_session_info
+
+Gather information BGP sessions in Equinix Metal. You can fetch it by device ID or project ID.
+
+
+- [Examples](#examples)
+- [Parameters](#parameters)
+- [Return Values](#return-values)
+
+## Examples
+
+```yaml
+- name: Gather information about all BGP sessions in a project
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session_info:
+ project_id: 2a5122b9-c323-4d5c-b53c-9ad3f54273e7
+
+```
+
+```yaml
+
+```
+
+
+
+
+
+
+
+
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `device_id` | `str` | Optional | Find BGP sessions by device ID. |
+| `project_id` | `str` | Optional | Find BGP sessions by project ID. |
+
+
+
+
+
+
+## Return Values
+
+- `resources` - Found resources
+
+ - Sample Response:
+ ```json
+ [
+ {
+ "address_family": "ipv6",
+ "default_route": true,
+ "device_id": "b068984f-f7d9-43a2-aa45-de04dcf4fe06",
+ "id": "03912bd6-a158-47ad-8bc7-c93df338fe0d"
+ }
+ ]
+ ```
+
+
diff --git a/docs/modules/metal_project_bgp_config.md b/docs/modules/metal_project_bgp_config.md
new file mode 100644
index 0000000..5fb1ca6
--- /dev/null
+++ b/docs/modules/metal_project_bgp_config.md
@@ -0,0 +1,62 @@
+# metal_project_bgp_config
+
+You can use this module to enable BGP Config for a project. To lookup BGP Config of an existing project, call the module only with `project_id`.
+
+
+- [Examples](#examples)
+- [Parameters](#parameters)
+- [Return Values](#return-values)
+
+## Examples
+
+```yaml
+- name: Enable local BGP Config in Equinix Metal project
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_bgp_config:
+ deployment_type: local
+ asn: 65000
+ md5: null
+ use_case: "ansible test"
+ project_id: "{{ test_project.id }}"
+
+```
+
+
+
+
+
+
+
+
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `project_id` | `str` | **Required** | UUID of the project where BGP Config should be enabled |
+| `asn` | `int` | **Required** | Autonomous System Number for local BGP deployment |
+| `deployment_type` | `str` | **Required** | "local" or "global". Local deployment type is likely to be usable immediately, "global" will need to be reviewed by Equinix Metal support. |
+| `md5` | `str` | Optional | Password for BGP session in plaintext (not a checksum) |
+| `use_case` | `str` | Optional | Description of your BGP use-case for Equinix Metal support |
+
+
+
+
+
+
+## Return Values
+
+- `metal_project_bgp_config` - The module object
+
+ - Sample Response:
+ ```json
+
+ {
+ "changed": true
+ }
+
+ ```
+
+
diff --git a/plugins/module_utils/metal/api_routes.py b/plugins/module_utils/metal/api_routes.py
index 172b7c1..62d076b 100644
--- a/plugins/module_utils/metal/api_routes.py
+++ b/plugins/module_utils/metal/api_routes.py
@@ -69,6 +69,12 @@ def get_routes(mpc):
equinix_metal.MetalGatewaysApi(mpc).find_metal_gateway_by_id,
extra_kwargs={"include": ["ip_reservation"]},
),
+ ("metal_bgp_session", action.GET): spec_types.Specs(
+ equinix_metal.BGPApi(mpc).find_bgp_session_by_id,
+ ),
+ ('metal_project_bgp_config', action.GET): spec_types.Specs(
+ equinix_metal.BGPApi(mpc).find_bgp_config_by_project,
+ ),
# LISTERS
('metal_project_device', action.LIST): spec_types.Specs(
@@ -140,6 +146,14 @@ def get_routes(mpc):
{'project_id': 'project_id'},
extra_kwargs={"include": ["ip_reservation"]},
),
+ ('metal_bgp_session', action.LIST): spec_types.Specs(
+ equinix_metal.DevicesApi(mpc).find_bgp_sessions,
+ {'id': 'device_id'},
+ ),
+ ('metal_bgp_session_by_project', action.LIST): spec_types.Specs(
+ equinix_metal.BGPApi(mpc).find_bgp_config_by_project,
+ {'id': 'project_id'},
+ ),
# DELETERS
('metal_device', action.DELETE): spec_types.Specs(
@@ -170,6 +184,10 @@ def get_routes(mpc):
equinix_metal.MetalGatewaysApi(mpc).delete_metal_gateway,
extra_kwargs={"include": ["ip_reservation"]},
),
+ ('metal_bgp_session', action.DELETE): spec_types.Specs(
+ equinix_metal.BGPApi(mpc).delete_bgp_session,
+ ),
+
# CREATORS
('metal_device', action.CREATE): spec_types.Specs(
@@ -249,6 +267,16 @@ def get_routes(mpc):
{"include": ["ip_reservation"]},
),
+ ('metal_bgp_session', action.CREATE): spec_types.Specs(
+ equinix_metal.DevicesApi(mpc).create_bgp_session,
+ {'id': 'device_id'},
+ equinix_metal.BGPSessionInput,
+ ),
+ ('metal_project_bgp_config', action.CREATE): spec_types.Specs(
+ equinix_metal.BGPApi(mpc).request_bgp_config,
+ {'id': 'project_id'},
+ equinix_metal.BgpConfigRequestInput,
+ ),
# UPDATERS
('metal_device', action.UPDATE): spec_types.Specs(
@@ -286,4 +314,9 @@ def get_routes(mpc):
{},
equinix_metal.VrfUpdateInput,
),
+ ('metal_bgp_session', action.UPDATE): spec_types.Specs(
+ equinix_metal.BGPApi(mpc).update_bgp_session,
+ {},
+ equinix_metal.BGPSessionInput,
+ ),
}
diff --git a/plugins/module_utils/metal/metal_api.py b/plugins/module_utils/metal/metal_api.py
index d6a6615..828c844 100644
--- a/plugins/module_utils/metal/metal_api.py
+++ b/plugins/module_utils/metal/metal_api.py
@@ -149,6 +149,8 @@ def extract_ids_from_projects_hrefs(resource: dict):
'interconnections',
'vrfs',
'metal_gateways',
+ 'bgp_sessions', # metal_bgp_session
+ 'sessions', # metal_bgp_session_info
]
@@ -209,7 +211,6 @@ def get_assignment_address(resource: dict):
"vxlan": "vxlan",
}
-
METAL_CONNECTION_RESPONSE_ATTRIBUTE_MAP = {
'id': 'id',
'name': 'name',
@@ -253,6 +254,23 @@ def private_ipv4_subnet_size(resource: dict):
'metal_state': optional_str('state'),
}
+METAL_BGP_SESSION_RESPONSE_ATTRIBUTE_MAP = {
+ 'id': 'id',
+ 'address_family': 'address_family',
+ 'device_id': 'device.id',
+ 'default_route': 'default_route',
+}
+
+METAL_PROJECT_BGP_CONFIG_RESPONSE_ATTRIBUTE_MAP = {
+ 'project_id': optional('project.id'),
+ 'asn': optional('asn'),
+ 'deployment_type': optional('deployment_type'),
+ 'md5': 'md5',
+ 'max_prefix': 'max_prefix',
+ 'id': optional('id'),
+ 'status': optional('status'),
+
+}
def get_attribute_mapper(resource_type):
"""
@@ -270,6 +288,8 @@ def get_attribute_mapper(resource_type):
'metal_connection_project_vlanfabric', 'metal_connection_project_vrf'])
vrf_resources = set(['metal_vrf'])
gateway_resources = set(["metal_gateway", "metal_gateway_vrf"])
+ bgp_resources = {'metal_bgp_session', 'metal_bgp_session_by_project'}
+ project_bgp_config_resources = {'metal_project_bgp_config'}
if resource_type in device_resources:
return METAL_DEVICE_RESPONSE_ATTRIBUTE_MAP
elif resource_type in project_resources:
@@ -296,6 +316,10 @@ def get_attribute_mapper(resource_type):
return METAL_VRF_RESPONSE_ATTRIBUTE_MAP
elif resource_type in gateway_resources:
return METAL_GATEWAY_RESPONSE_ATTRIBUTE_MAP
+ elif resource_type in bgp_resources:
+ return METAL_BGP_SESSION_RESPONSE_ATTRIBUTE_MAP
+ elif resource_type in project_bgp_config_resources:
+ return METAL_PROJECT_BGP_CONFIG_RESPONSE_ATTRIBUTE_MAP
else:
raise NotImplementedError("No mapper for resource type %s" % resource_type)
@@ -311,6 +335,8 @@ def call(resource_type, action, equinix_metal_client, params={}):
call = api_routes.build_api_call(conf, params)
response = call.do()
+ # uncomment to check response in /tmp/q
+ # import q; q(response)
if action == action.DELETE:
return None
attribute_mapper = get_attribute_mapper(resource_type)
diff --git a/plugins/modules/metal_bgp_session.py b/plugins/modules/metal_bgp_session.py
new file mode 100644
index 0000000..ebe3bfc
--- /dev/null
+++ b/plugins/modules/metal_bgp_session.py
@@ -0,0 +1,215 @@
+#!/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 BGP sessions in Equinix Metal.Create, update or delete BGP session.
+ To look up an existing session, pass only the *id* attribute.
+module: metal_bgp_session
+notes: []
+options:
+ address_family:
+ description:
+ - BGP session address family, "ipv4" or "ipv6"
+ required: false
+ type: str
+ default_route:
+ description:
+ - Boolean flag to set the default route policy. False by default.
+ required: false
+ type: bool
+ device_id:
+ description:
+ - Device ID for the BGP session
+ required: false
+ type: str
+ id:
+ description:
+ - UUID of the BGP session to look up
+ required: false
+ type: str
+requirements: null
+short_description: Manage BGP sessions in Equinix Metal
+'''
+EXAMPLES = '''
+- name: Start first test bgp session
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session:
+ device_id: 8ea9837a-6d19-4607-b166-f7f7bb04b022
+ address_family: ipv6
+ default_route: true
+- name: Delete bgp session
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session:
+ id: 1273edef-39af-4df0-85bb-02a847a484d1
+ state: absent
+'''
+RETURN = '''
+metal_bgp_session:
+ description: The module object
+ returned: always
+ sample:
+ - "\n [\n {\n \"address_family\": \"ipv4\",\n \"default_route\"\
+ : true,\n \"device_id\": \"2066d33e-7c43-4d78-87a3-aaa434913f7f\",\n\
+ \ \"id\": \"fc2d43e6-d606-47f7-9611-9d77aee443b5\"\n },\n \
+ \ {\n \"address_family\": \"ipv6\",\n \"default_route\"\
+ : true,\n \"device_id\": \"bfab58c0-0723-49aa-a64e-6caf1b8ea2e2\",\n\
+ \ \"id\": \"277d4a7a-82dd-4e7c-bf79-8a1de6882982\"\n }\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_spec = dict(
+ id=SpecField(
+ type=FieldType.string,
+ description="UUID of the BGP session to look up",
+ ),
+ device_id=SpecField(
+ type=FieldType.string,
+ description="Device ID for the BGP session",
+ ),
+ address_family=SpecField(
+ type=FieldType.string,
+ description="BGP session address family, \"ipv4\" or \"ipv6\"",
+ editable=False,
+ ),
+ default_route=SpecField(
+ type=FieldType.bool,
+ description="Boolean flag to set the default route policy. False by default.",
+ editable=False,
+ ),
+)
+
+
+specdoc_examples = ['''
+- name: Start first test bgp session
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session:
+ device_id: 8ea9837a-6d19-4607-b166-f7f7bb04b022
+ address_family: ipv6
+ default_route: true
+''', '''
+- name: Delete bgp session
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session:
+ id: 1273edef-39af-4df0-85bb-02a847a484d1
+ state: absent
+''',
+]
+
+result_sample = ['''
+ [
+ {
+ "address_family": "ipv4",
+ "default_route": true,
+ "device_id": "2066d33e-7c43-4d78-87a3-aaa434913f7f",
+ "id": "fc2d43e6-d606-47f7-9611-9d77aee443b5"
+ },
+ {
+ "address_family": "ipv6",
+ "default_route": true,
+ "device_id": "bfab58c0-0723-49aa-a64e-6caf1b8ea2e2",
+ "id": "277d4a7a-82dd-4e7c-bf79-8a1de6882982"
+ }
+ ]
+''']
+
+MUTABLE_ATTRIBUTES = [
+ k for k, v in module_spec.items() if v.editable
+]
+
+SPECDOC_META = getSpecDocMeta(
+ short_description='Manage BGP sessions in Equinix Metal',
+ description=(
+ 'Manage BGP sessions in Equinix Metal.'
+ 'Create, update or delete BGP session. To look up an existing session, pass only the *id* attribute.'
+ ),
+ examples=specdoc_examples,
+ options=module_spec,
+ return_values={
+ "metal_bgp_session": SpecReturnValue(
+ description='The module object',
+ type=FieldType.dict,
+ sample=result_sample,
+ ),
+ },
+)
+
+
+def main():
+ module = EquinixModule(
+ argument_spec=SPECDOC_META.ansible_spec,
+ required_one_of=[("id", "address_family"), ("id", "default_route"), ("id", "device_id")],
+ )
+
+ state = module.params.get("state")
+ changed = False
+
+ fetched = {}
+ try:
+ module.params_syntax_check()
+ if module.params.get("id"):
+ tolerate_not_found = state == "absent"
+ fetched = module.get_by_id("metal_bgp_session", tolerate_not_found)
+ else:
+ fetched = module.get_one_from_list(
+ "metal_bgp_session",
+ ["device_id"],
+ )
+
+ 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_bgp_session")
+ changed = True
+
+ else:
+ module.delete_by_id("metal_bgp_session")
+ changed = True
+ elif state == "present":
+ fetched = module.create("metal_bgp_session")
+ if 'id' not in fetched:
+ module.fail_json(msg="UUID not found in resource creation response")
+ changed = True
+
+ except Exception as e:
+ tb = traceback.format_exc()
+ module.fail_json(msg="Error in metal_bgp_session: {0}".format(to_native(e)),
+ exception=tb)
+
+ fetched = {} if not fetched else fetched
+ fetched.update({'changed': changed})
+ module.exit_json(**fetched)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/plugins/modules/metal_bgp_session_info.py b/plugins/modules/metal_bgp_session_info.py
new file mode 100644
index 0000000..162e9e7
--- /dev/null
+++ b/plugins/modules/metal_bgp_session_info.py
@@ -0,0 +1,126 @@
+#!/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 BGP sessions in Equinix Metal. You can fetch it by
+ device ID or project ID.
+module: metal_bgp_session_info
+notes: []
+options:
+ device_id:
+ description:
+ - Find BGP sessions by device ID.
+ required: false
+ type: str
+ project_id:
+ description:
+ - Find BGP sessions by project ID.
+ required: false
+ type: str
+requirements: null
+short_description: Gather information BGP sessions in Equinix Metal
+'''
+EXAMPLES = '''
+- name: Gather information about all BGP sessions in a project
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session_info:
+ project_id: 2a5122b9-c323-4d5c-b53c-9ad3f54273e7
+'''
+RETURN = '''
+resources:
+ description: Found resources
+ returned: always
+ sample:
+ - "[\n {\n \"address_family\": \"ipv6\",\n \"default_route\": true,\n \
+ \ \"device_id\": \"b068984f-f7d9-43a2-aa45-de04dcf4fe06\",\n \"id\": \"03912bd6-a158-47ad-8bc7-c93df338fe0d\"\
+ \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(
+ device_id=SpecField(
+ type=FieldType.string,
+ description=['Find BGP sessions by device ID.'],
+ ),
+ project_id=SpecField(
+ type=FieldType.string,
+ description=['Find BGP sessions by project ID.'],
+ ),
+)
+
+specdoc_examples = ['''
+- name: Gather information about all BGP sessions in a project
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_bgp_session_info:
+ project_id: 2a5122b9-c323-4d5c-b53c-9ad3f54273e7
+''', '''
+''',
+ ]
+
+result_sample = ['''[
+ {
+ "address_family": "ipv6",
+ "default_route": true,
+ "device_id": "b068984f-f7d9-43a2-aa45-de04dcf4fe06",
+ "id": "03912bd6-a158-47ad-8bc7-c93df338fe0d"
+ }
+]''',
+]
+
+SPECDOC_META = getSpecDocMeta(
+ short_description="Gather information BGP sessions in Equinix Metal",
+ description=(
+ 'Gather information BGP sessions in Equinix Metal. You can fetch it by device ID or project ID.'
+ ),
+ 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()
+
+ if 'project_id' in module.params:
+ return_value = {'resources': module.get_list("metal_bgp_session_by_project")}
+ else:
+ return_value = {'resources': module.get_list("metal_bgp_session")}
+
+ 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/plugins/modules/metal_project.py b/plugins/modules/metal_project.py
index 9cc4883..efe7757 100644
--- a/plugins/modules/metal_project.py
+++ b/plugins/modules/metal_project.py
@@ -255,7 +255,6 @@ def main():
module.params['id'] = fetched['id']
fetched = module.update_by_id({"backend_transfer_enabled": True}, "metal_project")
- # TODO: add support for bgp_config once we have a module
else:
fetched = {}
except Exception as e:
diff --git a/plugins/modules/metal_project_bgp_config.py b/plugins/modules/metal_project_bgp_config.py
new file mode 100644
index 0000000..0a04318
--- /dev/null
+++ b/plugins/modules/metal_project_bgp_config.py
@@ -0,0 +1,200 @@
+#!/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 METAL_PROJECT_ARGS are generated by
+# ansible_specdoc. Do not edit them directly.
+
+DOCUMENTATION = '''
+author: Equinix DevRel Team (@equinix)
+description: 'You can use this module to enable BGP Config for a project. To lookup
+ BGP Config of an existing project, call the module only with `project_id`. '
+module: metal_project_bgp_config
+notes: []
+options:
+ asn:
+ description:
+ - Autonomous System Number for local BGP deployment
+ required: true
+ type: int
+ deployment_type:
+ description:
+ - '"local" or "global". Local deployment type is likely to be usable immediately, '
+ - '"global" will need to be reviewed by Equinix Metal support.'
+ required: true
+ type: str
+ md5:
+ description:
+ - Password for BGP session in plaintext (not a checksum)
+ required: false
+ type: str
+ project_id:
+ description:
+ - UUID of the project where BGP Config should be enabled
+ required: true
+ type: str
+ use_case:
+ description:
+ - Description of your BGP use-case for Equinix Metal support
+ required: false
+ type: str
+requirements: null
+short_description: Manage BGP Config for Equinix Metal Project
+'''
+EXAMPLES = '''
+- name: Enable local BGP Config in Equinix Metal project
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_bgp_config:
+ deployment_type: local
+ asn: 65000
+ md5: null
+ use_case: ansible test
+ project_id: '{{ test_project.id }}'
+'''
+RETURN = '''
+metal_project_bgp_config:
+ description: The module object
+ returned: always
+ sample:
+ - "\n{\n \"changed\": true\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_spec = dict(
+ project_id=SpecField(
+ type=FieldType.string,
+ description=['UUID of the project where BGP Config should be enabled'],
+ required=True,
+ editable=False,
+ ),
+ asn=SpecField(
+ type=FieldType.integer,
+ required=True,
+ description=['Autonomous System Number for local BGP deployment'],
+ editable=False,
+ ),
+ deployment_type=SpecField(
+ type=FieldType.string,
+ required=True,
+ description=[
+ '"local" or "global". Local deployment type is likely to be usable immediately, ',
+ '"global" will need to be reviewed by Equinix Metal support.',
+ ],
+ editable=False,
+ ),
+ md5=SpecField(
+ type=FieldType.string,
+ description=['Password for BGP session in plaintext (not a checksum)'],
+ editable=False,
+ ),
+ use_case=SpecField(
+ type=FieldType.string,
+ description=['Description of your BGP use-case for Equinix Metal support'],
+ editable=False,
+ ),
+)
+
+
+specdoc_examples = [
+ '''
+- name: Enable local BGP Config in Equinix Metal project
+ hosts: localhost
+ tasks:
+ - equinix.cloud.metal_project_bgp_config:
+ deployment_type: local
+ asn: 65000
+ md5: null
+ use_case: "ansible test"
+ project_id: "{{ test_project.id }}"
+''',
+]
+
+result_sample = ['''
+{
+ "changed": true
+}
+''']
+
+MUTABLE_ATTRIBUTES = [
+ k for k, v in module_spec.items() if v.editable
+]
+
+SPECDOC_META = getSpecDocMeta(
+ short_description='Manage BGP Config for Equinix Metal Project',
+ description=(
+ 'You can use this module to enable BGP Config for a project. To lookup BGP Config of an existing project, call the module only with `project_id`. '
+ ),
+ examples=specdoc_examples,
+ options=module_spec,
+ return_values={
+ "metal_project_bgp_config": SpecReturnValue(
+ description='The module object',
+ type=FieldType.dict,
+ sample=result_sample,
+ ),
+ },
+)
+
+
+def main():
+ module = EquinixModule(
+ argument_spec=SPECDOC_META.ansible_spec,
+ )
+
+ state = module.params.get("state")
+ changed = False
+
+ try:
+ module.params_syntax_check()
+
+ module.params['id'] = module.params.get("project_id")
+ tolerate_not_found = state == "absent"
+ fetched = module.get_by_id("metal_project_bgp_config", tolerate_not_found)
+
+ if not fetched.get('id'):
+ # api returns {max_prefix: 10, 'md5': None} even if config not exists
+ # optional RESPONSE_ATTRIBUTE_MAP puts other attributes as Nones
+ fetched = {}
+
+ if fetched:
+ if state == "present":
+ diff = get_diff(module.params, fetched, MUTABLE_ATTRIBUTES)
+ if diff:
+ module.fail_json(msg="BGP config cannot be updated")
+
+ else:
+ module.fail_json(msg="BGP config cannot be deleted. Please delete project")
+ elif state == "present":
+ fetched = module.create("metal_project_bgp_config")
+ changed = True
+
+ except Exception as e:
+ tb = traceback.format_exc()
+ module.fail_json(msg="Error in metal_project_bgp_config: {0}".format(to_native(e)),
+ exception=tb)
+
+ fetched.update({'changed': changed})
+ module.exit_json(**fetched)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/integration/inventory b/tests/integration/inventory
index 7c937f8..c1ff27c 100644
--- a/tests/integration/inventory
+++ b/tests/integration/inventory
@@ -1,2 +1,2 @@
[testgroup]
-testhost ansible_connection="local" ansible_pipelining="yes" ansible_python_interpreter="/usr/bin/python3"
+testhost ansible_connection="local" ansible_pipelining="yes" ansible_python_interpreter="/usr/bin/python3.8"
diff --git a/tests/integration/targets/metal_bgp_session/tasks/main.yml b/tests/integration/targets/metal_bgp_session/tasks/main.yml
new file mode 100644
index 0000000..ea2d012
--- /dev/null
+++ b/tests/integration/targets/metal_bgp_session/tasks/main.yml
@@ -0,0 +1,166 @@
+- name: metal_project
+ module_defaults:
+ equinix.cloud.metal_project:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_bgp_session:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_project_info:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_bgp_session_info:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_device:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_device_info:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_project_bgp_config:
+ metal_api_token: '{{ metal_api_token }}'
+ block:
+ - set_fact:
+ test_resource_name_prefix: 'ansible-integration-test-bgp-session'
+ - set_fact:
+ unique_id: "{{ lookup('password', '/dev/null chars=ascii_lowercase,digits length=8') }}"
+ - set_fact:
+ test_prefix: "{{ test_resource_name_prefix }}-{{ unique_id }}"
+ - set_fact:
+ test_os: ubuntu_22_04
+ - set_fact:
+ test_plan: c3.small.x86
+ - set_fact:
+ wait_seconds: 1200
+
+ - name: create project for test
+ equinix.cloud.metal_project:
+ name: "{{ test_prefix }}"
+ register: test_project
+
+ - name: enable project bgp config
+ equinix.cloud.metal_project_bgp_config:
+ deployment_type: local
+ asn: 65000
+ md5: null
+ use_case: "ansible test"
+ project_id: "{{ test_project.id }}"
+
+ - name: start first test device
+ equinix.cloud.metal_device:
+ project_id: "{{ test_project.id }}"
+ hostname: "{{ test_prefix }}-dev1"
+ operating_system: "{{ test_os }}"
+ plan: "{{ test_plan }}"
+ metro: "{{ metal_test_metro }}"
+ state: present
+ provisioning_wait_seconds: "{{ wait_seconds }}"
+ register: test_device_1
+
+ - name: start first test bgp session
+ equinix.cloud.metal_bgp_session:
+ device_id: "{{ test_device_1.id }}"
+ address_family: ipv6
+ default_route: true
+ register: test_bgp_session_1
+
+ - debug:
+ var: test_bgp_session_1
+
+ - name: start first test bgp session again (idempotence test)
+ equinix.cloud.metal_bgp_session:
+ device_id: "{{ test_device_1.id }}"
+ address_family: ipv6
+ default_route: true
+ register: test_bgp_session_1d
+
+ - name: start second test device
+ equinix.cloud.metal_device:
+ project_id: "{{ test_project.id }}"
+ hostname: "{{ test_prefix }}-dev2"
+ operating_system: "{{ test_os }}"
+ plan: "{{ test_plan }}"
+ metro: "{{ metal_test_metro }}"
+ state: present
+ provisioning_wait_seconds: "{{ wait_seconds }}"
+ register: test_device_2
+
+
+ - name: start second test bgp session again
+ equinix.cloud.metal_bgp_session:
+ device_id: "{{ test_device_2.id }}"
+ address_family: ipv4
+ default_route: true
+ register: test_bgp_session_2
+
+ - name: assert bgp sessions
+ assert:
+ that:
+ - "test_bgp_session_1.address_family == 'ipv6'"
+ - "test_bgp_session_1d.changed == false"
+
+ - name: list bgp sessions
+ equinix.cloud.metal_bgp_session_info:
+ project_id: "{{ test_project.id }}"
+ register: both_bgp_sessions
+
+ - debug:
+ var: both_bgp_sessions
+
+ - name: assert both bgp sessions selected
+ assert:
+ that:
+ - "both_bgp_sessions.resources|length == 2"
+
+ - name: delete first bgp session
+ equinix.cloud.metal_bgp_session:
+ id: "{{ test_bgp_session_1.id }}"
+ state: absent
+
+ - name: delete first bgp session again (idempotence check)
+ equinix.cloud.metal_bgp_session:
+ id: "{{ test_bgp_session_1.id }}"
+ state: absent
+ register: test_deletion
+
+ - assert:
+ that:
+ - "test_deletion.changed == false"
+
+ always:
+ - name: Announce teardown start
+ debug:
+ msg: "***** TESTING COMPLETE. COMMENCE TEARDOWN *****"
+
+ - name: list test projects
+ equinix.cloud.metal_project_info:
+ name: "{{ test_prefix }}"
+ register: test_projects
+
+ - name: list devices in test projects
+ equinix.cloud.metal_device_info:
+ project_id: "{{ item.id }}"
+ register: "test_devices"
+ loop: "{{ test_projects.resources }}"
+
+ - name: list bgp sessions in test projects
+ equinix.cloud.metal_bgp_session_info:
+ project_id: "{{ item.id }}"
+ register: "test_bgp_sessions"
+ loop: "{{ test_projects.resources }}"
+
+ - name: delete bgp sessions
+ equinix.cloud.metal_bgp_session:
+ id: "{{ item.id }}"
+ state: absent
+ ignore_errors: yes
+ loop: "{{ test_bgp_sessions.results | map(attribute='resources') | flatten }}"
+
+ - name: delete test devices
+ equinix.cloud.metal_device:
+ id: "{{ item.id }}"
+ state: absent
+ ignore_errors: yes
+ loop: "{{ test_devices.results | map(attribute='resources') | flatten }}"
+
+ - name: delete test projects
+ equinix.cloud.metal_project:
+ id: "{{ item.id }}"
+ state: absent
+ ignore_errors: yes
+ loop: "{{ test_projects.resources }}"
diff --git a/tests/integration/targets/metal_project_bgp_config/tasks/main.yml b/tests/integration/targets/metal_project_bgp_config/tasks/main.yml
new file mode 100644
index 0000000..5c0d034
--- /dev/null
+++ b/tests/integration/targets/metal_project_bgp_config/tasks/main.yml
@@ -0,0 +1,59 @@
+- name: metal_project
+ module_defaults:
+ equinix.cloud.metal_project:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_project_info:
+ metal_api_token: '{{ metal_api_token }}'
+ equinix.cloud.metal_project_bgp_config:
+ metal_api_token: '{{ metal_api_token }}'
+ block:
+ - set_fact:
+ test_resource_name_prefix: 'ansible-integration-test-bgp-config'
+ - set_fact:
+ unique_id: "{{ lookup('password', '/dev/null chars=ascii_lowercase,digits length=8') }}"
+ - set_fact:
+ test_prefix: "{{ test_resource_name_prefix }}-{{ unique_id }}"
+
+ - name: create project for test
+ equinix.cloud.metal_project:
+ name: "{{ test_prefix }}"
+ register: test_project
+
+ - name: enable project bgp config
+ equinix.cloud.metal_project_bgp_config:
+ deployment_type: local
+ asn: 65000
+ md5: null
+ use_case: "ansible test"
+ project_id: "{{ test_project.id }}"
+ register: test_bgp_config1
+
+ - name: enable project bgp config again (idempotence)
+ equinix.cloud.metal_project_bgp_config:
+ deployment_type: local
+ asn: 65000
+ md5: null
+ use_case: "ansible test"
+ project_id: "{{ test_project.id }}"
+ register: test_bgp_config2
+
+ - assert:
+ that:
+ - "test_bgp_config2.changed == False"
+
+ always:
+ - name: Announce teardown start
+ debug:
+ msg: "***** TESTING COMPLETE. COMMENCE TEARDOWN *****"
+
+ - name: list test projects
+ equinix.cloud.metal_project_info:
+ name: "{{ test_prefix }}"
+ register: test_projects
+
+ - name: delete test projects
+ equinix.cloud.metal_project:
+ id: "{{ item.id }}"
+ state: absent
+ ignore_errors: yes
+ loop: "{{ test_projects.resources }}"