Skip to content

Commit

Permalink
feat: module metal_plan_info (#146)
Browse files Browse the repository at this point in the history
Ansible wrapper of

https://github.com/equinix-labs/metal-python/blob/main/equinix_metal/equinix_metal/api/plans_api.py#L50

which is a wrapper of:

https://deploy.equinix.com/developers/api/metal/#tag/Plans/operation/findPlans

Temporary as draft, until i find a way to make category, type, include
and exclude filters running
  • Loading branch information
t0mk authored Feb 22, 2024
2 parents e66b497 + 2a16c0d commit 7691455
Show file tree
Hide file tree
Showing 6 changed files with 379 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Name | Description |
[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_plan_info](https://github.com/equinix-labs/ansible-collection-equinix/blob/0.3.0/docs/modules/metal_plan_info.md)|Gather information about Equinix Metal plans|
[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|
Expand Down
96 changes: 96 additions & 0 deletions docs/modules/metal_plan_info.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# metal_plan_info

Gather information about Equinix Metal plans


- [Examples](#examples)
- [Parameters](#parameters)
- [Return Values](#return-values)

## Examples

```yaml
- name: Gather information about all plans
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info

```

```yaml
- name: Gather information for plans with storage category
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
categories: ['storage']

```

```yaml
- name: Gather information for plans with slug c3.medium
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
slug: c3.medium

```

```yaml
- name: Gather information for plans with a standard plan
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
type: standard

```










## Parameters

| Field | Type | Required | Description |
|-----------|------|----------|------------------------------------------------------------------------------|
| `categories` | <center>`list`</center> | <center>Optional</center> | Filter plans by its categories. |
| `type` | <center>`str`</center> | <center>Optional</center> | Filter plans by its plan type. |
| `slug` | <center>`str`</center> | <center>Optional</center> | Filter plans by slug. |






## Return Values

- `resources` - Found resources

- Sample Response:
```json

{
"available_in": [],
"available_in_metros": [],
"category": [
"compute",
"current_gen"
],
"class": "a3.large.opt-m3a2",
"deployment_types": [],
"description": "a3.large.opt-m3a2.x86",
"id": "8c04950a-87ab-5e52-a112-5a90bbca8868",
"legacy": false,
"line": "baremetal",
"name": "a3.large.opt-m3a2.x86",
"pricing_hour": 8.2,
"pricing_month": null,
"slug": "a3.large.opt-m3a2"
}
```


7 changes: 7 additions & 0 deletions plugins/module_utils/metal/api_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ def get_routes(mpc):
('metal_project_bgp_config', action.GET): spec_types.Specs(
equinix_metal.BGPApi(mpc).find_bgp_config_by_project,
),
("metal_plan", action.GET): spec_types.Specs(
equinix_metal.PlansApi(mpc).find_plans_by_project,
),

# LISTERS
('metal_project_device', action.LIST): spec_types.Specs(
Expand Down Expand Up @@ -154,6 +157,10 @@ def get_routes(mpc):
equinix_metal.BGPApi(mpc).find_bgp_config_by_project,
{'id': 'project_id'},
),
('metal_plan', action.LIST): spec_types.Specs(
equinix_metal.PlansApi(mpc).find_plans,
{'category': 'category', 'type': 'type', 'slug': 'slug', 'include': 'include', 'exclude': 'exclude'},
),

# DELETERS
('metal_device', action.DELETE): spec_types.Specs(
Expand Down
25 changes: 23 additions & 2 deletions plugins/module_utils/metal/metal_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ def optional_bool(key: str):
return lambda resource: resource.get(key, False)


def optional_float(key: str):
return lambda resource: resource.get(key, 0.0)
def optional_float(key: str, default=0.0):
return lambda resource: resource.get(key, default)

def cidr_to_quantity(key: str):
return lambda resource: ip_count_from_mask(resource.get(key))
Expand Down Expand Up @@ -151,6 +151,7 @@ def extract_ids_from_projects_hrefs(resource: dict):
'metal_gateways',
'bgp_sessions', # metal_bgp_session
'sessions', # metal_bgp_session_info
'plans',
]


Expand Down Expand Up @@ -272,6 +273,23 @@ def private_ipv4_subnet_size(resource: dict):

}

METAL_PLAN_RESPONSE_ATTRIBUTE_MAP = {
'id': 'id',
'categories': 'categories',
'name': 'name',
'slug': 'slug',
'description': 'description',
'line': 'line',
'legacy': 'legacy',
'class': 'class',
'pricing_hour': 'pricing.hour',
'pricing_month': optional_float('pricing.month', None),
'deployment_types': 'deployment_types',
'available_in': 'available_in',
'available_in_metros': 'available_in_metros',
}


def get_attribute_mapper(resource_type):
"""
Returns attribute mapper for the given resource type.
Expand All @@ -290,6 +308,7 @@ def get_attribute_mapper(resource_type):
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'}
plan_resources = set(["metal_plan"])
if resource_type in device_resources:
return METAL_DEVICE_RESPONSE_ATTRIBUTE_MAP
elif resource_type in project_resources:
Expand Down Expand Up @@ -320,6 +339,8 @@ def get_attribute_mapper(resource_type):
return METAL_BGP_SESSION_RESPONSE_ATTRIBUTE_MAP
elif resource_type in project_bgp_config_resources:
return METAL_PROJECT_BGP_CONFIG_RESPONSE_ATTRIBUTE_MAP
elif resource_type in plan_resources:
return METAL_PLAN_RESPONSE_ATTRIBUTE_MAP
else:
raise NotImplementedError("No mapper for resource type %s" % resource_type)

Expand Down
177 changes: 177 additions & 0 deletions plugins/modules/metal_plan_info.py
Original file line number Diff line number Diff line change
@@ -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) <[email protected]>
description: Gather information about Equinix Metal plans
module: metal_plan_info
notes: []
options:
categories:
description:
- Filter plans by its categories.
required: false
type: list
slug:
description:
- Filter plans by slug.
required: false
type: str
type:
description:
- Filter plans by its plan type.
required: false
type: str
requirements: null
short_description: Gather information about Equinix Metal plans
'''
EXAMPLES = '''
- name: Gather information about all plans
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info
- name: Gather information for plans with storage category
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
categories:
- storage
- name: Gather information for plans with slug c3.medium
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
slug: c3.medium
- name: Gather information for plans with a standard plan
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
type: standard
'''
RETURN = '''
resources:
description: Found resources
returned: always
sample:
- "\n{ \
\ \n \"available_in\": [], \
\ \
\ \n \"available_in_metros\": [],\n \"category\"\
: [\n \"compute\",\n \"current_gen\"\n ],\n \"class\": \"a3.large.opt-m3a2\"\
,\n \"deployment_types\": [],\n \"description\": \"a3.large.opt-m3a2.x86\",\n\
\ \"id\": \"8c04950a-87ab-5e52-a112-5a90bbca8868\",\n \"legacy\": false,\n \
\ \"line\": \"baremetal\",\n \"name\": \"a3.large.opt-m3a2.x86\",\n \"pricing_hour\"\
: 8.2,\n \"pricing_month\": null,\n \"slug\": \"a3.large.opt-m3a2\"\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(
categories=SpecField(
type=FieldType.list,
description=['Filter plans by categories.'],
),
type=SpecField(
type=FieldType.string,
description=['Filter plans by type.'],
),
slug=SpecField(
type=FieldType.string,
description=['Filter plans by slug.'],
),
)

specdoc_examples = ['''
- name: Gather information about all plans
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info
''', '''
- name: Gather information for plans with storage category
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
categories: ['storage']
''', '''
- name: Gather information for plans with slug c3.medium
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
slug: c3.medium
''', '''
- name: Gather information for plans with a standard plan
hosts: localhost
tasks:
- equinix.cloud.metal_plan_info:
type: standard
''',
]

result_sample = ['''
{
"available_in": [],
"available_in_metros": [],
"category": [
"compute",
"current_gen"
],
"class": "a3.large.opt-m3a2",
"deployment_types": [],
"description": "a3.large.opt-m3a2.x86",
"id": "8c04950a-87ab-5e52-a112-5a90bbca8868",
"legacy": false,
"line": "baremetal",
"name": "a3.large.opt-m3a2.x86",
"pricing_hour": 8.2,
"pricing_month": null,
"slug": "a3.large.opt-m3a2"
}''',
]

SPECDOC_META = getSpecDocMeta(
short_description="Gather information about Equinix Metal plans",
description=(
'Gather information about Equinix Metal plans'
),
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_plan")}

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()
Loading

0 comments on commit 7691455

Please sign in to comment.