From 7b31bc24c69a673554757f24a066d72ef143dcd5 Mon Sep 17 00:00:00 2001 From: Erik Zilber Date: Mon, 26 Aug 2024 16:08:42 -0400 Subject: [PATCH 1/9] Migrated Token-related info and list modules to new framework (#576) * Migrated token info and list modules * Fixed docs --- README.md | 2 +- docs/inventory/instance.rst | 8 +- docs/modules/token_info.md | 8 +- docs/modules/token_list.md | 14 ++-- plugins/modules/token_info.py | 135 ++++++++++------------------------ plugins/modules/token_list.py | 123 +++---------------------------- 6 files changed, 64 insertions(+), 226 deletions(-) diff --git a/README.md b/README.md index 718887a2..53d6d71a 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ Name | Description | [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 StackScripts.| -[linode.cloud.token_list](./docs/modules/token_list.md)|List and filter on Linode Account tokens.| +[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.| 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/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/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() From c718506c0bad126db9870c1bfe6fc745ed79f74a Mon Sep 17 00:00:00 2001 From: Lena Garber <114949949+lgarber-akamai@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:15:49 -0400 Subject: [PATCH 2/9] doc: Add "Attaching a Debugger" section to README (#570) * Add "Attaching a Debugger" section * Run make gendocs --- README.md | 25 +++++++++++++++++++++++++ template/README.template.md | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/README.md b/README.md index 53d6d71a..f5affe10 100644 --- a/README.md +++ b/README.md @@ -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/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. From 93cb64bfabd176237a014a837e3c01a58e94b476 Mon Sep 17 00:00:00 2001 From: Erik Zilber Date: Tue, 27 Aug 2024 15:26:15 -0400 Subject: [PATCH 3/9] Migrated User-related list module to new framework (#578) * Migrated user list module * Fixed docs --- README.md | 2 +- docs/modules/user_list.md | 19 ++++++-- plugins/modules/user_list.py | 91 +++++------------------------------- 3 files changed, 26 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index f5affe10..6a30e876 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ Name | Description | [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.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 Linode 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.| 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/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() From 19fb2878478957356281c008c741c4957d511115 Mon Sep 17 00:00:00 2001 From: Erik Zilber Date: Tue, 27 Aug 2024 16:38:12 -0400 Subject: [PATCH 4/9] Implemented changes for Linode Disk Encryption (#550) * Implemented changes for LDE * Added tests * Fix lint * Addressed PR comments * fixed * Fixed docs * Removed default --- docs/modules/instance.md | 7 +- docs/modules/instance_info.md | 5 +- docs/modules/instance_list.md | 4 +- docs/modules/lke_cluster.md | 1 + docs/modules/lke_cluster_info.md | 1 + docs/modules/lke_node_pool.md | 1 + .../module_utils/doc_fragments/instance.py | 5 +- .../doc_fragments/instance_list.py | 4 +- .../module_utils/doc_fragments/lke_cluster.py | 1 + .../doc_fragments/lke_node_pool.py | 1 + plugins/modules/instance.py | 12 ++ .../instance_disk_encryption/tasks/main.yaml | 143 ++++++++++++++++++ .../targets/lke_cluster_basic/tasks/main.yaml | 30 ++++ .../lke_node_pool_basic/tasks/main.yaml | 54 +++++++ 14 files changed, 264 insertions(+), 5 deletions(-) create mode 100644 tests/integration/targets/instance_disk_encryption/tasks/main.yaml diff --git a/docs/modules/instance.md b/docs/modules/instance.md index 581e93f2..919e66ee 100644 --- a/docs/modules/instance.md +++ b/docs/modules/instance.md @@ -149,6 +149,7 @@ Manage Linode Instances, Configs, and Disks. | `auto_disk_resize` |
`bool`
|
Optional
| Whether implicitly created disks should be resized during a type change operation. **(Default: `False`)** | | `tags` |
`list`
|
Optional
| An array of tags applied to this object. Tags are for organizational purposes only. **(Updatable)** | | [`placement_group` (sub-options)](#placement_group) |
`dict`
|
Optional
| A Placement Group to create this Linode under. | +| `disk_encryption` |
`str`
|
Optional
| The disk encryption status of this Linode. NOTE: Disk encryption may not currently be available to all users. **(Choices: `enabled`, `disabled`)** | | `swap_size` |
`int`
|
Optional
| When deploying from an Image, this field is optional, otherwise it is ignored. This is used to set the swap disk size for the newly-created Linode. | ### configs @@ -274,6 +275,7 @@ Manage Linode Instances, Configs, and Disks. | `authorized_keys` |
`list`
|
Optional
| A list of SSH public key parts to deploy for the root user. | | `authorized_users` |
`list`
|
Optional
| A list of usernames. | | `filesystem` |
`str`
|
Optional
| The filesystem to create this disk with. | +| `disk_encryption` |
`str`
|
Optional
| The disk encryption status of this disk.NOTE: Disk encryption may not currently be available to all users. **(Choices: `enabled`, `disabled`)** | | `image` |
`str`
|
Optional
| An Image ID to deploy the Disk from. | | `root_pass` |
`str`
|
Optional
| The root user’s password on the newly-created Linode. | | `stackscript_id` |
`int`
|
Optional
| The ID of the StackScript to use when creating the instance. See the [Linode API documentation](https://techdocs.akamai.com/linode-api/reference/get-stack-scripts). | @@ -354,6 +356,8 @@ Manage Linode Instances, Configs, and Disks. "placement_group_type": "anti_affinity:local", "placement_group_policy": "strict" } + "disk_encryption": "enabled", + "lke_cluster_id": null } ``` - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-linode-instance) for a list of returned fields @@ -439,7 +443,8 @@ Manage Linode Instances, Configs, and Disks. "label": "Debian 9 Disk", "size": 48640, "status": "ready", - "updated": "2018-01-01T00:01:01" + "updated": "2018-01-01T00:01:01", + "disk_encryption": "enabled" } ] ``` diff --git a/docs/modules/instance_info.md b/docs/modules/instance_info.md index 21c59298..0376d36c 100644 --- a/docs/modules/instance_info.md +++ b/docs/modules/instance_info.md @@ -89,6 +89,8 @@ Get info about a Linode Instance. "placement_group_type": "anti_affinity:local", "placement_group_policy": "strict" } + "disk_encryption": "enabled", + "lke_cluster_id": null } ``` - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-linode-instance) for a list of returned fields @@ -174,7 +176,8 @@ Get info about a Linode Instance. "label": "Debian 9 Disk", "size": 48640, "status": "ready", - "updated": "2018-01-01T00:01:01" + "updated": "2018-01-01T00:01:01", + "disk_encryption": "enabled" } ] ``` diff --git a/docs/modules/instance_list.md b/docs/modules/instance_list.md index e0b63c07..156a41a3 100644 --- a/docs/modules/instance_list.md +++ b/docs/modules/instance_list.md @@ -94,7 +94,9 @@ List and filter on Instances. ], "type": "g6-standard-1", "updated": "2018-01-01T00:01:01", - "watchdog_enabled": true + "watchdog_enabled": true, + "disk_encryption": "enabled", + "lke_cluster_id": null } ] ``` diff --git a/docs/modules/lke_cluster.md b/docs/modules/lke_cluster.md index d18469bd..7208c89e 100644 --- a/docs/modules/lke_cluster.md +++ b/docs/modules/lke_cluster.md @@ -139,6 +139,7 @@ Manage Linode LKE clusters. "max": 12, "min": 3 }, + "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/docs/modules/lke_cluster_info.md b/docs/modules/lke_cluster_info.md index 3c395fce..23dbfe75 100644 --- a/docs/modules/lke_cluster_info.md +++ b/docs/modules/lke_cluster_info.md @@ -77,6 +77,7 @@ Get info about a Linode LKE cluster. "max": 12, "min": 3 }, + "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/docs/modules/lke_node_pool.md b/docs/modules/lke_node_pool.md index 9d9767e7..57a76fa3 100644 --- a/docs/modules/lke_node_pool.md +++ b/docs/modules/lke_node_pool.md @@ -89,6 +89,7 @@ Manage Linode LKE cluster node pools. "max": 12, "min": 3 }, + "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/plugins/module_utils/doc_fragments/instance.py b/plugins/module_utils/doc_fragments/instance.py index f13bf3d3..a71d3fa9 100644 --- a/plugins/module_utils/doc_fragments/instance.py +++ b/plugins/module_utils/doc_fragments/instance.py @@ -135,6 +135,8 @@ "placement_group_type": "anti_affinity:local", "placement_group_policy": "strict" } + "disk_encryption": "enabled", + "lke_cluster_id": null }'''] result_configs_samples = ['''[ @@ -206,7 +208,8 @@ "label": "Debian 9 Disk", "size": 48640, "status": "ready", - "updated": "2018-01-01T00:01:01" + "updated": "2018-01-01T00:01:01", + "disk_encryption": "enabled" } ]'''] diff --git a/plugins/module_utils/doc_fragments/instance_list.py b/plugins/module_utils/doc_fragments/instance_list.py index d69ef97c..41191845 100644 --- a/plugins/module_utils/doc_fragments/instance_list.py +++ b/plugins/module_utils/doc_fragments/instance_list.py @@ -53,6 +53,8 @@ ], "type": "g6-standard-1", "updated": "2018-01-01T00:01:01", - "watchdog_enabled": true + "watchdog_enabled": true, + "disk_encryption": "enabled", + "lke_cluster_id": null } ]'''] diff --git a/plugins/module_utils/doc_fragments/lke_cluster.py b/plugins/module_utils/doc_fragments/lke_cluster.py index f9b9ba8f..2a89d0b7 100644 --- a/plugins/module_utils/doc_fragments/lke_cluster.py +++ b/plugins/module_utils/doc_fragments/lke_cluster.py @@ -60,6 +60,7 @@ "max": 12, "min": 3 }, + "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/plugins/module_utils/doc_fragments/lke_node_pool.py b/plugins/module_utils/doc_fragments/lke_node_pool.py index d58bb9fd..e7d86544 100644 --- a/plugins/module_utils/doc_fragments/lke_node_pool.py +++ b/plugins/module_utils/doc_fragments/lke_node_pool.py @@ -35,6 +35,7 @@ "max": 12, "min": 3 }, + "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/plugins/modules/instance.py b/plugins/modules/instance.py index eeb38bc6..d7740953 100644 --- a/plugins/modules/instance.py +++ b/plugins/modules/instance.py @@ -83,6 +83,12 @@ type=FieldType.string, description=["The filesystem to create this disk with."], ), + "disk_encryption": SpecField( + type=FieldType.string, + description="The disk encryption status of this disk." + + "NOTE: Disk encryption may not currently be available to all users.", + choices=["enabled", "disabled"], + ), "image": SpecField( type=FieldType.string, description=["An Image ID to deploy the Disk from."], @@ -523,6 +529,12 @@ suboptions=linode_instance_placement_group_spec, description=["A Placement Group to create this Linode under."], ), + "disk_encryption": SpecField( + type=FieldType.string, + description="The disk encryption status of this Linode. " + + "NOTE: Disk encryption may not currently be available to all users.", + choices=["enabled", "disabled"], + ), "swap_size": SpecField( type=FieldType.integer, description=[ diff --git a/tests/integration/targets/instance_disk_encryption/tasks/main.yaml b/tests/integration/targets/instance_disk_encryption/tasks/main.yaml new file mode 100644 index 00000000..cbb92667 --- /dev/null +++ b/tests/integration/targets/instance_disk_encryption/tasks/main.yaml @@ -0,0 +1,143 @@ +- name: instance_disk_encryption + block: + - set_fact: + r: "{{ 1000000000 | random }}" + + - name: List regions that support Disk Encryption + linode.cloud.region_list: {} + register: all_regions + + - set_fact: + lde_region: '{{ (all_regions.regions | selectattr("capabilities", "search", "Disk Encryption") | list)[0].id }}' + + - name: Create a Linode instance with disk encryption set + linode.cloud.instance: + label: 'ansible-test-disk-encryption-{{ r }}' + region: '{{ lde_region }}' + type: g6-standard-1 + image: linode/ubuntu22.04 + private_ip: true + wait: false + state: present + firewall_id: '{{ firewall_id }}' + disk_encryption: 'enabled' + register: create_instance_with_disk_encryption + + - name: Assert instance created + assert: + that: + - create_instance_with_disk_encryption.changed + - create_instance_with_disk_encryption.instance.disk_encryption == 'enabled' + + - name: Create a Linode instance with explicit disks with disk encryption set + linode.cloud.instance: + label: 'ansible-test-disks-disk-encryption-{{ r }}' + region: '{{ lde_region }}' + type: g6-standard-1 + booted: false + disks: + - label: test-disk + filesystem: ext4 + size: 5000 + state: present + firewall_id: '{{ firewall_id }}' + disk_encryption: 'enabled' + register: create_instance_disks_disk_encryption + + - name: Assert instance created + assert: + that: + - create_instance_disks_disk_encryption.changed + - create_instance_disks_disk_encryption.instance.disk_encryption == 'enabled' + - create_instance_disks_disk_encryption.disks[0].disk_encryption == 'enabled' + + - name: Create a small Linode instance with two disks that sum up to its max size + linode.cloud.instance: + label: 'ansible-test-disks-max-size-{{ r }}' + region: '{{ lde_region }}' + type: g6-nanode-1 + booted: false + disks: + - label: test-disk-1 + filesystem: ext4 + size: 15000 + - label: test-disk-2 + filesystem: ext4 + size: 10000 + state: present + firewall_id: '{{ firewall_id }}' + disk_encryption: 'enabled' + register: create_instance_disks_max_size + + - name: Assert instance created + assert: + that: + - create_instance_disks_max_size.changed + - create_instance_disks_max_size.disks[0].size == 15000 + - create_instance_disks_max_size.disks[1].size == 10000 + + - name: Update the instance to resize test-disk-1 and test-disk-2 + linode.cloud.instance: + label: "{{ create_instance_disks_max_size.instance.label }}" + disks: + - label: test-disk-1 + filesystem: ext4 + size: 14500 + - label: test-disk-2 + filesystem: ext4 + size: 10500 + state: present + register: resize_disks + + - name: Assert instance created + assert: + that: + - resize_disks.changed + - resize_disks.disks[0].size == 14500 + - resize_disks.disks[1].size == 10500 + + always: + - ignore_errors: yes + block: + - name: Delete a Linode instance + linode.cloud.instance: + label: 'ansible-test-disk-encryption-{{ r }}' + state: absent + register: delete_disk_encryption + + - name: Assert instance delete succeeded + assert: + that: + - delete_disk_encryption.changed + - delete_disk_encryption.instance.id == create_instance_with_disk_encryption.instance.id + + - name: Delete a Linode instance + linode.cloud.instance: + label: 'ansible-test-disks-disk-encryption-{{ r }}' + state: absent + register: delete_disks_disk_encryption + + - name: Assert instance delete succeeded + assert: + that: + - delete_disks_disk_encryption.changed + - delete_disks_disk_encryption.instance.id == create_instance_disks_disk_encryption.instance.id + + - name: Delete a Linode instance + linode.cloud.instance: + label: 'ansible-test-disks-max-size-{{ r }}' + state: absent + register: delete_disks_max_size + + - name: Assert instance delete succeeded + assert: + that: + - delete_disks_max_size.changed + - delete_disks_max_size.instance.id == create_instance_disks_max_size.instance.id + + environment: + LINODE_UA_PREFIX: '{{ ua_prefix }}' + LINODE_API_TOKEN: '{{ api_token }}' + LINODE_API_URL: '{{ api_url }}' + LINODE_API_VERSION: '{{ api_version }}' + LINODE_CA: '{{ ca_file or "" }}' \ No newline at end of file diff --git a/tests/integration/targets/lke_cluster_basic/tasks/main.yaml b/tests/integration/targets/lke_cluster_basic/tasks/main.yaml index 3da2258e..c7f3f615 100644 --- a/tests/integration/targets/lke_cluster_basic/tasks/main.yaml +++ b/tests/integration/targets/lke_cluster_basic/tasks/main.yaml @@ -16,6 +16,13 @@ # Sometimes only one LKE version is available for provisioning kube_version: '{{ lke_versions[1].id if lke_versions|length > 1 else lke_versions[0].id }}' + - name: List regions that support Disk Encryption + linode.cloud.region_list: {} + register: all_regions + + - set_fact: + lde_region: '{{ (all_regions.regions | selectattr("capabilities", "search", "Disk Encryption") | list)[0].id }}' + - name: Create a Linode LKE cluster linode.cloud.lke_cluster: label: 'ansible-test-{{ r }}' @@ -147,6 +154,23 @@ - info_by_label.node_pools[0].count == 1 - info_by_label.node_pools[0].id == create_cluster.node_pools[0].id + - name: Create a Linode LKE cluster with a pool with disk encryption enabled + linode.cloud.lke_cluster: + label: 'ansible-test-de-{{ r }}' + region: '{{ lde_region }}' + k8s_version: '{{ old_kube_version }}' + node_pools: + - type: g6-standard-1 + count: 3 + skip_polling: true + state: present + register: create_cluster_disk_encryption + + - name: Assert LKE cluster is created + assert: + that: + - create_cluster_disk_encryption.node_pools[0].disk_encryption == 'enabled' + always: - ignore_errors: yes block: @@ -155,6 +179,12 @@ label: '{{ create_cluster.cluster.label }}' state: absent + - name: Delete the LKE cluster + linode.cloud.lke_cluster: + label: '{{ create_cluster_disk_encryption.cluster.label }}' + state: absent + + environment: LINODE_UA_PREFIX: '{{ ua_prefix }}' LINODE_API_TOKEN: '{{ api_token }}' diff --git a/tests/integration/targets/lke_node_pool_basic/tasks/main.yaml b/tests/integration/targets/lke_node_pool_basic/tasks/main.yaml index 92c3cede..0142e3cb 100644 --- a/tests/integration/targets/lke_node_pool_basic/tasks/main.yaml +++ b/tests/integration/targets/lke_node_pool_basic/tasks/main.yaml @@ -10,6 +10,13 @@ - set_fact: kube_version: '{{ lke_versions.lke_versions[0].id }}' + - name: List regions that support Disk Encryption + linode.cloud.region_list: {} + register: all_regions + + - set_fact: + lde_region: '{{ (all_regions.regions | selectattr("capabilities", "search", "Disk Encryption") | list)[0].id }}' + - name: Create a minimal LKE cluster linode.cloud.lke_cluster: label: 'ansible-test-{{ r }}' @@ -83,6 +90,44 @@ - update_pool.node_pool.autoscaler.min == 1 - update_pool.node_pool.autoscaler.max == 3 + - name: Create a minimal LKE cluster + linode.cloud.lke_cluster: + label: 'ansible-test-de-{{ r }}' + region: '{{ lde_region }}' + k8s_version: '{{ kube_version }}' + node_pools: + - type: g6-standard-1 + count: 1 + skip_polling: true + state: present + register: create_cluster_de + + - name: Assert minimal LKE cluster is created + assert: + that: + - create_cluster_de.cluster.k8s_version == kube_version + - create_cluster_de.node_pools[0].type == 'g6-standard-1' + - create_cluster_de.node_pools[0].count == 1 + + - name: Add a node pool to the cluster + linode.cloud.lke_node_pool: + cluster_id: '{{ create_cluster_de.cluster.id }}' + + tags: ['my-pool'] + type: g6-standard-1 + count: 2 + state: present + register: new_pool_de + + - name: Assert node pool is added to cluster + assert: + that: + - new_pool_de.node_pool.count == 2 + - new_pool_de.node_pool.type == 'g6-standard-1' + - new_pool_de.node_pool.disk_encryption == 'enabled' + - new_pool_de.node_pool.nodes[0].status == 'ready' + - new_pool_de.node_pool.nodes[1].status == 'ready' + always: - ignore_errors: yes block: @@ -95,6 +140,15 @@ linode.cloud.lke_cluster: label: '{{ create_cluster.cluster.label }}' state: absent + - name: Delete the LKE cluster node pool + linode.cloud.lke_node_pool: + cluster_id: '{{ create_cluster_de.cluster.id }}' + tags: ['my-pool'] + state: absent + - name: Delete the LKE cluster + linode.cloud.lke_cluster: + label: '{{ create_cluster_de.cluster.label }}' + state: absent environment: LINODE_UA_PREFIX: '{{ ua_prefix }}' From 1b2d1a70f4ce428240109e54c05c1890f73d91b6 Mon Sep 17 00:00:00 2001 From: Erik Zilber Date: Wed, 28 Aug 2024 10:22:33 -0400 Subject: [PATCH 5/9] Revert "Implemented changes for Linode Disk Encryption (#550)" (#581) This reverts commit 19fb2878478957356281c008c741c4957d511115. --- docs/modules/instance.md | 7 +- docs/modules/instance_info.md | 5 +- docs/modules/instance_list.md | 4 +- docs/modules/lke_cluster.md | 1 - docs/modules/lke_cluster_info.md | 1 - docs/modules/lke_node_pool.md | 1 - .../module_utils/doc_fragments/instance.py | 5 +- .../doc_fragments/instance_list.py | 4 +- .../module_utils/doc_fragments/lke_cluster.py | 1 - .../doc_fragments/lke_node_pool.py | 1 - plugins/modules/instance.py | 12 -- .../instance_disk_encryption/tasks/main.yaml | 143 ------------------ .../targets/lke_cluster_basic/tasks/main.yaml | 30 ---- .../lke_node_pool_basic/tasks/main.yaml | 54 ------- 14 files changed, 5 insertions(+), 264 deletions(-) delete mode 100644 tests/integration/targets/instance_disk_encryption/tasks/main.yaml diff --git a/docs/modules/instance.md b/docs/modules/instance.md index 919e66ee..581e93f2 100644 --- a/docs/modules/instance.md +++ b/docs/modules/instance.md @@ -149,7 +149,6 @@ Manage Linode Instances, Configs, and Disks. | `auto_disk_resize` |
`bool`
|
Optional
| Whether implicitly created disks should be resized during a type change operation. **(Default: `False`)** | | `tags` |
`list`
|
Optional
| An array of tags applied to this object. Tags are for organizational purposes only. **(Updatable)** | | [`placement_group` (sub-options)](#placement_group) |
`dict`
|
Optional
| A Placement Group to create this Linode under. | -| `disk_encryption` |
`str`
|
Optional
| The disk encryption status of this Linode. NOTE: Disk encryption may not currently be available to all users. **(Choices: `enabled`, `disabled`)** | | `swap_size` |
`int`
|
Optional
| When deploying from an Image, this field is optional, otherwise it is ignored. This is used to set the swap disk size for the newly-created Linode. | ### configs @@ -275,7 +274,6 @@ Manage Linode Instances, Configs, and Disks. | `authorized_keys` |
`list`
|
Optional
| A list of SSH public key parts to deploy for the root user. | | `authorized_users` |
`list`
|
Optional
| A list of usernames. | | `filesystem` |
`str`
|
Optional
| The filesystem to create this disk with. | -| `disk_encryption` |
`str`
|
Optional
| The disk encryption status of this disk.NOTE: Disk encryption may not currently be available to all users. **(Choices: `enabled`, `disabled`)** | | `image` |
`str`
|
Optional
| An Image ID to deploy the Disk from. | | `root_pass` |
`str`
|
Optional
| The root user’s password on the newly-created Linode. | | `stackscript_id` |
`int`
|
Optional
| The ID of the StackScript to use when creating the instance. See the [Linode API documentation](https://techdocs.akamai.com/linode-api/reference/get-stack-scripts). | @@ -356,8 +354,6 @@ Manage Linode Instances, Configs, and Disks. "placement_group_type": "anti_affinity:local", "placement_group_policy": "strict" } - "disk_encryption": "enabled", - "lke_cluster_id": null } ``` - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-linode-instance) for a list of returned fields @@ -443,8 +439,7 @@ Manage Linode Instances, Configs, and Disks. "label": "Debian 9 Disk", "size": 48640, "status": "ready", - "updated": "2018-01-01T00:01:01", - "disk_encryption": "enabled" + "updated": "2018-01-01T00:01:01" } ] ``` diff --git a/docs/modules/instance_info.md b/docs/modules/instance_info.md index 0376d36c..21c59298 100644 --- a/docs/modules/instance_info.md +++ b/docs/modules/instance_info.md @@ -89,8 +89,6 @@ Get info about a Linode Instance. "placement_group_type": "anti_affinity:local", "placement_group_policy": "strict" } - "disk_encryption": "enabled", - "lke_cluster_id": null } ``` - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-linode-instance) for a list of returned fields @@ -176,8 +174,7 @@ Get info about a Linode Instance. "label": "Debian 9 Disk", "size": 48640, "status": "ready", - "updated": "2018-01-01T00:01:01", - "disk_encryption": "enabled" + "updated": "2018-01-01T00:01:01" } ] ``` diff --git a/docs/modules/instance_list.md b/docs/modules/instance_list.md index 156a41a3..e0b63c07 100644 --- a/docs/modules/instance_list.md +++ b/docs/modules/instance_list.md @@ -94,9 +94,7 @@ List and filter on Instances. ], "type": "g6-standard-1", "updated": "2018-01-01T00:01:01", - "watchdog_enabled": true, - "disk_encryption": "enabled", - "lke_cluster_id": null + "watchdog_enabled": true } ] ``` diff --git a/docs/modules/lke_cluster.md b/docs/modules/lke_cluster.md index 7208c89e..d18469bd 100644 --- a/docs/modules/lke_cluster.md +++ b/docs/modules/lke_cluster.md @@ -139,7 +139,6 @@ Manage Linode LKE clusters. "max": 12, "min": 3 }, - "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/docs/modules/lke_cluster_info.md b/docs/modules/lke_cluster_info.md index 23dbfe75..3c395fce 100644 --- a/docs/modules/lke_cluster_info.md +++ b/docs/modules/lke_cluster_info.md @@ -77,7 +77,6 @@ Get info about a Linode LKE cluster. "max": 12, "min": 3 }, - "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/docs/modules/lke_node_pool.md b/docs/modules/lke_node_pool.md index 57a76fa3..9d9767e7 100644 --- a/docs/modules/lke_node_pool.md +++ b/docs/modules/lke_node_pool.md @@ -89,7 +89,6 @@ Manage Linode LKE cluster node pools. "max": 12, "min": 3 }, - "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/plugins/module_utils/doc_fragments/instance.py b/plugins/module_utils/doc_fragments/instance.py index a71d3fa9..f13bf3d3 100644 --- a/plugins/module_utils/doc_fragments/instance.py +++ b/plugins/module_utils/doc_fragments/instance.py @@ -135,8 +135,6 @@ "placement_group_type": "anti_affinity:local", "placement_group_policy": "strict" } - "disk_encryption": "enabled", - "lke_cluster_id": null }'''] result_configs_samples = ['''[ @@ -208,8 +206,7 @@ "label": "Debian 9 Disk", "size": 48640, "status": "ready", - "updated": "2018-01-01T00:01:01", - "disk_encryption": "enabled" + "updated": "2018-01-01T00:01:01" } ]'''] diff --git a/plugins/module_utils/doc_fragments/instance_list.py b/plugins/module_utils/doc_fragments/instance_list.py index 41191845..d69ef97c 100644 --- a/plugins/module_utils/doc_fragments/instance_list.py +++ b/plugins/module_utils/doc_fragments/instance_list.py @@ -53,8 +53,6 @@ ], "type": "g6-standard-1", "updated": "2018-01-01T00:01:01", - "watchdog_enabled": true, - "disk_encryption": "enabled", - "lke_cluster_id": null + "watchdog_enabled": true } ]'''] diff --git a/plugins/module_utils/doc_fragments/lke_cluster.py b/plugins/module_utils/doc_fragments/lke_cluster.py index 2a89d0b7..f9b9ba8f 100644 --- a/plugins/module_utils/doc_fragments/lke_cluster.py +++ b/plugins/module_utils/doc_fragments/lke_cluster.py @@ -60,7 +60,6 @@ "max": 12, "min": 3 }, - "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/plugins/module_utils/doc_fragments/lke_node_pool.py b/plugins/module_utils/doc_fragments/lke_node_pool.py index e7d86544..d58bb9fd 100644 --- a/plugins/module_utils/doc_fragments/lke_node_pool.py +++ b/plugins/module_utils/doc_fragments/lke_node_pool.py @@ -35,7 +35,6 @@ "max": 12, "min": 3 }, - "disk_encryption": "enabled", "count": 6, "disks": [ { diff --git a/plugins/modules/instance.py b/plugins/modules/instance.py index d7740953..eeb38bc6 100644 --- a/plugins/modules/instance.py +++ b/plugins/modules/instance.py @@ -83,12 +83,6 @@ type=FieldType.string, description=["The filesystem to create this disk with."], ), - "disk_encryption": SpecField( - type=FieldType.string, - description="The disk encryption status of this disk." - + "NOTE: Disk encryption may not currently be available to all users.", - choices=["enabled", "disabled"], - ), "image": SpecField( type=FieldType.string, description=["An Image ID to deploy the Disk from."], @@ -529,12 +523,6 @@ suboptions=linode_instance_placement_group_spec, description=["A Placement Group to create this Linode under."], ), - "disk_encryption": SpecField( - type=FieldType.string, - description="The disk encryption status of this Linode. " - + "NOTE: Disk encryption may not currently be available to all users.", - choices=["enabled", "disabled"], - ), "swap_size": SpecField( type=FieldType.integer, description=[ diff --git a/tests/integration/targets/instance_disk_encryption/tasks/main.yaml b/tests/integration/targets/instance_disk_encryption/tasks/main.yaml deleted file mode 100644 index cbb92667..00000000 --- a/tests/integration/targets/instance_disk_encryption/tasks/main.yaml +++ /dev/null @@ -1,143 +0,0 @@ -- name: instance_disk_encryption - block: - - set_fact: - r: "{{ 1000000000 | random }}" - - - name: List regions that support Disk Encryption - linode.cloud.region_list: {} - register: all_regions - - - set_fact: - lde_region: '{{ (all_regions.regions | selectattr("capabilities", "search", "Disk Encryption") | list)[0].id }}' - - - name: Create a Linode instance with disk encryption set - linode.cloud.instance: - label: 'ansible-test-disk-encryption-{{ r }}' - region: '{{ lde_region }}' - type: g6-standard-1 - image: linode/ubuntu22.04 - private_ip: true - wait: false - state: present - firewall_id: '{{ firewall_id }}' - disk_encryption: 'enabled' - register: create_instance_with_disk_encryption - - - name: Assert instance created - assert: - that: - - create_instance_with_disk_encryption.changed - - create_instance_with_disk_encryption.instance.disk_encryption == 'enabled' - - - name: Create a Linode instance with explicit disks with disk encryption set - linode.cloud.instance: - label: 'ansible-test-disks-disk-encryption-{{ r }}' - region: '{{ lde_region }}' - type: g6-standard-1 - booted: false - disks: - - label: test-disk - filesystem: ext4 - size: 5000 - state: present - firewall_id: '{{ firewall_id }}' - disk_encryption: 'enabled' - register: create_instance_disks_disk_encryption - - - name: Assert instance created - assert: - that: - - create_instance_disks_disk_encryption.changed - - create_instance_disks_disk_encryption.instance.disk_encryption == 'enabled' - - create_instance_disks_disk_encryption.disks[0].disk_encryption == 'enabled' - - - name: Create a small Linode instance with two disks that sum up to its max size - linode.cloud.instance: - label: 'ansible-test-disks-max-size-{{ r }}' - region: '{{ lde_region }}' - type: g6-nanode-1 - booted: false - disks: - - label: test-disk-1 - filesystem: ext4 - size: 15000 - - label: test-disk-2 - filesystem: ext4 - size: 10000 - state: present - firewall_id: '{{ firewall_id }}' - disk_encryption: 'enabled' - register: create_instance_disks_max_size - - - name: Assert instance created - assert: - that: - - create_instance_disks_max_size.changed - - create_instance_disks_max_size.disks[0].size == 15000 - - create_instance_disks_max_size.disks[1].size == 10000 - - - name: Update the instance to resize test-disk-1 and test-disk-2 - linode.cloud.instance: - label: "{{ create_instance_disks_max_size.instance.label }}" - disks: - - label: test-disk-1 - filesystem: ext4 - size: 14500 - - label: test-disk-2 - filesystem: ext4 - size: 10500 - state: present - register: resize_disks - - - name: Assert instance created - assert: - that: - - resize_disks.changed - - resize_disks.disks[0].size == 14500 - - resize_disks.disks[1].size == 10500 - - always: - - ignore_errors: yes - block: - - name: Delete a Linode instance - linode.cloud.instance: - label: 'ansible-test-disk-encryption-{{ r }}' - state: absent - register: delete_disk_encryption - - - name: Assert instance delete succeeded - assert: - that: - - delete_disk_encryption.changed - - delete_disk_encryption.instance.id == create_instance_with_disk_encryption.instance.id - - - name: Delete a Linode instance - linode.cloud.instance: - label: 'ansible-test-disks-disk-encryption-{{ r }}' - state: absent - register: delete_disks_disk_encryption - - - name: Assert instance delete succeeded - assert: - that: - - delete_disks_disk_encryption.changed - - delete_disks_disk_encryption.instance.id == create_instance_disks_disk_encryption.instance.id - - - name: Delete a Linode instance - linode.cloud.instance: - label: 'ansible-test-disks-max-size-{{ r }}' - state: absent - register: delete_disks_max_size - - - name: Assert instance delete succeeded - assert: - that: - - delete_disks_max_size.changed - - delete_disks_max_size.instance.id == create_instance_disks_max_size.instance.id - - environment: - LINODE_UA_PREFIX: '{{ ua_prefix }}' - LINODE_API_TOKEN: '{{ api_token }}' - LINODE_API_URL: '{{ api_url }}' - LINODE_API_VERSION: '{{ api_version }}' - LINODE_CA: '{{ ca_file or "" }}' \ No newline at end of file diff --git a/tests/integration/targets/lke_cluster_basic/tasks/main.yaml b/tests/integration/targets/lke_cluster_basic/tasks/main.yaml index c7f3f615..3da2258e 100644 --- a/tests/integration/targets/lke_cluster_basic/tasks/main.yaml +++ b/tests/integration/targets/lke_cluster_basic/tasks/main.yaml @@ -16,13 +16,6 @@ # Sometimes only one LKE version is available for provisioning kube_version: '{{ lke_versions[1].id if lke_versions|length > 1 else lke_versions[0].id }}' - - name: List regions that support Disk Encryption - linode.cloud.region_list: {} - register: all_regions - - - set_fact: - lde_region: '{{ (all_regions.regions | selectattr("capabilities", "search", "Disk Encryption") | list)[0].id }}' - - name: Create a Linode LKE cluster linode.cloud.lke_cluster: label: 'ansible-test-{{ r }}' @@ -154,23 +147,6 @@ - info_by_label.node_pools[0].count == 1 - info_by_label.node_pools[0].id == create_cluster.node_pools[0].id - - name: Create a Linode LKE cluster with a pool with disk encryption enabled - linode.cloud.lke_cluster: - label: 'ansible-test-de-{{ r }}' - region: '{{ lde_region }}' - k8s_version: '{{ old_kube_version }}' - node_pools: - - type: g6-standard-1 - count: 3 - skip_polling: true - state: present - register: create_cluster_disk_encryption - - - name: Assert LKE cluster is created - assert: - that: - - create_cluster_disk_encryption.node_pools[0].disk_encryption == 'enabled' - always: - ignore_errors: yes block: @@ -179,12 +155,6 @@ label: '{{ create_cluster.cluster.label }}' state: absent - - name: Delete the LKE cluster - linode.cloud.lke_cluster: - label: '{{ create_cluster_disk_encryption.cluster.label }}' - state: absent - - environment: LINODE_UA_PREFIX: '{{ ua_prefix }}' LINODE_API_TOKEN: '{{ api_token }}' diff --git a/tests/integration/targets/lke_node_pool_basic/tasks/main.yaml b/tests/integration/targets/lke_node_pool_basic/tasks/main.yaml index 0142e3cb..92c3cede 100644 --- a/tests/integration/targets/lke_node_pool_basic/tasks/main.yaml +++ b/tests/integration/targets/lke_node_pool_basic/tasks/main.yaml @@ -10,13 +10,6 @@ - set_fact: kube_version: '{{ lke_versions.lke_versions[0].id }}' - - name: List regions that support Disk Encryption - linode.cloud.region_list: {} - register: all_regions - - - set_fact: - lde_region: '{{ (all_regions.regions | selectattr("capabilities", "search", "Disk Encryption") | list)[0].id }}' - - name: Create a minimal LKE cluster linode.cloud.lke_cluster: label: 'ansible-test-{{ r }}' @@ -90,44 +83,6 @@ - update_pool.node_pool.autoscaler.min == 1 - update_pool.node_pool.autoscaler.max == 3 - - name: Create a minimal LKE cluster - linode.cloud.lke_cluster: - label: 'ansible-test-de-{{ r }}' - region: '{{ lde_region }}' - k8s_version: '{{ kube_version }}' - node_pools: - - type: g6-standard-1 - count: 1 - skip_polling: true - state: present - register: create_cluster_de - - - name: Assert minimal LKE cluster is created - assert: - that: - - create_cluster_de.cluster.k8s_version == kube_version - - create_cluster_de.node_pools[0].type == 'g6-standard-1' - - create_cluster_de.node_pools[0].count == 1 - - - name: Add a node pool to the cluster - linode.cloud.lke_node_pool: - cluster_id: '{{ create_cluster_de.cluster.id }}' - - tags: ['my-pool'] - type: g6-standard-1 - count: 2 - state: present - register: new_pool_de - - - name: Assert node pool is added to cluster - assert: - that: - - new_pool_de.node_pool.count == 2 - - new_pool_de.node_pool.type == 'g6-standard-1' - - new_pool_de.node_pool.disk_encryption == 'enabled' - - new_pool_de.node_pool.nodes[0].status == 'ready' - - new_pool_de.node_pool.nodes[1].status == 'ready' - always: - ignore_errors: yes block: @@ -140,15 +95,6 @@ linode.cloud.lke_cluster: label: '{{ create_cluster.cluster.label }}' state: absent - - name: Delete the LKE cluster node pool - linode.cloud.lke_node_pool: - cluster_id: '{{ create_cluster_de.cluster.id }}' - tags: ['my-pool'] - state: absent - - name: Delete the LKE cluster - linode.cloud.lke_cluster: - label: '{{ create_cluster_de.cluster.label }}' - state: absent environment: LINODE_UA_PREFIX: '{{ ua_prefix }}' From abd4b3552c99a5ad8381dc67e76cca3b5db6cc49 Mon Sep 17 00:00:00 2001 From: Erik Zilber Date: Wed, 28 Aug 2024 10:55:17 -0400 Subject: [PATCH 6/9] Migrated SSH-Key-related info and list modules to new framework (#577) * Migrated ssh_key info and list modules * Fixed docs --- README.md | 4 +- docs/modules/ssh_key_info.md | 8 +- docs/modules/ssh_key_list.md | 14 ++-- plugins/modules/ssh_key_info.py | 131 +++++++++----------------------- plugins/modules/ssh_key_list.py | 125 +++--------------------------- 5 files changed, 61 insertions(+), 221 deletions(-) diff --git a/README.md b/README.md index 6a30e876..23089f21 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,7 +105,7 @@ 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.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.| 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/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() From ce05f8ac89baf00231b747c2467335dd4cfdf8fb Mon Sep 17 00:00:00 2001 From: Erik Zilber Date: Wed, 28 Aug 2024 14:39:07 -0400 Subject: [PATCH 7/9] Migrated VLAN-related list module to new framework (#579) * Migrated vlan info and list modules * Fixed docs --- README.md | 2 +- docs/modules/vlan_info.md | 7 +- docs/modules/vlan_list.md | 8 +-- plugins/modules/vlan_info.py | 115 ++++++++++---------------------- plugins/modules/vlan_list.py | 126 +++-------------------------------- 5 files changed, 55 insertions(+), 203 deletions(-) diff --git a/README.md b/README.md index 23089f21..00392c9e 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ Name | Description | [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 and filter on Users.| -[linode.cloud.vlan_list](./docs/modules/vlan_list.md)|List and filter on Linode VLANs.| +[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.| 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/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() From 73cbd64f2532f2b4bbf33e6d50858656bd07dbe8 Mon Sep 17 00:00:00 2001 From: Erik Zilber Date: Tue, 3 Sep 2024 11:28:19 -0400 Subject: [PATCH 8/9] Migrated Firewall-related info and list modules to new framework (#568) * Migrated firewall info and list modules * Fixed docs --- docs/modules/firewall_info.md | 10 +- docs/modules/firewall_list.md | 12 +-- plugins/modules/firewall_info.py | 161 +++++++++---------------------- plugins/modules/firewall_list.py | 126 +++--------------------- 4 files changed, 72 insertions(+), 237 deletions(-) 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/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() From 0ce1e792e90b15576a7c5aa54a711ff829c01cd9 Mon Sep 17 00:00:00 2001 From: Ye Chen <127243817+yec-akamai@users.noreply.github.com> Date: Tue, 3 Sep 2024 14:28:38 -0400 Subject: [PATCH 9/9] ref: Migrate lke_version_list to use common list info (#573) --- README.md | 2 +- docs/modules/lke_version_list.md | 17 +++-- plugins/modules/lke_version_list.py | 97 +++++------------------------ 3 files changed, 29 insertions(+), 87 deletions(-) diff --git a/README.md b/README.md index 00392c9e..b397fc6f 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ Name | Description | [linode.cloud.image_list](./docs/modules/image_list.md)|List and filter on Images.| [linode.cloud.instance_list](./docs/modules/instance_list.md)|List and filter on Instances.| [linode.cloud.instance_type_list](./docs/modules/instance_type_list.md)|**NOTE: This module has been deprecated in favor of `type_list`.| -[linode.cloud.lke_version_list](./docs/modules/lke_version_list.md)|List Kubernetes versions available for deployment to a Kubernetes cluster.| +[linode.cloud.lke_version_list](./docs/modules/lke_version_list.md)|List and filter on LKE Versions.| [linode.cloud.nodebalancer_list](./docs/modules/nodebalancer_list.md)|List and filter on Node Balancers.| [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.| diff --git a/docs/modules/lke_version_list.md b/docs/modules/lke_version_list.md index da6f0d54..f7474cc6 100644 --- a/docs/modules/lke_version_list.md +++ b/docs/modules/lke_version_list.md @@ -1,6 +1,6 @@ # lke_version_list -List Kubernetes versions available for deployment to a Kubernetes cluster. +List and filter on LKE Versions. - [Minimum Required Fields](#minimum-required-fields) - [Examples](#examples) @@ -24,12 +24,21 @@ List Kubernetes versions available for deployment to a Kubernetes cluster. | Field | Type | Required | Description | |-----------|------|----------|------------------------------------------------------------------------------| -| `order` |
`str`
|
Optional
| The order to list lke versions 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 LKE Versions in. **(Choices: `desc`, `asc`; Default: `asc`)** | +| `order_by` |
`str`
|
Optional
| The attribute to order LKE Versions by. | +| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting LKE Versions. | +| `count` |
`int`
|
Optional
| The number of LKE Versions 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-lke-versions). | +| `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 -- `lke_versions` - The returned LKE versions. +- `lke_versions` - The returned LKE Versions. - Sample Response: ```json diff --git a/plugins/modules/lke_version_list.py b/plugins/modules/lke_version_list.py index c0224400..97dbe869 100644 --- a/plugins/modules/lke_version_list.py +++ b/plugins/modules/lke_version_list.py @@ -1,67 +1,28 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -"""This module allows users to list Linode instances.""" -from __future__ import absolute_import, division, print_function +"""This module allows users to list Linode LKE Versions.""" -from typing import Any, Dict, Optional +from __future__ import absolute_import, division, print_function -import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.lke_version_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_collections.linode.cloud.plugins.module_utils.doc_fragments import ( + lke_version_list as docs, ) -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 lke versions 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 Kubernetes versions available for deployment to a Kubernetes cluster." - ], - requirements=global_requirements, - author=global_authors, - options=spec, +module = ListModule( + result_display_name="LKE Versions", + result_field_name="lke_versions", + endpoint_template="/lke/versions", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-lke-versions", + result_samples=docs.result_lke_versions_samples, examples=docs.specdoc_examples, - return_values={ - "lke_versions": SpecReturnValue( - description="The returned LKE versions.", - docs_url="https://techdocs.akamai.com/linode-api/reference/get-lke-versions", - type=FieldType.list, - elements=FieldType.dict, - sample=docs.result_lke_versions_samples, - ) - }, ) +SPECDOC_META = module.spec + DOCUMENTATION = r""" """ EXAMPLES = r""" @@ -69,33 +30,5 @@ RETURN = r""" """ - -class Module(LinodeModuleBase): - """Module for getting a list of Kubernetes versions""" - - def __init__(self) -> None: - self.module_arg_spec = SPECDOC_META.ansible_spec - self.results: Dict[str, Any] = {"lke_versions": []} - - super().__init__(module_arg_spec=self.module_arg_spec) - - def exec_module(self, **kwargs: Any) -> Optional[dict]: - """Entrypoint for lke version list module""" - - self.results["lke_versions"] = get_all_paginated( - self.client, - "/lke/versions", - 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()