Skip to content

Commit

Permalink
Migrated Token-related info and list modules to new framework (#576)
Browse files Browse the repository at this point in the history
* Migrated token info and list modules

* Fixed docs
  • Loading branch information
ezilber-akamai authored Aug 26, 2024
1 parent 9f3f30c commit 7b31bc2
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 226 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.|
Expand Down
8 changes: 4 additions & 4 deletions docs/inventory/instance.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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`.



Expand Down
8 changes: 4 additions & 4 deletions docs/modules/token_info.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ Get info about a Linode Personal Access Token.
| Field | Type | Required | Description |
|-----------|------|----------|------------------------------------------------------------------------------|
| `id` | <center>`int`</center> | <center>Optional</center> | The ID of the token. **(Conflicts With: `label`)** |
| `label` | <center>`str`</center> | <center>Optional</center> | The label of the token. **(Conflicts With: `id`)** |
| `label` | <center>`str`</center> | <center>Optional</center> | The label of the Personal Access Token to resolve. **(Conflicts With: `id`)** |
| `id` | <center>`int`</center> | <center>Optional</center> | 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
Expand All @@ -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


14 changes: 7 additions & 7 deletions docs/modules/token_list.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -32,21 +32,21 @@ List and filter on Linode Account tokens.
| Field | Type | Required | Description |
|-----------|------|----------|------------------------------------------------------------------------------|
| `order` | <center>`str`</center> | <center>Optional</center> | The order to list tokens in. **(Choices: `desc`, `asc`; Default: `asc`)** |
| `order_by` | <center>`str`</center> | <center>Optional</center> | The attribute to order tokens by. |
| [`filters` (sub-options)](#filters) | <center>`list`</center> | <center>Optional</center> | A list of filters to apply to the resulting tokens. |
| `count` | <center>`int`</center> | <center>Optional</center> | The number of results to return. If undefined, all results will be returned. |
| `order` | <center>`str`</center> | <center>Optional</center> | The order to list Tokens in. **(Choices: `desc`, `asc`; Default: `asc`)** |
| `order_by` | <center>`str`</center> | <center>Optional</center> | The attribute to order Tokens by. |
| [`filters` (sub-options)](#filters) | <center>`list`</center> | <center>Optional</center> | A list of filters to apply to the resulting Tokens. |
| `count` | <center>`int`</center> | <center>Optional</center> | The number of Tokens to return. If undefined, all results will be returned. |

### filters

| Field | Type | Required | Description |
|-----------|------|----------|------------------------------------------------------------------------------|
| `name` | <center>`str`</center> | <center>**Required**</center> | 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` | <center>`str`</center> | <center>**Required**</center> | 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` | <center>`list`</center> | <center>**Required**</center> | 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
Expand Down
135 changes: 37 additions & 98 deletions plugins/modules/token_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,120 +5,59 @@

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"""
"""
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()
123 changes: 11 additions & 112 deletions plugins/modules/token_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,129 +4,28 @@
"""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"""
"""
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()

0 comments on commit 7b31bc2

Please sign in to comment.