Skip to content

Commit

Permalink
Merge pull request #506 from linode/dev
Browse files Browse the repository at this point in the history
v0.25.8
  • Loading branch information
jriddle-linode authored May 20, 2024
2 parents 5494ae7 + 8ac62e2 commit cf84ef9
Show file tree
Hide file tree
Showing 16 changed files with 557 additions and 15 deletions.
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ansible_linode
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,10 @@ Name | Description |
[linode.cloud.user_list](./docs/modules/user_list.md)|List Users.|
[linode.cloud.vlan_list](./docs/modules/vlan_list.md)|List and filter on Linode VLANs.|
[linode.cloud.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.|
[linode.cloud.vpc_subnet_list](./docs/modules/vpc_subnet_list.md)|List and filter on VPC Subnets.|
[linode.cloud.vpcs_ip_list](./docs/modules/vpcs_ip_list.md)|List and filter on all VPC IP Addresses.|


### Inventory Plugins
Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ip_rdns.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Manage a Linode IP address's rDNS.
|-----------|------|----------|------------------------------------------------------------------------------|
| `address` | <center>`str`</center> | <center>**Required**</center> | The IP address. |
| `state` | <center>`str`</center> | <center>Optional</center> | The state of this rDNS of the IP address. **(Choices: `present`, `absent`)** |
| `rdns` | <center>`str`</center> | <center>Optional</center> | The desired rDNS value. **(Updatable)** |
| `rdns` | <center>`str`</center> | <center>Optional</center> | The desired RDNS value. **(Updatable)** |

## Return Values

Expand Down
66 changes: 66 additions & 0 deletions docs/modules/vpc_ip_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# vpc_ip_list

List and filter on VPC IP Addresses.

- [Minimum Required Fields](#minimum-required-fields)
- [Examples](#examples)
- [Parameters](#parameters)
- [Return Values](#return-values)

## Minimum Required Fields
| Field | Type | Required | Description |
|-------------|-------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api_token` | `str` | **Required** | The Linode account personal access token. It is necessary to run the module. <br/>It can be exposed by the environment variable `LINODE_API_TOKEN` instead. <br/>See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |

## Examples

```yaml
- name: List all IPs of a specific VPC.
linode.cloud.vpc_ip_list:
vpc_id: 12345
```
## Parameters
| Field | Type | Required | Description |
|-----------|------|----------|------------------------------------------------------------------------------|
| `vpc_id` | <center>`int`</center> | <center>**Required**</center> | The parent VPC for the VPC IP Addresses. |
| `order` | <center>`str`</center> | <center>Optional</center> | The order to list VPC IP Addresses in. **(Choices: `desc`, `asc`; Default: `asc`)** |
| `order_by` | <center>`str`</center> | <center>Optional</center> | The attribute to order VPC IP Addresses by. |
| [`filters` (sub-options)](#filters) | <center>`list`</center> | <center>Optional</center> | A list of filters to apply to the resulting VPC IP Addresses. |
| `count` | <center>`int`</center> | <center>Optional</center> | The number of VPC IP Addresses 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 fields can be found [here](). |
| `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

- `vpcs_ips` - The returned VPC IP Addresses.

- Sample Response:
```json
[
{
"address": "10.0.0.2",
"address_range": null,
"vpc_id": 56242,
"subnet_id": 55829,
"region": "us-mia",
"linode_id": 57328104,
"config_id": 60480976,
"interface_id": 1373818,
"active": false,
"nat_1_1": null,
"gateway": "10.0.0.1",
"prefix": 24,
"subnet_mask": "255.255.255.0",
}
]
```


65 changes: 65 additions & 0 deletions docs/modules/vpcs_ip_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# vpcs_ip_list

List and filter on all VPC IP Addresses.

- [Minimum Required Fields](#minimum-required-fields)
- [Examples](#examples)
- [Parameters](#parameters)
- [Return Values](#return-values)

## Minimum Required Fields
| Field | Type | Required | Description |
|-------------|-------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api_token` | `str` | **Required** | The Linode account personal access token. It is necessary to run the module. <br/>It can be exposed by the environment variable `LINODE_API_TOKEN` instead. <br/>See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |

## Examples

```yaml
- name: List all IPs of all VPCs in the account.
linode.cloud.vpcs_ip_list: {}
```
## Parameters
| Field | Type | Required | Description |
|-----------|------|----------|------------------------------------------------------------------------------|
| `order` | <center>`str`</center> | <center>Optional</center> | The order to list all VPC IP Addresses in. **(Choices: `desc`, `asc`; Default: `asc`)** |
| `order_by` | <center>`str`</center> | <center>Optional</center> | The attribute to order all VPC IP Addresses by. |
| [`filters` (sub-options)](#filters) | <center>`list`</center> | <center>Optional</center> | A list of filters to apply to the resulting all VPC IP Addresses. |
| `count` | <center>`int`</center> | <center>Optional</center> | The number of all VPC IP Addresses 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 fields can be found [here](). |
| `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

- `vpcs_ips` - The returned all VPC IP Addresses.

- Sample Response:
```json
[
{
"address": "10.0.0.2",
"address_range": null,
"vpc_id": 56242,
"subnet_id": 55829,
"region": "us-mia",
"linode_id": 57328104,
"config_id": 60480976,
"interface_id": 1373818,
"active": false,
"nat_1_1": null,
"gateway": "10.0.0.1",
"prefix": 24,
"subnet_mask": "255.255.255.0",
}
]
```


27 changes: 27 additions & 0 deletions plugins/module_utils/doc_fragments/vpc_ip_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Documentation fragments for the vpc_ip_list module"""

specdoc_examples = ["""
- name: List all IPs of a specific VPC.
linode.cloud.vpc_ip_list:
vpc_id: 12345""",
]

result_vpc_ip_view_samples = [
"""[
{
"address": "10.0.0.2",
"address_range": null,
"vpc_id": 56242,
"subnet_id": 55829,
"region": "us-mia",
"linode_id": 57328104,
"config_id": 60480976,
"interface_id": 1373818,
"active": false,
"nat_1_1": null,
"gateway": "10.0.0.1",
"prefix": 24,
"subnet_mask": "255.255.255.0",
}
]"""
]
27 changes: 27 additions & 0 deletions plugins/module_utils/doc_fragments/vpcs_ip_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Documentation fragments for the vpcs_ip_list module"""

specdoc_examples = [
"""
- name: List all IPs of all VPCs in the account.
linode.cloud.vpcs_ip_list: {}""",
]

result_vpc_samples = ["""
[
{
"address": "10.0.0.2",
"address_range": null,
"vpc_id": 56242,
"subnet_id": 55829,
"region": "us-mia",
"linode_id": 57328104,
"config_id": 60480976,
"interface_id": 1373818,
"active": false,
"nat_1_1": null,
"gateway": "10.0.0.1",
"prefix": 24,
"subnet_mask": "255.255.255.0",
}
]"""
]
2 changes: 1 addition & 1 deletion plugins/module_utils/linode_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def _get_resource_by_id(
)
return self.fail(
msg=f"failed to get {resource_name} "
"with id {resource_id}: {exception}"
f"with id {resource_id}: {exception}"
)

@property
Expand Down
63 changes: 52 additions & 11 deletions plugins/modules/ip_rdns.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

from __future__ import absolute_import, division, print_function

from typing import Any, Optional
from ipaddress import IPv6Address, ip_address
from typing import Any, Optional, Union

import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.ip_info as ip_docs
import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.ip_rdns as ip_rdns_docs
Expand Down Expand Up @@ -40,7 +41,7 @@
"rdns": SpecField(
type=FieldType.string,
editable=True,
description=["The desired rDNS value."],
description=["The desired RDNS value."],
),
}

Expand Down Expand Up @@ -82,28 +83,68 @@ def __init__(self) -> None:
required_if=[["state", "present", ["rdns"]]],
)

def update_rdns(self, rdns: str) -> None:
@staticmethod
def _build_default_rdns(
address: str,
) -> Optional[str]:
"""
Builds the default RDNS address for the given IPv4/IPv6 address.
This is only used for local diffing purposes.
"""
parsed_address = ip_address(address)

# IPv6 addresses have no default RDNS
if isinstance(parsed_address, IPv6Address):
return None

return f"{address.replace('.', '-')}.ip.linodeusercontent.com"

def _should_update_rdns(
self, old_rdns: str, new_rdns: Union[str, ExplicitNullValue]
) -> bool:
"""
Returns whether the old RDNS value and the proposed new RDNS for the
IP address differ.
"""

# If the RDNS address is being reset, compare the old RDNS against
# the Linode API default
if isinstance(new_rdns, ExplicitNullValue):
new_rdns = self._build_default_rdns(
self.module.params.get("address")
)

return new_rdns != old_rdns

def _attempt_update_rdns(self, rdns: Union[str, ExplicitNullValue]) -> None:
"""
Update the reverse DNS of the IP address.
"""
ip_str = self.module.params.get("address")
ip_obj = self._get_resource_by_id(IPAddress, ip_str)
ip_obj.rdns = rdns
ip_obj.save()
ip_obj._api_get()
self.register_action(
f"Updated reverse DNS of the IP address {ip_str} to be {rdns}"
)

old_rdns = ip_obj.rdns

if self._should_update_rdns(old_rdns, rdns):
ip_obj.rdns = rdns

ip_obj.save()
ip_obj._api_get()
self.register_action(
f"Updated reverse DNS of the IP address {ip_str} from {old_rdns} to {ip_obj.rdns}"
)
self.results["ip"] = ip_obj._raw_json

def _handle_present(self) -> None:
rdns = self.module.params.get("rdns")

if not rdns:
self.fail("`rdns` attribute is required to update the IP address")
self.update_rdns(rdns)

self._attempt_update_rdns(rdns)

def _handle_absent(self) -> None:
self.update_rdns(ExplicitNullValue())
self._attempt_update_rdns(ExplicitNullValue())

def exec_module(self, **kwargs: Any) -> Optional[dict]:
"""Entrypoint for reverse DNS module"""
Expand Down
3 changes: 3 additions & 0 deletions plugins/modules/ssh_key_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,15 @@ def exec_module(self, **kwargs: Any) -> Optional[dict]:

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


Expand Down
35 changes: 35 additions & 0 deletions plugins/modules/vpc_ip_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""This module contains all of the functionality for listing IP addresses of a VPC."""

from __future__ import absolute_import, division, print_function

import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.vpc_ip_list as docs
from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import (
ListModule,
ListModuleParam,
)
from ansible_specdoc.objects import FieldType

module = ListModule(
result_display_name="VPC IP Addresses",
result_field_name="vpcs_ips",
endpoint_template="/vpcs/{vpc_id}/ips",
result_docs_url="",
examples=docs.specdoc_examples,
result_samples=docs.result_vpc_ip_view_samples,
params=[
ListModuleParam(
display_name="VPC",
name="vpc_id",
type=FieldType.integer,
)
],
)


SPECDOC_META = module.spec

if __name__ == "__main__":
module.run()
26 changes: 26 additions & 0 deletions plugins/modules/vpcs_ip_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""This module contains all of the functionality for listing IP addresses of all VPCs."""

from __future__ import absolute_import, division, print_function

import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.vpcs_ip_list as docs
from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import (
ListModule,
)

module = ListModule(
result_display_name="all VPC IP Addresses",
result_field_name="vpcs_ips",
endpoint_template="/vpcs/ips",
result_docs_url="",
examples=docs.specdoc_examples,
result_samples=docs.result_vpc_samples,
)


SPECDOC_META = module.spec

if __name__ == "__main__":
module.run()
Loading

0 comments on commit cf84ef9

Please sign in to comment.