diff --git a/README.md b/README.md index 1c04e31d..00392c9e 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Name | Description | [linode.cloud.object_cluster_info](./docs/modules/object_cluster_info.md)|**NOTE: This module has been deprecated because it relies on deprecated API endpoints. Going forward, `region` will be the preferred way to designate where Object Storage resources should be created.**| [linode.cloud.placement_group_info](./docs/modules/placement_group_info.md)|Get info about a Linode Placement Group.| [linode.cloud.profile_info](./docs/modules/profile_info.md)|Get info about a Linode Profile.| -[linode.cloud.ssh_key_info](./docs/modules/ssh_key_info.md)|Get info about the Linode SSH public key.| +[linode.cloud.ssh_key_info](./docs/modules/ssh_key_info.md)|Get info about a Linode SSH Key.| [linode.cloud.stackscript_info](./docs/modules/stackscript_info.md)|Get info about a Linode StackScript.| [linode.cloud.token_info](./docs/modules/token_info.md)|Get info about a Linode Personal Access Token.| [linode.cloud.type_info](./docs/modules/type_info.md)|Get info about a Linode Type.| @@ -105,12 +105,12 @@ Name | Description | [linode.cloud.object_cluster_list](./docs/modules/object_cluster_list.md)|**NOTE: This module has been deprecated because it relies on deprecated API endpoints. Going forward, `region` will be the preferred way to designate where Object Storage resources should be created.**| [linode.cloud.placement_group_list](./docs/modules/placement_group_list.md)|List and filter on Placement Groups.| [linode.cloud.region_list](./docs/modules/region_list.md)|List and filter on Regions.| -[linode.cloud.ssh_key_list](./docs/modules/ssh_key_list.md)|List and filter on SSH keys in the Linode profile.| -[linode.cloud.stackscript_list](./docs/modules/stackscript_list.md)|List and filter on Linode stackscripts.| -[linode.cloud.token_list](./docs/modules/token_list.md)|List and filter on Linode Account tokens.| +[linode.cloud.ssh_key_list](./docs/modules/ssh_key_list.md)|List and filter on SSH Keys.| +[linode.cloud.stackscript_list](./docs/modules/stackscript_list.md)|List and filter on StackScripts.| +[linode.cloud.token_list](./docs/modules/token_list.md)|List and filter on Tokens.| [linode.cloud.type_list](./docs/modules/type_list.md)|List and filter on Types.| -[linode.cloud.user_list](./docs/modules/user_list.md)|List Users.| -[linode.cloud.vlan_list](./docs/modules/vlan_list.md)|List and filter on Linode VLANs.| +[linode.cloud.user_list](./docs/modules/user_list.md)|List and filter on Users.| +[linode.cloud.vlan_list](./docs/modules/vlan_list.md)|List and filter on VLANs.| [linode.cloud.volume_list](./docs/modules/volume_list.md)|List and filter on Linode Volumes.| [linode.cloud.vpc_ip_list](./docs/modules/vpc_ip_list.md)|List and filter on VPC IP Addresses.| [linode.cloud.vpc_list](./docs/modules/vpc_list.md)|List and filter on VPCs.| @@ -178,6 +178,31 @@ For more information on Ansible collection usage, see [Ansible's official usage Use-case examples for this collection can be found [here](./examples/README.md). +## Development + +The following section outlines various information relating to the development of this collection. + +### Attaching a Debugger + +To quickly and easily attach a debugger to a running module in this collection, +you can use the [madbg](https://pypi.org/project/madbg/) package: + +1. Install `madbg` in your local Python environment: + +```shell +pip install madbg +``` + +2. Call `madbg.set_trace(...)` at the location you would like to create a breakpoint at: + +```shell +import madbg; madbg.set_trace() +``` + +3. Run the module in either a playbook or a test. +4. In a separate shell, run `madbg connect`. +5. You should now be able to remotely debug the module as soon as the breakpoint is triggered. + ## Licensing GNU General Public License v3.0. diff --git a/docs/inventory/instance.rst b/docs/inventory/instance.rst index 195d8afa..18445b50 100644 --- a/docs/inventory/instance.rst +++ b/docs/inventory/instance.rst @@ -58,7 +58,7 @@ Parameters **strict (type=bool):** - \• If \ :literal:`yes`\ make invalid entries a fatal error, otherwise skip and continue. + \• If :literal:`yes` make invalid entries a fatal error, otherwise skip and continue. \• Since it is possible to use facts in the expressions they might not always be available and we ignore those errors by default. @@ -94,13 +94,13 @@ Parameters **default_value (type=str):** \• The default value when the host variable's value is an empty string. - \• This option is mutually exclusive with \ :literal:`keyed\_groups[].trailing\_separator`\ . + \• This option is mutually exclusive with :literal:`keyed\_groups[].trailing\_separator`. **trailing_separator (type=bool, default=True):** - \• Set this option to \ :literal:`False`\ to omit the \ :literal:`keyed\_groups[].separator`\ after the host variable when the value is an empty string. + \• Set this option to :literal:`False` to omit the :literal:`keyed\_groups[].separator` after the host variable when the value is an empty string. - \• This option is mutually exclusive with \ :literal:`keyed\_groups[].default\_value`\ . + \• This option is mutually exclusive with :literal:`keyed\_groups[].default\_value`. diff --git a/docs/modules/firewall_info.md b/docs/modules/firewall_info.md index e3d440f4..162d3334 100644 --- a/docs/modules/firewall_info.md +++ b/docs/modules/firewall_info.md @@ -31,12 +31,12 @@ Get info about a Linode Firewall. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `id` |
`int`
|
Optional
| The unique id of the Firewall. Optional if `label` is defined. **(Conflicts With: `label`)** | -| `label` |
`str`
|
Optional
| The Firewall’s label. Optional if `id` is defined. **(Conflicts With: `id`)** | +| `label` |
`str`
|
Optional
| The label of the Firewall to resolve. **(Conflicts With: `id`)** | +| `id` |
`int`
|
Optional
| The ID of the Firewall to resolve. **(Conflicts With: `label`)** | ## Return Values -- `firewall` - The Firewall description in JSON serialized form. +- `firewall` - The returned Firewall. - Sample Response: ```json @@ -93,7 +93,7 @@ Get info about a Linode Firewall. - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-firewall) for a list of returned fields -- `devices` - A list of Firewall devices JSON serialized form. +- `devices` - The returned devices. - Sample Response: ```json @@ -111,6 +111,6 @@ Get info about a Linode Firewall. } ] ``` - - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-firewall-device) for a list of returned fields + - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-firewall-devices) for a list of returned fields diff --git a/docs/modules/firewall_list.md b/docs/modules/firewall_list.md index 72d26216..98116a32 100644 --- a/docs/modules/firewall_list.md +++ b/docs/modules/firewall_list.md @@ -32,21 +32,21 @@ List and filter on Firewalls. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `order` |
`str`
|
Optional
| The order to list firewalls in. **(Choices: `desc`, `asc`; Default: `asc`)** | -| `order_by` |
`str`
|
Optional
| The attribute to order firewalls by. | -| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting firewalls. | -| `count` |
`int`
|
Optional
| The number of results to return. If undefined, all results will be returned. | +| `order` |
`str`
|
Optional
| The order to list Firewalls in. **(Choices: `desc`, `asc`; Default: `asc`)** | +| `order_by` |
`str`
|
Optional
| The attribute to order Firewalls by. | +| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting Firewalls. | +| `count` |
`int`
|
Optional
| The number of Firewalls to return. If undefined, all results will be returned. | ### filters | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable attributes can be found here: https://techdocs.akamai.com/linode-api/reference/get-ips | +| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable fields can be found [here](https://techdocs.akamai.com/linode-api/reference/get-firewalls). | | `values` |
`list`
|
**Required**
| A list of values to allow for this field. Fields will pass this filter if at least one of these values matches. | ## Return Values -- `firewalls` - The returned firewalls. +- `firewalls` - The returned Firewalls. - Sample Response: ```json diff --git a/docs/modules/ssh_key_info.md b/docs/modules/ssh_key_info.md index cf643c30..6d193e78 100644 --- a/docs/modules/ssh_key_info.md +++ b/docs/modules/ssh_key_info.md @@ -1,6 +1,6 @@ # ssh_key_info -Get info about the Linode SSH public key. +Get info about a Linode SSH Key. - [Minimum Required Fields](#minimum-required-fields) - [Examples](#examples) @@ -31,12 +31,12 @@ Get info about the Linode SSH public key. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `id` |
`int`
|
Optional
| The ID of the SSH key. **(Conflicts With: `label`)** | -| `label` |
`str`
|
Optional
| The label of the SSH key. **(Conflicts With: `id`)** | +| `label` |
`str`
|
Optional
| The label of the SSH Key to resolve. **(Conflicts With: `id`)** | +| `id` |
`int`
|
Optional
| The ID of the SSH Key to resolve. **(Conflicts With: `label`)** | ## Return Values -- `ssh_key` - The SSH key in JSON serialized form. +- `ssh_key` - The returned SSH Key. - Sample Response: ```json diff --git a/docs/modules/ssh_key_list.md b/docs/modules/ssh_key_list.md index 479ac4ef..2ca2b0fc 100644 --- a/docs/modules/ssh_key_list.md +++ b/docs/modules/ssh_key_list.md @@ -1,6 +1,6 @@ # ssh_key_list -List and filter on SSH keys in the Linode profile. +List and filter on SSH Keys. - [Minimum Required Fields](#minimum-required-fields) - [Examples](#examples) @@ -52,21 +52,21 @@ List and filter on SSH keys in the Linode profile. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `order` |
`str`
|
Optional
| The order to list ssh keys in. **(Choices: `desc`, `asc`; Default: `asc`)** | -| `order_by` |
`str`
|
Optional
| The attribute to order ssh keys by. | -| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting ssh keys. | -| `count` |
`int`
|
Optional
| The number of results to return. If undefined, all results will be returned. | +| `order` |
`str`
|
Optional
| The order to list SSH Keys in. **(Choices: `desc`, `asc`; Default: `asc`)** | +| `order_by` |
`str`
|
Optional
| The attribute to order SSH Keys by. | +| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting SSH Keys. | +| `count` |
`int`
|
Optional
| The number of SSH Keys to return. If undefined, all results will be returned. | ### filters | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable attributes can be found here: https://techdocs.akamai.com/linode-api/reference/get-profile | +| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable fields can be found [here](https://techdocs.akamai.com/linode-api/reference/get-ssh-keys). | | `values` |
`list`
|
**Required**
| A list of values to allow for this field. Fields will pass this filter if at least one of these values matches. | ## Return Values -- `ssh_keys` - The returned SSH keys. +- `ssh_keys` - The returned SSH Keys. - Sample Response: ```json diff --git a/docs/modules/stackscript_list.md b/docs/modules/stackscript_list.md index 00300355..ef0aa242 100644 --- a/docs/modules/stackscript_list.md +++ b/docs/modules/stackscript_list.md @@ -1,6 +1,6 @@ # stackscript_list -List and filter on Linode stackscripts. +List and filter on StackScripts. - [Minimum Required Fields](#minimum-required-fields) - [Examples](#examples) @@ -40,21 +40,21 @@ List and filter on Linode stackscripts. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `order` |
`str`
|
Optional
| The order to list events in. **(Choices: `desc`, `asc`; Default: `asc`)** | -| `order_by` |
`str`
|
Optional
| The attribute to order events by. | -| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting events. | -| `count` |
`int`
|
Optional
| The number of results to return. If undefined, all results will be returned. | +| `order` |
`str`
|
Optional
| The order to list StackScripts in. **(Choices: `desc`, `asc`; Default: `asc`)** | +| `order_by` |
`str`
|
Optional
| The attribute to order StackScripts by. | +| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting StackScripts. | +| `count` |
`int`
|
Optional
| The number of StackScripts to return. If undefined, all results will be returned. | ### filters | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable attributes can be found here: https://techdocs.akamai.com/linode-api/reference/get-stack-scripts | +| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable fields can be found [here](https://techdocs.akamai.com/linode-api/reference/get-stack-scripts). | | `values` |
`list`
|
**Required**
| A list of values to allow for this field. Fields will pass this filter if at least one of these values matches. | ## Return Values -- `stackscripts` - The returned stackscripts. +- `stackscripts` - The returned StackScripts. - Sample Response: ```json diff --git a/docs/modules/token_info.md b/docs/modules/token_info.md index 88875541..ede98195 100644 --- a/docs/modules/token_info.md +++ b/docs/modules/token_info.md @@ -31,12 +31,12 @@ Get info about a Linode Personal Access Token. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `id` |
`int`
|
Optional
| The ID of the token. **(Conflicts With: `label`)** | -| `label` |
`str`
|
Optional
| The label of the token. **(Conflicts With: `id`)** | +| `label` |
`str`
|
Optional
| The label of the Personal Access Token to resolve. **(Conflicts With: `id`)** | +| `id` |
`int`
|
Optional
| The ID of the Personal Access Token to resolve. **(Conflicts With: `label`)** | ## Return Values -- `token` - The token in JSON serialized form. +- `token` - The returned Personal Access Token. - Sample Response: ```json @@ -49,6 +49,6 @@ Get info about a Linode Personal Access Token. "token": "abcdefghijklmnop" } ``` - - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/post-personal-access-token) for a list of returned fields + - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-personal-access-tokens) for a list of returned fields diff --git a/docs/modules/token_list.md b/docs/modules/token_list.md index aacc77af..2e910b1d 100644 --- a/docs/modules/token_list.md +++ b/docs/modules/token_list.md @@ -1,6 +1,6 @@ # token_list -List and filter on Linode Account tokens. +List and filter on Tokens. - [Minimum Required Fields](#minimum-required-fields) - [Examples](#examples) @@ -32,21 +32,21 @@ List and filter on Linode Account tokens. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `order` |
`str`
|
Optional
| The order to list tokens in. **(Choices: `desc`, `asc`; Default: `asc`)** | -| `order_by` |
`str`
|
Optional
| The attribute to order tokens by. | -| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting tokens. | -| `count` |
`int`
|
Optional
| The number of results to return. If undefined, all results will be returned. | +| `order` |
`str`
|
Optional
| The order to list Tokens in. **(Choices: `desc`, `asc`; Default: `asc`)** | +| `order_by` |
`str`
|
Optional
| The attribute to order Tokens by. | +| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting Tokens. | +| `count` |
`int`
|
Optional
| The number of Tokens to return. If undefined, all results will be returned. | ### filters | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable attributes can be found here: https://techdocs.akamai.com/linode-api/reference/get-profile | +| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable fields can be found [here](https://techdocs.akamai.com/linode-api/reference/get-personal-access-tokens). | | `values` |
`list`
|
**Required**
| A list of values to allow for this field. Fields will pass this filter if at least one of these values matches. | ## Return Values -- `tokens` - The returned tokens. +- `tokens` - The returned Tokens. - Sample Response: ```json diff --git a/docs/modules/user_list.md b/docs/modules/user_list.md index e770f0d9..81bc1b6d 100644 --- a/docs/modules/user_list.md +++ b/docs/modules/user_list.md @@ -1,6 +1,6 @@ # user_list -List Users. +List and filter on Users. - [Minimum Required Fields](#minimum-required-fields) - [Examples](#examples) @@ -24,12 +24,21 @@ List Users. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `order` |
`str`
|
Optional
| The order to list users in. **(Choices: `desc`, `asc`; Default: `asc`)** | -| `count` |
`int`
|
Optional
| The number of results to return. If undefined, all results will be returned. | +| `order` |
`str`
|
Optional
| The order to list Users in. **(Choices: `desc`, `asc`; Default: `asc`)** | +| `order_by` |
`str`
|
Optional
| The attribute to order Users by. | +| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting Users. | +| `count` |
`int`
|
Optional
| The number of Users to return. If undefined, all results will be returned. | + +### filters + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable fields can be found [here](https://techdocs.akamai.com/linode-api/reference/get-users). | +| `values` |
`list`
|
**Required**
| A list of values to allow for this field. Fields will pass this filter if at least one of these values matches. | ## Return Values -- `users` - The returned users. +- `users` - The returned Users. - Sample Response: ```json @@ -47,6 +56,6 @@ List Users. } ] ``` - - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-account) for a list of returned fields + - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-users) for a list of returned fields diff --git a/docs/modules/vlan_info.md b/docs/modules/vlan_info.md index 3d31800e..c5ef1d98 100644 --- a/docs/modules/vlan_info.md +++ b/docs/modules/vlan_info.md @@ -2,8 +2,6 @@ Get info about a Linode VLAN. -WARNING! This module makes use of beta endpoints and requires the C(api_version) field be explicitly set to C(v4beta). - - [Minimum Required Fields](#minimum-required-fields) - [Examples](#examples) - [Parameters](#parameters) @@ -28,11 +26,12 @@ WARNING! This module makes use of beta endpoints and requires the C(api_version) | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `label` |
`str`
|
**Required**
| The VLAN’s label. | +| `label` |
`str`
|
Optional
| The label of the VLAN to resolve. **(Conflicts With: `id`)** | +| `id` |
`int`
|
Optional
| The ID of the VLAN to resolve. **(Conflicts With: `label`)** | ## Return Values -- `vlan` - The VLAN in JSON serialized form. +- `vlan` - The returned VLAN. - Sample Response: ```json diff --git a/docs/modules/vlan_list.md b/docs/modules/vlan_list.md index 893df5a1..38d7579a 100644 --- a/docs/modules/vlan_list.md +++ b/docs/modules/vlan_list.md @@ -1,8 +1,6 @@ # vlan_list -List and filter on Linode VLANs. - -WARNING! This module makes use of beta endpoints and requires the C(api_version) field be explicitly set to C(v4beta). +List and filter on VLANs. - [Minimum Required Fields](#minimum-required-fields) - [Examples](#examples) @@ -40,13 +38,13 @@ WARNING! This module makes use of beta endpoints and requires the C(api_version) | `order` |
`str`
|
Optional
| The order to list VLANs in. **(Choices: `desc`, `asc`; Default: `asc`)** | | `order_by` |
`str`
|
Optional
| The attribute to order VLANs by. | | [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting VLANs. | -| `count` |
`int`
|
Optional
| The number of results to return. If undefined, all results will be returned. | +| `count` |
`int`
|
Optional
| The number of VLANs to return. If undefined, all results will be returned. | ### filters | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable attributes can be found here: https://techdocs.akamai.com/linode-api/reference/get-vlans | +| `name` |
`str`
|
**Required**
| The name of the field to filter on. Valid filterable fields can be found [here](https://techdocs.akamai.com/linode-api/reference/get-vlans). | | `values` |
`list`
|
**Required**
| A list of values to allow for this field. Fields will pass this filter if at least one of these values matches. | ## Return Values diff --git a/plugins/modules/firewall_info.py b/plugins/modules/firewall_info.py index efdf5bc6..ec7b3d01 100644 --- a/plugins/modules/firewall_info.py +++ b/plugins/modules/firewall_info.py @@ -1,76 +1,69 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -"""This module contains all of the functionality for Linode Firewall info.""" +"""This module allows users to retrieve information about a Linode Firewall.""" from __future__ import absolute_import, division, print_function -from typing import Any, Dict, List, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.firewall as docs_parent import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.firewall_info as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - global_authors, - global_requirements, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_info import ( + InfoModule, + InfoModuleAttr, + InfoModuleResult, ) from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - create_filter_and, paginated_list_to_json, + safe_find, ) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, -) +from ansible_specdoc.objects import FieldType from linode_api4 import Firewall -linode_firewall_info_spec = { - # We need to overwrite attributes to exclude them as requirements - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "id": SpecField( - type=FieldType.integer, - required=False, - conflicts_with=["label"], - description=[ - "The unique id of the Firewall.", - "Optional if `label` is defined.", - ], - ), - "label": SpecField( - type=FieldType.string, - required=False, - conflicts_with=["id"], - description=["The Firewall’s label.", "Optional if `id` is defined."], +module = InfoModule( + primary_result=InfoModuleResult( + field_name="firewall", + field_type=FieldType.dict, + display_name="Firewall", + docs_url="https://techdocs.akamai.com/linode-api/reference/get-firewall", + samples=docs_parent.result_firewall_samples, ), -} - -SPECDOC_META = SpecDocMeta( - description=["Get info about a Linode Firewall."], - requirements=global_requirements, - author=global_authors, - options=linode_firewall_info_spec, - examples=docs.specdoc_examples, - return_values={ - "firewall": SpecReturnValue( - description="The Firewall description in JSON serialized form.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-firewall", - type=FieldType.dict, - sample=docs_parent.result_firewall_samples, + secondary_results=[ + InfoModuleResult( + field_name="devices", + field_type=FieldType.list, + display_name="devices", + docs_url="https://techdocs.akamai.com/linode-api/reference/get-firewall-devices", + samples=docs_parent.result_devices_samples, + get=lambda client, firewall, params: paginated_list_to_json( + Firewall(client, firewall["id"]).devices + ), + ), + ], + attributes=[ + InfoModuleAttr( + display_name="ID", + name="id", + type=FieldType.integer, + get=lambda client, params: client.load( + Firewall, + params.get("id"), + )._raw_json, ), - "devices": SpecReturnValue( - description="A list of Firewall devices JSON serialized form.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-firewall-device", - type=FieldType.list, - sample=docs_parent.result_devices_samples, + InfoModuleAttr( + display_name="label", + name="label", + type=FieldType.string, + get=lambda client, params: safe_find( + client.networking.firewalls, + Firewall.label == params.get("label"), + raise_not_found=True, + )._raw_json, ), - }, + ], + examples=docs.specdoc_examples, ) -linode_firewall_valid_filters = ["id", "label"] +SPECDOC_META = module.spec DOCUMENTATION = r""" """ @@ -79,63 +72,5 @@ RETURN = r""" """ - -class LinodeFirewallInfo(LinodeModuleBase): - """Module for viewing info about a Linode Firewall""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.required_one_of: List[str] = [] - self.results: Dict[str, Any] = {"firewall": None} - - super().__init__( - module_arg_spec=self.module_arg_spec, - required_one_of=self.required_one_of, - ) - - def _get_matching_firewall(self) -> Optional[Firewall]: - """Gets the Firewall with the param properties""" - - filter_items = { - k: v - for k, v in self.module.params.items() - if k in linode_firewall_valid_filters and v is not None - } - - filter_statement = create_filter_and(Firewall, filter_items) - - try: - # Special case because ID is not filterable - if "id" in filter_items.keys(): - result = Firewall(self.client, self.module.params.get("id")) - result._api_get() # Force lazy-loading - - return result - - return self.client.networking.firewalls(filter_statement)[0] - except IndexError: - return None - except Exception as exception: - return self.fail(msg="failed to get firewall {0}".format(exception)) - - def exec_module(self, **kwargs: dict) -> Optional[dict]: - """Entrypoint for Firewall info module""" - - firewall = self._get_matching_firewall() - - if firewall is None: - self.fail("failed to get firewall") - - self.results["firewall"] = firewall._raw_json - self.results["devices"] = paginated_list_to_json(firewall.devices) - - return self.results - - -def main() -> None: - """Constructs and calls the Linode Firewall info module""" - LinodeFirewallInfo() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/firewall_list.py b/plugins/modules/firewall_list.py index 70a1a11b..9548bdd1 100644 --- a/plugins/modules/firewall_list.py +++ b/plugins/modules/firewall_list.py @@ -1,97 +1,26 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -"""This module allows users to list Linode tokens.""" -from __future__ import absolute_import, division, print_function +"""This module contains all of the functionality for listing Linode Firewalls.""" -from typing import Any, Dict, Optional +from __future__ import absolute_import, division, print_function import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.firewall_list as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - global_authors, - global_requirements, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - construct_api_filter, - get_all_paginated, -) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import ( + ListModule, ) -spec_filter = { - "name": SpecField( - type=FieldType.string, - required=True, - description=[ - "The name of the field to filter on.", - "Valid filterable attributes can be found here: " - "https://techdocs.akamai.com/linode-api/reference/get-ips", - ], - ), - "values": SpecField( - type=FieldType.list, - element_type=FieldType.string, - required=True, - description=[ - "A list of values to allow for this field.", - "Fields will pass this filter if at least one of these values matches.", - ], - ), -} - -spec = { - # Disable the default values - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "label": SpecField(type=FieldType.string, required=False, doc_hide=True), - "order": SpecField( - type=FieldType.string, - description=["The order to list firewalls in."], - default="asc", - choices=["desc", "asc"], - ), - "order_by": SpecField( - type=FieldType.string, - description=["The attribute to order firewalls by."], - ), - "filters": SpecField( - type=FieldType.list, - element_type=FieldType.dict, - suboptions=spec_filter, - description=["A list of filters to apply to the resulting firewalls."], - ), - "count": SpecField( - type=FieldType.integer, - description=[ - "The number of results to return.", - "If undefined, all results will be returned.", - ], - ), -} - -SPECDOC_META = SpecDocMeta( - description=["List and filter on Firewalls."], - requirements=global_requirements, - author=global_authors, - options=spec, +module = ListModule( + result_display_name="Firewalls", + result_field_name="firewalls", + endpoint_template="/networking/firewalls", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-firewalls", examples=docs.specdoc_examples, - return_values={ - "firewalls": SpecReturnValue( - description="The returned firewalls.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-firewalls", - type=FieldType.list, - elements=FieldType.dict, - sample=docs.result_firewalls_samples, - ) - }, + result_samples=docs.result_firewalls_samples, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -99,34 +28,5 @@ RETURN = r""" """ - -class Module(LinodeModuleBase): - """Module for getting a list of Firewalls""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results: Dict[str, Any] = {"firewalls": []} - - super().__init__(module_arg_spec=self.module_arg_spec) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for firewall list module""" - - filter_dict = construct_api_filter(self.module.params) - - self.results["firewalls"] = get_all_paginated( - self.client, - "/networking/firewalls", - filter_dict, - num_results=self.module.params["count"], - ) - return self.results - - -def main() -> None: - """Constructs and calls the module""" - Module() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/ssh_key_info.py b/plugins/modules/ssh_key_info.py index 7842e484..6cb4e636 100644 --- a/plugins/modules/ssh_key_info.py +++ b/plugins/modules/ssh_key_info.py @@ -5,58 +5,52 @@ from __future__ import absolute_import, division, print_function -from typing import Any, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.ssh_key_info as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - global_authors, - global_requirements, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_info import ( + InfoModule, + InfoModuleAttr, + InfoModuleResult, ) from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - filter_null_values, -) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, + safe_find, ) +from ansible_specdoc.objects import FieldType from linode_api4 import SSHKey -linode_ssh_key_info_spec = { - # Disable the default values - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "id": SpecField( - type=FieldType.integer, - conflicts_with=["label"], - description=["The ID of the SSH key."], +module = InfoModule( + primary_result=InfoModuleResult( + field_name="ssh_key", + field_type=FieldType.dict, + display_name="SSH Key", + docs_url="https://techdocs.akamai.com/linode-api/reference/get-ssh-key", + samples=docs.ssh_key_info_response_sample, ), - "label": SpecField( - type=FieldType.string, - conflicts_with=["id"], - description=["The label of the SSH key."], - ), -} - -SPECDOC_META = SpecDocMeta( - description=["Get info about the Linode SSH public key."], - requirements=global_requirements, - author=global_authors, - options=linode_ssh_key_info_spec, + attributes=[ + InfoModuleAttr( + display_name="ID", + name="id", + type=FieldType.integer, + get=lambda client, params: client.load( + SSHKey, + params.get("id"), + )._raw_json, + ), + InfoModuleAttr( + display_name="label", + name="label", + type=FieldType.string, + get=lambda client, params: safe_find( + client.profile.ssh_keys, + SSHKey.label == params.get("label"), + raise_not_found=True, + )._raw_json, + ), + ], examples=docs.specdoc_examples, - return_values={ - "ssh_key": SpecReturnValue( - description="The SSH key in JSON serialized form.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-ssh-key", - type=FieldType.dict, - sample=docs.ssh_key_info_response_sample, - ) - }, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -64,56 +58,5 @@ RETURN = r""" """ - -class LinodeSSHKeyInfo(LinodeModuleBase): - """Module for getting Linode SSH public key""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results = {"ssh_key": None} - - super().__init__( - module_arg_spec=self.module_arg_spec, - required_one_of=[("id", "label")], - mutually_exclusive=[("id", "label")], - ) - - def _get_ssh_key_by_label(self, label: str) -> Optional[SSHKey]: - try: - ssh_keys = self.client.profile.ssh_keys(SSHKey.label == label) - if not ssh_keys: - return self.fail( - msg=f"failed to get ssh key with label {label}: " - "ssh key does not exist" - ) - return ssh_keys[0] # maybe return whole list? - except Exception as exception: - return self.fail(msg=f"failed to get ssh key {label}: {exception}") - - def _get_ssh_key_by_id(self, ssh_key_id: int) -> Optional[SSHKey]: - return self._get_resource_by_id(SSHKey, ssh_key_id) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for ssh_key_info module""" - - params = filter_null_values(self.module.params) - - ssh_key = None - - if "id" in params: - ssh_key = self._get_ssh_key_by_id(params.get("id")) - elif "label" in params: - ssh_key = self._get_ssh_key_by_label(params.get("label")) - - self.results["ssh_key"] = ssh_key._raw_json - - return self.results - - -def main() -> None: - """Constructs and calls the module""" - LinodeSSHKeyInfo() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/ssh_key_list.py b/plugins/modules/ssh_key_list.py index 92a99991..45df7be6 100644 --- a/plugins/modules/ssh_key_list.py +++ b/plugins/modules/ssh_key_list.py @@ -5,96 +5,22 @@ from __future__ import absolute_import, division, print_function -from typing import Any, Dict, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.ssh_key_list as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - global_authors, - global_requirements, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - construct_api_filter, - get_all_paginated, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import ( + ListModule, ) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, -) - -spec_filter = { - "name": SpecField( - type=FieldType.string, - required=True, - description=[ - "The name of the field to filter on.", - ( - "Valid filterable attributes can be found here: " - "https://techdocs.akamai.com/linode-api/reference/get-profile" - ), - ], - ), - "values": SpecField( - type=FieldType.list, - element_type=FieldType.string, - required=True, - description=[ - "A list of values to allow for this field.", - "Fields will pass this filter if at least one of these values matches.", - ], - ), -} -spec = { - # Disable the default values - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "label": SpecField(type=FieldType.string, required=False, doc_hide=True), - "order": SpecField( - type=FieldType.string, - description=["The order to list ssh keys in."], - default="asc", - choices=["desc", "asc"], - ), - "order_by": SpecField( - type=FieldType.string, - description=["The attribute to order ssh keys by."], - ), - "filters": SpecField( - type=FieldType.list, - element_type=FieldType.dict, - suboptions=spec_filter, - description=["A list of filters to apply to the resulting ssh keys."], - ), - "count": SpecField( - type=FieldType.integer, - description=[ - "The number of results to return.", - "If undefined, all results will be returned.", - ], - ), -} - -SPECDOC_META = SpecDocMeta( - description=["List and filter on SSH keys in the Linode profile."], - requirements=global_requirements, - author=global_authors, - options=spec, +module = ListModule( + result_display_name="SSH Keys", + result_field_name="ssh_keys", + endpoint_template="/profile/sshkeys", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-ssh-keys", examples=docs.ssh_key_list_specdoc_examples, - return_values={ - "ssh_keys": SpecReturnValue( - description="The returned SSH keys.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-ssh-keys", - type=FieldType.list, - elements=FieldType.dict, - sample=docs.result_ssh_key_list_samples, - ) - }, + result_samples=docs.result_ssh_key_list_samples, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -102,34 +28,5 @@ RETURN = r""" """ - -class SSHKeyListModule(LinodeModuleBase): - """Module for getting a list of SSH keys in the Linode profile""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results: Dict[str, Any] = {"ssh_keys": []} - - super().__init__(module_arg_spec=self.module_arg_spec) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for SSH key list module""" - - filter_dict = construct_api_filter(self.module.params) - - self.results["ssh_keys"] = get_all_paginated( - self.client, - "/profile/sshkeys", - filter_dict, - num_results=self.module.params["count"], - ) - return self.results - - -def main() -> None: - """Constructs and calls the module""" - SSHKeyListModule() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/stackscript_list.py b/plugins/modules/stackscript_list.py index ed5e9bd9..42865e10 100644 --- a/plugins/modules/stackscript_list.py +++ b/plugins/modules/stackscript_list.py @@ -1,99 +1,26 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -"""This module allows users to list Linode stackscripts.""" +"""This module contains all of the functionality for listing Linode StackScripts.""" from __future__ import absolute_import, division, print_function -from typing import Any, Dict, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.stackscript_list as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - global_authors, - global_requirements, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - construct_api_filter, - get_all_paginated, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import ( + ListModule, ) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, -) - -spec_filter = { - "name": SpecField( - type=FieldType.string, - required=True, - description=[ - "The name of the field to filter on.", - "Valid filterable attributes can be found here: " - # pylint: disable-next=line-too-long - "https://techdocs.akamai.com/linode-api/reference/get-stack-scripts", - ], - ), - "values": SpecField( - type=FieldType.list, - element_type=FieldType.string, - required=True, - description=[ - "A list of values to allow for this field.", - "Fields will pass this filter if at least one of these values matches.", - ], - ), -} -spec = { - # Disable the default values - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "label": SpecField(type=FieldType.string, required=False, doc_hide=True), - "order": SpecField( - type=FieldType.string, - description=["The order to list events in."], - default="asc", - choices=["desc", "asc"], - ), - "order_by": SpecField( - type=FieldType.string, description=["The attribute to order events by."] - ), - "filters": SpecField( - type=FieldType.list, - element_type=FieldType.dict, - suboptions=spec_filter, - description=["A list of filters to apply to the resulting events."], - ), - "count": SpecField( - type=FieldType.integer, - description=[ - "The number of results to return.", - "If undefined, all results will be returned.", - ], - ), -} - -SPECDOC_META = SpecDocMeta( - description=["List and filter on Linode stackscripts."], - requirements=global_requirements, - author=global_authors, - options=spec, +module = ListModule( + result_display_name="StackScripts", + result_field_name="stackscripts", + endpoint_template="/linode/stackscripts", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-stack-scripts", examples=docs.specdoc_examples, - return_values={ - "stackscripts": SpecReturnValue( - description="The returned stackscripts.", - # pylint: disable-next=line-too-long - docs_url="https://techdocs.akamai.com/linode-api/reference/get-stack-scripts", - type=FieldType.list, - elements=FieldType.dict, - sample=docs.result_stackscripts_samples, - ) - }, + result_samples=docs.result_stackscripts_samples, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -101,34 +28,5 @@ RETURN = r""" """ - -class Module(LinodeModuleBase): - """Module for getting a list of Linode stackscripts""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results: Dict[str, Any] = {"stackscripts": []} - - super().__init__(module_arg_spec=self.module_arg_spec) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for stackscript list module""" - - filter_dict = construct_api_filter(self.module.params) - - self.results["stackscripts"] = get_all_paginated( - self.client, - "/linode/stackscripts", - filter_dict, - num_results=self.module.params["count"], - ) - return self.results - - -def main() -> None: - """Constructs and calls the module""" - Module() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/token_info.py b/plugins/modules/token_info.py index bf132d25..6d89df9d 100644 --- a/plugins/modules/token_info.py +++ b/plugins/modules/token_info.py @@ -5,59 +5,53 @@ from __future__ import absolute_import, division, print_function -from typing import Any, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.token as docs_parent import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.token_info as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - global_authors, - global_requirements, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_info import ( + InfoModule, + InfoModuleAttr, + InfoModuleResult, ) from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - filter_null_values, -) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, + safe_find, ) +from ansible_specdoc.objects import FieldType from linode_api4 import PersonalAccessToken -spec = { - # Disable the default values - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "id": SpecField( - type=FieldType.integer, - description=["The ID of the token."], - conflicts_with=["label"], +module = InfoModule( + primary_result=InfoModuleResult( + field_name="token", + field_type=FieldType.dict, + display_name="Personal Access Token", + docs_url="https://techdocs.akamai.com/linode-api/reference/get-personal-access-tokens", + samples=docs_parent.result_token_samples, ), - "label": SpecField( - type=FieldType.string, - description=["The label of the token."], - conflicts_with=["id"], - ), -} - -SPECDOC_META = SpecDocMeta( - description=["Get info about a Linode Personal Access Token."], - requirements=global_requirements, - author=global_authors, - options=spec, + attributes=[ + InfoModuleAttr( + display_name="ID", + name="id", + type=FieldType.integer, + get=lambda client, params: client.load( + PersonalAccessToken, + params.get("id"), + )._raw_json, + ), + InfoModuleAttr( + display_name="label", + name="label", + type=FieldType.string, + get=lambda client, params: safe_find( + client.profile.tokens, + PersonalAccessToken.label == params.get("label"), + raise_not_found=True, + )._raw_json, + ), + ], examples=docs.specdoc_examples, - return_values={ - "token": SpecReturnValue( - description="The token in JSON serialized form.", - docs_url="https://techdocs.akamai.com/linode-api/reference/post-personal-access-token", - type=FieldType.dict, - sample=docs_parent.result_token_samples, - ) - }, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -65,60 +59,5 @@ RETURN = r""" """ - -class Module(LinodeModuleBase): - """Module for getting info about a Linode token""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results = {"token": None} - - super().__init__( - module_arg_spec=self.module_arg_spec, - required_one_of=[("id", "label")], - mutually_exclusive=[("id", "label")], - ) - - def _get_token_by_label(self, label: str) -> Optional[PersonalAccessToken]: - try: - return self.client.profile.tokens( - PersonalAccessToken.label == label - )[0] - except IndexError: - return self.fail( - msg="failed to get token with label {0}: " - "token does not exist".format(label) - ) - except Exception as exception: - return self.fail( - msg="failed to get token {0}: {1}".format(label, exception) - ) - - def _get_token_by_id(self, token_id: int) -> PersonalAccessToken: - return self._get_resource_by_id(PersonalAccessToken, token_id) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for token info module""" - - params = filter_null_values(self.module.params) - - if "id" in params: - self.results["token"] = self._get_token_by_id( - params.get("id") - )._raw_json - - if "label" in params: - self.results["token"] = self._get_token_by_label( - params.get("label") - )._raw_json - - return self.results - - -def main() -> None: - """Constructs and calls the module""" - Module() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/token_list.py b/plugins/modules/token_list.py index 92ce5094..4d4d0068 100644 --- a/plugins/modules/token_list.py +++ b/plugins/modules/token_list.py @@ -4,94 +4,22 @@ """This module allows users to list Linode tokens.""" from __future__ import absolute_import, division, print_function -from typing import Any, Dict, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.token_list as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - global_authors, - global_requirements, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - construct_api_filter, - get_all_paginated, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import ( + ListModule, ) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, -) - -spec_filter = { - "name": SpecField( - type=FieldType.string, - required=True, - description=[ - "The name of the field to filter on.", - "Valid filterable attributes can be found here: " - "https://techdocs.akamai.com/linode-api/reference/get-profile", - ], - ), - "values": SpecField( - type=FieldType.list, - element_type=FieldType.string, - required=True, - description=[ - "A list of values to allow for this field.", - "Fields will pass this filter if at least one of these values matches.", - ], - ), -} -spec = { - # Disable the default values - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "label": SpecField(type=FieldType.string, required=False, doc_hide=True), - "order": SpecField( - type=FieldType.string, - description=["The order to list tokens in."], - default="asc", - choices=["desc", "asc"], - ), - "order_by": SpecField( - type=FieldType.string, - description=["The attribute to order tokens by."], - ), - "filters": SpecField( - type=FieldType.list, - element_type=FieldType.dict, - suboptions=spec_filter, - description=["A list of filters to apply to the resulting tokens."], - ), - "count": SpecField( - type=FieldType.integer, - description=[ - "The number of results to return.", - "If undefined, all results will be returned.", - ], - ), -} - -SPECDOC_META = SpecDocMeta( - description=["List and filter on Linode Account tokens."], - requirements=global_requirements, - author=global_authors, - options=spec, +module = ListModule( + result_display_name="Tokens", + result_field_name="tokens", + endpoint_template="/profile/tokens", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-personal-access-tokens", examples=docs.specdoc_examples, - return_values={ - "tokens": SpecReturnValue( - description="The returned tokens.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-personal-access-tokens", - type=FieldType.list, - elements=FieldType.dict, - sample=docs.result_tokens_samples, - ), - }, + result_samples=docs.result_tokens_samples, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -99,34 +27,5 @@ RETURN = r""" """ - -class Module(LinodeModuleBase): - """Module for getting a list of Linode Account tokens""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results: Dict[str, Any] = {"tokens": []} - - super().__init__(module_arg_spec=self.module_arg_spec) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for token list module""" - - filter_dict = construct_api_filter(self.module.params) - - self.results["tokens"] = get_all_paginated( - self.client, - "/profile/tokens", - filter_dict, - num_results=self.module.params["count"], - ) - return self.results - - -def main() -> None: - """Constructs and calls the module""" - Module() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/user_list.py b/plugins/modules/user_list.py index b976d5e9..d34964ce 100644 --- a/plugins/modules/user_list.py +++ b/plugins/modules/user_list.py @@ -4,64 +4,22 @@ """This module allows users to list Users.""" from __future__ import absolute_import, division, print_function -from typing import Any, Dict, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.user_list as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - global_authors, - global_requirements, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - get_all_paginated, -) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import ( + ListModule, ) -spec = { - # Disable the default values - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "label": SpecField(type=FieldType.string, required=False, doc_hide=True), - "order": SpecField( - type=FieldType.string, - description=["The order to list users in."], - default="asc", - choices=["desc", "asc"], - ), - "count": SpecField( - type=FieldType.integer, - description=[ - "The number of results to return.", - "If undefined, all results will be returned.", - ], - ), -} - -SPECDOC_META = SpecDocMeta( - description=["List Users."], - requirements=global_requirements, - author=global_authors, - options=spec, +module = ListModule( + result_display_name="Users", + result_field_name="users", + endpoint_template="/account/users", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-users", examples=docs.specdoc_examples, - return_values={ - "users": SpecReturnValue( - description="The returned users.", - docs_url=( - "https://techdocs.akamai.com/linode-api/reference/get-account" - ), - type=FieldType.list, - elements=FieldType.dict, - sample=docs.result_users_samples, - ) - }, + result_samples=docs.result_users_samples, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -69,32 +27,5 @@ RETURN = r""" """ - -class Module(LinodeModuleBase): - """Module for getting a list of Users""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results: Dict[str, Any] = {"users": []} - - super().__init__(module_arg_spec=self.module_arg_spec) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for user module""" - - self.results["users"] = get_all_paginated( - self.client, - "/account/users", - None, - num_results=self.module.params["count"], - ) - return self.results - - -def main() -> None: - """Constructs and calls the module""" - Module() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/vlan_info.py b/plugins/modules/vlan_info.py index 9f404860..f8274ea7 100644 --- a/plugins/modules/vlan_info.py +++ b/plugins/modules/vlan_info.py @@ -5,52 +5,52 @@ from __future__ import absolute_import, division, print_function -from typing import Any, List, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.vlan_info as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - BETA_DISCLAIMER, - global_authors, - global_requirements, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_info import ( + InfoModule, + InfoModuleAttr, + InfoModuleResult, ) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, +from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( + safe_find, ) +from ansible_specdoc.objects import FieldType from linode_api4 import VLAN -linode_vlan_info_spec = { - # We need to overwrite attributes to exclude them as requirements - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "label": SpecField( - type=FieldType.string, required=True, description=["The VLAN’s label."] +module = InfoModule( + primary_result=InfoModuleResult( + field_name="vlan", + field_type=FieldType.dict, + display_name="VLAN", + docs_url="https://techdocs.akamai.com/linode-api/reference/get-vlans", + samples=docs.result_vlan_samples, ), -} - -SPECDOC_META = SpecDocMeta( - description=[ - "Get info about a Linode VLAN.", - BETA_DISCLAIMER, + attributes=[ + InfoModuleAttr( + display_name="ID", + name="id", + type=FieldType.integer, + get=lambda client, params: client.load( + VLAN, + params.get("id"), + )._raw_json, + ), + InfoModuleAttr( + display_name="label", + name="label", + type=FieldType.string, + get=lambda client, params: safe_find( + client.networking.vlans, + VLAN.label == params.get("label"), + raise_not_found=True, + )._raw_json, + ), ], - requirements=global_requirements, - author=global_authors, - options=linode_vlan_info_spec, examples=docs.specdoc_examples, - return_values={ - "vlan": SpecReturnValue( - description="The VLAN in JSON serialized form.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-vlans", - type=FieldType.dict, - sample=docs.result_vlan_samples, - ) - }, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -58,46 +58,5 @@ RETURN = r""" """ - -class LinodeVLANInfo(LinodeModuleBase): - """Module for getting info about a Linode VLAN""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.required_one_of: List[str] = [] - self.results = {"vlan": None} - - super().__init__( - module_arg_spec=self.module_arg_spec, - required_one_of=self.required_one_of, - ) - - def _get_vlan_by_label(self, label: str) -> Optional[VLAN]: - try: - return self.client.networking.vlans(VLAN.label == label)[0] - except IndexError: - return None - except Exception as exception: - return self.fail(msg="failed to get VLAN {0}".format(exception)) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for VLAN info module""" - - label: str = kwargs.get("label") - vlan = self._get_vlan_by_label(label) - - if vlan is None: - self.fail("failed to get vlan") - - self.results["vlan"] = vlan._raw_json - - return self.results - - -def main() -> None: - """Constructs and calls the Linode VLAN info module""" - LinodeVLANInfo() - - if __name__ == "__main__": - main() + module.run() diff --git a/plugins/modules/vlan_list.py b/plugins/modules/vlan_list.py index efc3c0b4..dcb5d240 100644 --- a/plugins/modules/vlan_list.py +++ b/plugins/modules/vlan_list.py @@ -5,97 +5,22 @@ from __future__ import absolute_import, division, print_function -from typing import Any, Dict, Optional - import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.vlan_list as docs -from ansible_collections.linode.cloud.plugins.module_utils.linode_common import ( - LinodeModuleBase, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_docs import ( - BETA_DISCLAIMER, - global_authors, - global_requirements, -) -from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( - construct_api_filter, - get_all_paginated, +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import ( + ListModule, ) -from ansible_specdoc.objects import ( - FieldType, - SpecDocMeta, - SpecField, - SpecReturnValue, -) - -spec_filter = { - "name": SpecField( - type=FieldType.string, - required=True, - description=[ - "The name of the field to filter on.", - "Valid filterable attributes can be found here: " - "https://techdocs.akamai.com/linode-api/reference/get-vlans", - ], - ), - "values": SpecField( - type=FieldType.list, - element_type=FieldType.string, - required=True, - description=[ - "A list of values to allow for this field.", - "Fields will pass this filter if at least one of these values matches.", - ], - ), -} -spec = { - # Disable the default values - "state": SpecField(type=FieldType.string, required=False, doc_hide=True), - "label": SpecField(type=FieldType.string, required=False, doc_hide=True), - "order": SpecField( - type=FieldType.string, - description=["The order to list VLANs in."], - default="asc", - choices=["desc", "asc"], - ), - "order_by": SpecField( - type=FieldType.string, description=["The attribute to order VLANs by."] - ), - "filters": SpecField( - type=FieldType.list, - element_type=FieldType.dict, - suboptions=spec_filter, - description=["A list of filters to apply to the resulting VLANs."], - ), - "count": SpecField( - type=FieldType.integer, - description=[ - "The number of results to return.", - "If undefined, all results will be returned.", - ], - ), -} - -SPECDOC_META = SpecDocMeta( - description=[ - "List and filter on Linode VLANs.", - BETA_DISCLAIMER, - ], - requirements=global_requirements, - author=global_authors, - options=spec, +module = ListModule( + result_display_name="VLANs", + result_field_name="vlans", + endpoint_template="/networking/vlans", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-vlans", examples=docs.specdoc_examples, - return_values={ - "vlans": SpecReturnValue( - description="The returned VLANs.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-vlans", - type=FieldType.list, - elements=FieldType.dict, - sample=docs.result_vlan_samples, - ) - }, + result_samples=docs.result_vlan_samples, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -103,34 +28,5 @@ RETURN = r""" """ - -class Module(LinodeModuleBase): - """Module for getting info about a Linode VLANs""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results: Dict[str, Any] = {"vlans": []} - - super().__init__(module_arg_spec=self.module_arg_spec) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for VLANs list module""" - - filter_dict = construct_api_filter(self.module.params) - - self.results["vlans"] = get_all_paginated( - self.client, - "/networking/vlans", - filter_dict, - num_results=self.module.params["count"], - ) - return self.results - - -def main() -> None: - """Constructs and calls the module""" - Module() - - if __name__ == "__main__": - main() + module.run() diff --git a/template/README.template.md b/template/README.template.md index 895729ff..1c6ab1eb 100644 --- a/template/README.template.md +++ b/template/README.template.md @@ -102,6 +102,31 @@ For more information on Ansible collection usage, see [Ansible's official usage Use-case examples for this collection can be found [here](./examples/README.md). +## Development + +The following section outlines various information relating to the development of this collection. + +### Attaching a Debugger + +To quickly and easily attach a debugger to a running module in this collection, +you can use the [madbg](https://pypi.org/project/madbg/) package: + +1. Install `madbg` in your local Python environment: + +```shell +pip install madbg +``` + +2. Call `madbg.set_trace(...)` at the location you would like to create a breakpoint at: + +```shell +import madbg; madbg.set_trace() +``` + +3. Run the module in either a playbook or a test. +4. In a separate shell, run `madbg connect`. +5. You should now be able to remotely debug the module as soon as the breakpoint is triggered. + ## Licensing GNU General Public License v3.0.