diff --git a/Makefile b/Makefile
index 9b80db77..8515b6aa 100644
--- a/Makefile
+++ b/Makefile
@@ -121,6 +121,11 @@ else
echo "LINODE_API_TOKEN must be set"; \
exit 1;
endif
+ # Add producer/consumer tokens, may be empty
+ @echo "producer_api_token: $${LINODE_PRODUCER_API_TOKEN:-}" >> $(INTEGRATION_CONFIG)
+ @echo "consumer_api_token: $${LINODE_CONSUMER_API_TOKEN:-}" >> $(INTEGRATION_CONFIG)
+
+ # Common settings
@echo "ua_prefix: E2E" >> $(INTEGRATION_CONFIG)
@echo "api_url: $$(url=$${LINODE_API_URL:-$${TEST_API_URL:-https://api.linode.com}}; echo $${url%/}/)" >> $(INTEGRATION_CONFIG)
@echo "api_version: $${LINODE_API_VERSION:-$${TEST_API_VERSION:-v4beta}}" >> $(INTEGRATION_CONFIG)
diff --git a/README.md b/README.md
index 321eba22..49f6afc2 100644
--- a/README.md
+++ b/README.md
@@ -33,6 +33,9 @@ Name | Description |
[linode.cloud.firewall_device](./docs/modules/firewall_device.md)|Manage Linode Firewall Devices.|
[linode.cloud.firewall_settings](./docs/modules/firewall_settings.md)|Configure the firewall settings for the account.|
[linode.cloud.image](./docs/modules/image.md)|Manage a Linode Image.|
+[linode.cloud.image_share_group](./docs/modules/image_share_group.md)|Manage an Image Share Group.|
+[linode.cloud.image_share_group_member](./docs/modules/image_share_group_member.md)|Manage an Image Share Group Member.|
+[linode.cloud.image_share_group_token](./docs/modules/image_share_group_token.md)|Manage an Image Share Group Token.|
[linode.cloud.instance](./docs/modules/instance.md)|Manage Linode Instances, Configs, and Disks.|
[linode.cloud.instance_interface_settings](./docs/modules/instance_interface_settings.md)|Create, read, and update the interface settings for a Linode instance.|
[linode.cloud.ip](./docs/modules/ip.md)|Allocates a new IPv4 Address on your Account. The Linode must be configured to support additional addresses - please Open a support ticket requesting additional addresses before attempting allocation.|
@@ -66,6 +69,7 @@ Name | Description |
[linode.cloud.account_availability_info](./docs/modules/account_availability_info.md)|Get info about a Linode Account Availability.|
[linode.cloud.account_info](./docs/modules/account_info.md)|Get info about a Linode Account.|
[linode.cloud.child_account_info](./docs/modules/child_account_info.md)|Get info about a Linode Child Account.|
+[linode.cloud.consumer_image_share_group_info](./docs/modules/consumer_image_share_group_info.md)|Get info about a Linode Image Share Group.|
[linode.cloud.database_config_info](./docs/modules/database_config_info.md)|Get info about a Linode Configuration.|
[linode.cloud.database_mysql_info](./docs/modules/database_mysql_info.md)|Get info about a Linode MySQL Managed Database.|
[linode.cloud.database_postgresql_info](./docs/modules/database_postgresql_info.md)|Get info about a Linode PostgreSQL Managed Database.|
@@ -75,6 +79,9 @@ Name | Description |
[linode.cloud.firewall_settings_info](./docs/modules/firewall_settings_info.md)|Get info about a Linode Firewall Settings.|
[linode.cloud.firewall_template_info](./docs/modules/firewall_template_info.md)|Get info about a Linode Firewall Template.|
[linode.cloud.image_info](./docs/modules/image_info.md)|Get info about a Linode Image.|
+[linode.cloud.image_share_group_info](./docs/modules/image_share_group_info.md)|Get info about a Linode Image Share Group.|
+[linode.cloud.image_share_group_member_info](./docs/modules/image_share_group_member_info.md)|Get info about a Linode Image Share Group Member.|
+[linode.cloud.image_share_group_token_info](./docs/modules/image_share_group_token_info.md)|Get info about a Linode Image Share Group Token.|
[linode.cloud.instance_info](./docs/modules/instance_info.md)|Get info about a Linode Instance.|
[linode.cloud.instance_interface_settings_info](./docs/modules/instance_interface_settings_info.md)|Get the interface settings for a Linode instance.|
[linode.cloud.ip_info](./docs/modules/ip_info.md)|Get info about a Linode IP.|
@@ -107,6 +114,7 @@ Name | Description |
--- | ------------ |
[linode.cloud.account_availability_list](./docs/modules/account_availability_list.md)|List and filter on Account Availabilities.|
[linode.cloud.child_account_list](./docs/modules/child_account_list.md)|List and filter on Child Account.|
+[linode.cloud.consumer_image_share_group_image_list](./docs/modules/consumer_image_share_group_image_list.md)|List and filter on Image Share Group Images.|
[linode.cloud.database_engine_list](./docs/modules/database_engine_list.md)|List and filter on Managed Database engine types.|
[linode.cloud.database_list](./docs/modules/database_list.md)|List and filter on Linode Managed Databases.|
[linode.cloud.domain_list](./docs/modules/domain_list.md)|List and filter on Domains.|
@@ -114,6 +122,10 @@ Name | Description |
[linode.cloud.firewall_list](./docs/modules/firewall_list.md)|List and filter on Firewalls.|
[linode.cloud.firewall_template_list](./docs/modules/firewall_template_list.md)|List and filter on Firewall Templates.|
[linode.cloud.image_list](./docs/modules/image_list.md)|List and filter on Images.|
+[linode.cloud.image_share_group_image_list](./docs/modules/image_share_group_image_list.md)|List and filter on Image Share Group Images.|
+[linode.cloud.image_share_group_list](./docs/modules/image_share_group_list.md)|List and filter on Image Share Groups.|
+[linode.cloud.image_share_group_member_list](./docs/modules/image_share_group_member_list.md)|List and filter on Image Share Group Members.|
+[linode.cloud.image_share_group_token_list](./docs/modules/image_share_group_token_list.md)|List and filter on Image Share Group Tokens.|
[linode.cloud.instance_interface_firewall_list](./docs/modules/instance_interface_firewall_list.md)|List and filter on Linode Interface Firewalls.|
[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`.**|
diff --git a/docs/modules/consumer_image_share_group_image_list.md b/docs/modules/consumer_image_share_group_image_list.md
new file mode 100644
index 00000000..565763b0
--- /dev/null
+++ b/docs/modules/consumer_image_share_group_image_list.md
@@ -0,0 +1,93 @@
+# consumer_image_share_group_image_list
+
+List and filter on Image Share Group Images.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: List all of the Image Share Group Images for the specified Token UUID
+ linode.cloud.consumer_image_share_group_image_list:
+ token_uuid: "9e64b99e-92f7-4c7b-a616-8f622fffb94c"
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `token_uuid` |
`str` | **Required** | The parent Token for the Image Share Group Images. |
+| `order` | `str` | Optional | The order to list Image Share Group Images in. **(Choices: `desc`, `asc`; Default: `asc`)** |
+| `order_by` | `str` | Optional | The attribute to order Image Share Group Images by. |
+| [`filters` (sub-options)](#filters) | `list` | Optional | A list of filters to apply to the resulting Image Share Group Images. |
+| `count` | `int` | Optional | The number of Image Share Group Images 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-sharegroup-images-by-token). |
+| `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
+
+- `image_share_group_images` - The returned Image Share Group Images.
+
+ - Sample Response:
+ ```json
+ [
+ {
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
+ "created": "2025-08-04T10:07:59",
+ "created_by": null,
+ "deprecated": true,
+ "description": "Official Debian Linux image for server deployment",
+ "eol": "2025-12-31T18:13:44.756Z",
+ "expiry": "2025-12-31T18:13:44.756Z",
+ "id": "shared/1",
+ "image_sharing": {
+ "shared_by": {
+ "sharegroup_id": 123,
+ "sharegroup_label": "DevOps Base Images",
+ "sharegroup_uuid": "8d64b99e-92f7-4c7b-a616-8f622fffb94c",
+ "source_image_id": "private/15"
+ },
+ "shared_with": null
+ },
+ "is_public": true,
+ "is_shared": "none",
+ "label": "Linux Debian",
+ "regions": [
+ {
+ "region": "us-iad",
+ "status": "available"
+ }
+ ],
+ "size": 256,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 256,
+ "type": "shared",
+ "updated": null,
+ "vendor": "string"
+ }
+ ]
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup-images-by-token) for a list of returned fields
+
+
diff --git a/docs/modules/consumer_image_share_group_info.md b/docs/modules/consumer_image_share_group_info.md
new file mode 100644
index 00000000..404e6531
--- /dev/null
+++ b/docs/modules/consumer_image_share_group_info.md
@@ -0,0 +1,48 @@
+# consumer_image_share_group_info
+
+Get info about a Linode Image Share Group.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: Get info about an Image Share Group by a Consumer's Token UUID
+ linode.cloud.consumer_image_share_group_info:
+ token_uuid: "1433863e-16a4-47b5-b829-ac0f35c13278"
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `token_uuid` | `str` | **Required** | The ID of the Token for this resource. |
+
+## Return Values
+
+- `image_share_group` - The returned Image Share Group.
+
+ - Sample Response:
+ ```json
+ {
+ "created": "2025-04-14T22:44:02",
+ "description": "Group of base operating system images and engineers used for CI/CD pipelines and infrastructure automation",
+ "id": 1,
+ "is_suspended": false,
+ "label": "DevOps Base Images",
+ "updated": "2025-04-14T22:44:03",
+ "uuid": "1533863e-16a4-47b5-b829-ac0f35c13278"
+ }
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup-by-token) for a list of returned fields
+
+
diff --git a/docs/modules/image.md b/docs/modules/image.md
index d16b3835..ea9aa386 100644
--- a/docs/modules/image.md
+++ b/docs/modules/image.md
@@ -83,33 +83,43 @@ Manage a Linode Image.
- Sample Response:
```json
{
- "capabilities": [],
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
"created": "2021-08-14T22:44:02",
- "created_by": "my-account",
+ "created_by": "linode",
"deprecated": false,
- "description": "Example Image description.",
+ "description": "Example image description.",
"eol": "2026-07-01T04:00:00",
"expiry": null,
- "id": "private/123",
- "is_public": true,
- "label": "my-image",
- "size": 2500,
- "status": null,
- "type": "manual",
- "updated": "2021-08-14T22:44:02",
- "vendor": "Debian",
- "tags": ["test"],
- "total_size": 5000,
+ "id": "private/15",
+ "image_sharing": {
+ "shared_by": null,
+ "shared_with": {
+ "sharegroup_count": 0,
+ "sharegroup_list_url": "/images/private/15/sharegroups"
+ }
+ },
+ "is_public": false,
+ "is_shared": false,
+ "label": "Debian 11",
"regions": [
{
- "region": "us-east",
- "status": "available"
- },
- {
- "region": "us-central",
- "status": "pending"
+ "region": "us-iad",
+ "status": "available"
}
- ]
+ ],
+ "size": 2500,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 1234567,
+ "type": "manual",
+ "updated": "2021-08-14T22:44:02",
+ "vendor": "Debian"
}
```
- See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-image) for a list of returned fields
diff --git a/docs/modules/image_info.md b/docs/modules/image_info.md
index abf339b4..0fdf84d9 100644
--- a/docs/modules/image_info.md
+++ b/docs/modules/image_info.md
@@ -41,33 +41,43 @@ Get info about a Linode Image.
- Sample Response:
```json
{
- "capabilities": [],
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
"created": "2021-08-14T22:44:02",
- "created_by": "my-account",
+ "created_by": "linode",
"deprecated": false,
- "description": "Example Image description.",
+ "description": "Example image description.",
"eol": "2026-07-01T04:00:00",
"expiry": null,
- "id": "private/123",
- "is_public": true,
- "label": "my-image",
- "size": 2500,
- "status": null,
- "type": "manual",
- "updated": "2021-08-14T22:44:02",
- "vendor": "Debian",
- "tags": ["test"],
- "total_size": 5000,
+ "id": "private/15",
+ "image_sharing": {
+ "shared_by": null,
+ "shared_with": {
+ "sharegroup_count": 0,
+ "sharegroup_list_url": "/images/private/15/sharegroups"
+ }
+ },
+ "is_public": false,
+ "is_shared": false,
+ "label": "Debian 11",
"regions": [
{
- "region": "us-east",
- "status": "available"
- },
- {
- "region": "us-central",
- "status": "pending"
+ "region": "us-iad",
+ "status": "available"
}
- ]
+ ],
+ "size": 2500,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 1234567,
+ "type": "manual",
+ "updated": "2021-08-14T22:44:02",
+ "vendor": "Debian"
}
```
- See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-image) for a list of returned fields
diff --git a/docs/modules/image_list.md b/docs/modules/image_list.md
index 03345cf8..9f67eac6 100644
--- a/docs/modules/image_list.md
+++ b/docs/modules/image_list.md
@@ -59,33 +59,45 @@ List and filter on Images.
- Sample Response:
```json
[
- {
- "created":"2021-08-14T22:44:02",
- "created_by":"my-account",
- "deprecated":false,
- "description":"Example Image description.",
- "eol":"2026-07-01T04:00:00",
- "expiry":null,
- "id":"private/123",
- "is_public":false,
- "label":"test",
- "size":2500,
- "status":null,
- "type":"manual",
- "updated":"2021-08-14T22:44:02",
- "vendor":"Debian",
- "tags": ["test"],
- "total_size": 5000,
+ {
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
+ "created": "2021-08-14T22:44:02",
+ "created_by": "linode",
+ "deprecated": false,
+ "description": "Example image description.",
+ "eol": "2026-07-01T04:00:00",
+ "expiry": null,
+ "id": "private/15",
+ "image_sharing": {
+ "shared_by": null,
+ "shared_with": {
+ "sharegroup_count": 0,
+ "sharegroup_list_url": "/images/private/15/sharegroups"
+ }
+ },
+ "is_public": false,
+ "is_shared": false,
+ "label": "Debian 11",
"regions": [
{
- "region": "us-east",
- "status": "available"
- },
- {
- "region": "us-central",
- "status": "pending"
- }]
- }
+ "region": "us-iad",
+ "status": "available"
+ }
+ ],
+ "size": 2500,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 1234567,
+ "type": "manual",
+ "updated": "2021-08-14T22:44:02",
+ "vendor": "Debian"
+ }
]
```
- See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-images) for a list of returned fields
diff --git a/docs/modules/image_share_group.md b/docs/modules/image_share_group.md
new file mode 100644
index 00000000..3ffc598d
--- /dev/null
+++ b/docs/modules/image_share_group.md
@@ -0,0 +1,84 @@
+# image_share_group
+
+Manage an Image Share Group.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: Create a basic image share group
+ linode.cloud.image_share_group:
+ label: "my-sharegroup"
+ description: "My image share group."
+ state: present
+```
+
+```yaml
+- name: Create a basic image share group with an image
+ linode.cloud.image_share_group:
+ label: "my-sharegroup"
+ description: "My image share group."
+ images:
+ - id: "private/123"
+ label: "My shared image"
+ description: "An image shared in the group."
+ state: present
+
+```
+
+```yaml
+- name: Delete an image share group
+ linode.cloud.image_share_group:
+ label: "my-sharegroup"
+ state: absent
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `label` | `str` | **Required** | This Image Share Group's unique label. |
+| `state` | `str` | **Required** | The desired state of the target. **(Choices: `present`, `absent`)** |
+| `description` | `str` | Optional | A description of this Image Share Group. |
+| [`images` (sub-options)](#images) | `list` | Optional | A list of images to include in this Image Share Group. |
+
+### images
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `id` | `str` | **Required** | The id of the Private Image to include in an Image Share Group. |
+| `label` | `str` | Optional | A label to assign to the Image within the context of an Image Share Group. |
+| `description` | `str` | Optional | A description to assign to the Image within the context of an Image Share Group. |
+
+## Return Values
+
+- `image_share_group` - The Image Share Group in JSON serialized form.
+
+ - Sample Response:
+ ```json
+ {
+ "created": "2025-04-14T22:44:02",
+ "description": "My image share group.",
+ "expiry": null,
+ "id": 1,
+ "images_count": 0,
+ "is_suspended": false,
+ "label": "my-sharegroup",
+ "members_count": 0,
+ "updated": null,
+ "uuid": "1533863e-16a4-47b5-b829-ac0f35c13278"
+ }
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup) for a list of returned fields
+
+
diff --git a/docs/modules/image_share_group_image_list.md b/docs/modules/image_share_group_image_list.md
new file mode 100644
index 00000000..7cd80de2
--- /dev/null
+++ b/docs/modules/image_share_group_image_list.md
@@ -0,0 +1,93 @@
+# image_share_group_image_list
+
+List and filter on Image Share Group Images.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: List all of the Image Share Group Images for the specified Share Group
+ linode.cloud.image_share_group_image_list:
+ sharegroup_id: 123
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `sharegroup_id` | `int` | **Required** | The parent Image Share Group for the Image Share Group Images. |
+| `order` | `str` | Optional | The order to list Image Share Group Images in. **(Choices: `desc`, `asc`; Default: `asc`)** |
+| `order_by` | `str` | Optional | The attribute to order Image Share Group Images by. |
+| [`filters` (sub-options)](#filters) | `list` | Optional | A list of filters to apply to the resulting Image Share Group Images. |
+| `count` | `int` | Optional | The number of Image Share Group Images 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-sharegroup-images). |
+| `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
+
+- `image_share_group_images` - The returned Image Share Group Images.
+
+ - Sample Response:
+ ```json
+ [
+ {
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
+ "created": "2025-08-04T10:07:59",
+ "created_by": null,
+ "deprecated": true,
+ "description": "Official Debian Linux image for server deployment",
+ "eol": "2025-12-31T18:13:44.756Z",
+ "expiry": "2025-12-31T18:13:44.756Z",
+ "id": "shared/1",
+ "image_sharing": {
+ "shared_by": {
+ "sharegroup_id": 123,
+ "sharegroup_label": "DevOps Base Images",
+ "sharegroup_uuid": "8d64b99e-92f7-4c7b-a616-8f622fffb94c",
+ "source_image_id": "private/15"
+ },
+ "shared_with": null
+ },
+ "is_public": true,
+ "is_shared": "none",
+ "label": "Linux Debian",
+ "regions": [
+ {
+ "region": "us-iad",
+ "status": "available"
+ }
+ ],
+ "size": 256,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 256,
+ "type": "shared",
+ "updated": null,
+ "vendor": "string"
+ }
+ ]
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup-images) for a list of returned fields
+
+
diff --git a/docs/modules/image_share_group_info.md b/docs/modules/image_share_group_info.md
new file mode 100644
index 00000000..7ee3b691
--- /dev/null
+++ b/docs/modules/image_share_group_info.md
@@ -0,0 +1,52 @@
+# image_share_group_info
+
+Get info about a Linode Image Share Group.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: Get info about an Image Share Group by label
+ linode.cloud.image_share_group_info:
+ label: example-image-share-group
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `id` | `int` | Optional | The ID of the Image Share Group to resolve. **(Conflicts With: `label`)** |
+| `label` | `str` | Optional | The label of the Image Share Group to resolve. **(Conflicts With: `id`)** |
+
+## Return Values
+
+- `image_share_group` - The returned Image Share Group.
+
+ - Sample Response:
+ ```json
+ {
+ "created": "2025-04-14T22:44:02",
+ "description": "Example.",
+ "expiry": "2025-04-14T22:44:02",
+ "id": 1,
+ "images_count": 0,
+ "is_suspended": false,
+ "label": "example-image-share-group",
+ "members_count": 0,
+ "updated": "2025-04-14T22:44:02",
+ "uuid": "1533863e-16a4-47b5-b829-ac0f35c13278"
+ }
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup) for a list of returned fields
+
+
diff --git a/docs/modules/image_share_group_list.md b/docs/modules/image_share_group_list.md
new file mode 100644
index 00000000..62f9dbd2
--- /dev/null
+++ b/docs/modules/image_share_group_list.md
@@ -0,0 +1,69 @@
+# image_share_group_list
+
+List and filter on Image Share Groups.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: List all of the Image Share Groups for the current Linode Account
+ linode.cloud.image_share_group_list: {}
+```
+
+```yaml
+- name: List all of the Image Share Groups that contain a specific private image
+ linode.cloud.image_share_group_list:
+ image_id: "private/12345"
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `order` | `str` | Optional | The order to list Image Share Groups in. **(Choices: `desc`, `asc`; Default: `asc`)** |
+| `order_by` | `str` | Optional | The attribute to order Image Share Groups by. |
+| [`filters` (sub-options)](#filters) | `list` | Optional | A list of filters to apply to the resulting Image Share Groups. |
+| `count` | `int` | Optional | The number of Image Share Groups to return. If undefined, all results will be returned. |
+| `image_id` | `str` | Optional | Specifies the private image ID to list share groups for. If provided, only share groups containing the specified image 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-sharegroups). |
+| `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
+
+- `image_share_groups` - The returned Image Share Groups.
+
+ - Sample Response:
+ ```json
+ [
+ {
+ "created": "2025-04-14T22:44:02",
+ "description": "Group of base operating system images and engineers used for CI/CD pipelines and infrastructure automation",
+ "expiry": null,
+ "id": 1,
+ "images_count": 0,
+ "is_suspended": false,
+ "label": "DevOps Base Images",
+ "members_count": 0,
+ "updated": null,
+ "uuid": "1533863e-16a4-47b5-b829-ac0f35c13278"
+ }
+ ]
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroups) for a list of returned fields
+
+
diff --git a/docs/modules/image_share_group_member.md b/docs/modules/image_share_group_member.md
new file mode 100644
index 00000000..0ae7287c
--- /dev/null
+++ b/docs/modules/image_share_group_member.md
@@ -0,0 +1,60 @@
+# image_share_group_member
+
+Manage an Image Share Group Member.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: Create an image share group member
+ linode.cloud.image_share_group_member:
+ label: "my-sharegroup-member"
+ token: "abcdefghijklmnopqrstuvwxyz1234567890"
+ state: present
+```
+
+```yaml
+- name: Delete an image share group member
+ linode.cloud.image_share_group_member:
+ label: "my-sharegroup-member"
+ state: absent
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `label` | `str` | **Required** | This Image Share Group Member's unique label. |
+| `sharegroup_id` | `int` | **Required** | The ID of the Image Share Group this member belongs to. |
+| `state` | `str` | **Required** | The desired state of the target. **(Choices: `present`, `absent`)** |
+| `token` | `str` | Optional | A single-use Image Share Group Token provided by the Consumer. This value is required when creating a member and is never returned. |
+
+## Return Values
+
+- `image_share_group_member` - The Image Share Group Member in JSON serialized form.
+
+ - Sample Response:
+ ```json
+ {
+ "token_uuid": "24wef-243qg-45wgg-q343q",
+ "status": "active",
+ "label": "my-sharegroup-member",
+ "created": "2016-03-16T17:30:49",
+ "updated": "2016-03-18T17:30:49",
+ "expiry": "2016-03-18T17:30:49"
+ }
+
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup-member-token) for a list of returned fields
+
+
diff --git a/docs/modules/image_share_group_member_info.md b/docs/modules/image_share_group_member_info.md
new file mode 100644
index 00000000..832a14b4
--- /dev/null
+++ b/docs/modules/image_share_group_member_info.md
@@ -0,0 +1,50 @@
+# image_share_group_member_info
+
+Get info about a Linode Image Share Group Member.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: Get info about an Image Share Group Member by label
+ linode.cloud.image_share_group_member_info:
+ sharegroup_id: 123456
+ label: example-image-share-group-member
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `sharegroup_id` | `int` | **Required** | The ID of the Image Share Group for this resource. |
+| `token_uuid` | `str` | Optional | The Token UUID of the Image Share Group Member to resolve. **(Conflicts With: `label`)** |
+| `label` | `str` | Optional | The label of the Image Share Group Member to resolve. **(Conflicts With: `token_uuid`)** |
+
+## Return Values
+
+- `image_share_group_member` - The returned Image Share Group Member.
+
+ - Sample Response:
+ ```json
+ {
+ "created": "2025-08-04T10:07:59",
+ "expiry": "2025-08-04T10:08:01",
+ "label": "Engineering - Backend",
+ "status": "active",
+ "token_uuid": "4591075e-4ba8-43c9-a521-928c3d4a135d",
+ "updated": "2025-08-04T10:08:00"
+ }
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup-member-token) for a list of returned fields
+
+
diff --git a/docs/modules/image_share_group_member_list.md b/docs/modules/image_share_group_member_list.md
new file mode 100644
index 00000000..b8c9b43a
--- /dev/null
+++ b/docs/modules/image_share_group_member_list.md
@@ -0,0 +1,60 @@
+# image_share_group_member_list
+
+List and filter on Image Share Group Members.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: List all of the Image Share Group Members for the specified Share Group
+ linode.cloud.image_share_group_member_list:
+ sharegroup_id: 123
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `sharegroup_id` | `int` | **Required** | The parent Image Share Group for the Image Share Group Members. |
+| `order` | `str` | Optional | The order to list Image Share Group Members in. **(Choices: `desc`, `asc`; Default: `asc`)** |
+| `order_by` | `str` | Optional | The attribute to order Image Share Group Members by. |
+| [`filters` (sub-options)](#filters) | `list` | Optional | A list of filters to apply to the resulting Image Share Group Members. |
+| `count` | `int` | Optional | The number of Image Share Group Members 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-sharegroup-members). |
+| `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
+
+- `image_share_group_members` - The returned Image Share Group Members.
+
+ - Sample Response:
+ ```json
+ [
+ {
+ "created": "2025-08-04T10:07:59",
+ "expiry": "2025-08-04T10:08:01",
+ "label": "member-label",
+ "status": "active",
+ "token_uuid": "4591075e-4ba8-43c9-a521-928c3d4a135d",
+ "updated": "2025-08-04T10:08:00"
+ }
+ ]
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup-members) for a list of returned fields
+
+
diff --git a/docs/modules/image_share_group_token.md b/docs/modules/image_share_group_token.md
new file mode 100644
index 00000000..2c9ca49d
--- /dev/null
+++ b/docs/modules/image_share_group_token.md
@@ -0,0 +1,71 @@
+# image_share_group_token
+
+Manage an Image Share Group Token.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: Create an image share group token
+ linode.cloud.image_share_group_token:
+ label: "my-sharegroup-token"
+ valid_for_sharegroup_uuid: "1533863e-16a4-47b5-b829-ac0f35c13278"
+ state: present
+```
+
+```yaml
+- name: Delete an image share group token
+ linode.cloud.image_share_group_token:
+ label: "my-sharegroup-token"
+ state: absent
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `label` | `str` | **Required** | This Image Share Group Token's unique label. |
+| `state` | `str` | **Required** | The desired state of the target. **(Choices: `present`, `absent`)** |
+| `valid_for_sharegroup_uuid` | `str` | Optional | The UUID of the Image Share Group that this token is valid for. |
+
+## Return Values
+
+- `image_share_group_token` - The Image Share Group Token in JSON serialized form.
+
+ - Sample Response:
+ ```json
+ {
+ "created": "2025-08-04T10:09:09",
+ "expiry": null,
+ "label": "Backend Services - Engineering",
+ "sharegroup_label": "DevOps Base Images",
+ "sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359",
+ "status": "active",
+ "token_uuid": "13428362-5458-4dad-b14b-8d0d4d648f8c",
+ "updated": null,
+ "valid_for_sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359"
+ }
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup-token) for a list of returned fields
+
+
+- `single_use_token` - The single use token string to provide to a Image Share Group Producer to be added to the share group.
+
+ - Sample Response:
+ ```json
+ {
+ "token": "abcdefghijklmnopqrstuvwxyz1234567890"
+ }
+ ```
+
+
diff --git a/docs/modules/image_share_group_token_info.md b/docs/modules/image_share_group_token_info.md
new file mode 100644
index 00000000..482d2a32
--- /dev/null
+++ b/docs/modules/image_share_group_token_info.md
@@ -0,0 +1,51 @@
+# image_share_group_token_info
+
+Get info about a Linode Image Share Group Token.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: Get info about an Image Share Group Token by label
+ linode.cloud.image_share_group_token_info:
+ label: example-image-share-group-token
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `token_uuid` | `str` | Optional | The Token UUID of the Image Share Group Token to resolve. **(Conflicts With: `label`)** |
+| `label` | `str` | Optional | The label of the Image Share Group Token to resolve. **(Conflicts With: `token_uuid`)** |
+
+## Return Values
+
+- `image_share_group_token` - The returned Image Share Group Token.
+
+ - Sample Response:
+ ```json
+ {
+ "created": "2025-08-04T10:09:09",
+ "expiry": "2025-08-04T10:09:11",
+ "label": "example-token",
+ "sharegroup_label": "example-sharegroup",
+ "sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359",
+ "status": "active",
+ "token_uuid": "13428362-5458-4dad-b14b-8d0d4d648f8c",
+ "updated": "2025-08-04T10:09:10",
+ "valid_for_sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359"
+ }
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-sharegroup-token) for a list of returned fields
+
+
diff --git a/docs/modules/image_share_group_token_list.md b/docs/modules/image_share_group_token_list.md
new file mode 100644
index 00000000..b5f1120a
--- /dev/null
+++ b/docs/modules/image_share_group_token_list.md
@@ -0,0 +1,61 @@
+# image_share_group_token_list
+
+List and filter on Image Share Group Tokens.
+
+- [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.
It can be exposed by the environment variable `LINODE_API_TOKEN` instead.
See details in [Usage](https://github.com/linode/ansible_linode?tab=readme-ov-file#usage). |
+
+## Examples
+
+```yaml
+- name: List all of the Image Share Group Tokens for the current Linode Account
+ linode.cloud.image_share_group_token_list: {}
+```
+
+
+## Parameters
+
+| Field | Type | Required | Description |
+|-----------|------|----------|------------------------------------------------------------------------------|
+| `order` | `str` | Optional | The order to list Image Share Group Tokens in. **(Choices: `desc`, `asc`; Default: `asc`)** |
+| `order_by` | `str` | Optional | The attribute to order Image Share Group Tokens by. |
+| [`filters` (sub-options)](#filters) | `list` | Optional | A list of filters to apply to the resulting Image Share Group Tokens. |
+| `count` | `int` | Optional | The number of Image Share Group 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 fields can be found [here](https://techdocs.akamai.com/linode-api/reference/get-user-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
+
+- `image_share_group_tokens` - The returned Image Share Group Tokens.
+
+ - Sample Response:
+ ```json
+ [
+ {
+ "created": "2025-08-04T10:09:09",
+ "expiry": "2025-08-04T10:09:11",
+ "label": "example-token",
+ "sharegroup_label": "example-sharegroup",
+ "sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359",
+ "status": "active",
+ "token_uuid": "13428362-5458-4dad-b14b-8d0d4d648f8c",
+ "updated": "2025-08-04T10:09:10",
+ "valid_for_sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359"
+ }
+ ]
+ ```
+ - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-user-tokens) for a list of returned fields
+
+
diff --git a/plugins/module_utils/doc_fragments/consumer_image_share_group_image_list.py b/plugins/module_utils/doc_fragments/consumer_image_share_group_image_list.py
new file mode 100644
index 00000000..0893664c
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/consumer_image_share_group_image_list.py
@@ -0,0 +1,50 @@
+"""Documentation fragments for the consumer_image_share_group_image_list module"""
+
+specdoc_examples = ['''
+- name: List all of the Image Share Group Images for the specified Token UUID
+ linode.cloud.consumer_image_share_group_image_list:
+ token_uuid: "9e64b99e-92f7-4c7b-a616-8f622fffb94c"''']
+
+result_consumer_image_share_group_images_samples = ['''[
+ {
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
+ "created": "2025-08-04T10:07:59",
+ "created_by": null,
+ "deprecated": true,
+ "description": "Official Debian Linux image for server deployment",
+ "eol": "2025-12-31T18:13:44.756Z",
+ "expiry": "2025-12-31T18:13:44.756Z",
+ "id": "shared/1",
+ "image_sharing": {
+ "shared_by": {
+ "sharegroup_id": 123,
+ "sharegroup_label": "DevOps Base Images",
+ "sharegroup_uuid": "8d64b99e-92f7-4c7b-a616-8f622fffb94c",
+ "source_image_id": "private/15"
+ },
+ "shared_with": null
+ },
+ "is_public": true,
+ "is_shared": "none",
+ "label": "Linux Debian",
+ "regions": [
+ {
+ "region": "us-iad",
+ "status": "available"
+ }
+ ],
+ "size": 256,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 256,
+ "type": "shared",
+ "updated": null,
+ "vendor": "string"
+ }
+]''']
diff --git a/plugins/module_utils/doc_fragments/consumer_image_share_group_info.py b/plugins/module_utils/doc_fragments/consumer_image_share_group_info.py
new file mode 100644
index 00000000..10e2eb64
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/consumer_image_share_group_info.py
@@ -0,0 +1,16 @@
+"""Documentation fragments for the image_share_group_info module"""
+
+specdoc_examples = ['''
+- name: Get info about an Image Share Group by a Consumer's Token UUID
+ linode.cloud.consumer_image_share_group_info:
+ token_uuid: "1433863e-16a4-47b5-b829-ac0f35c13278"''']
+
+result_consumer_image_share_group_samples = ['''{
+ "created": "2025-04-14T22:44:02",
+ "description": "Group of base operating system images and engineers used for CI/CD pipelines and infrastructure automation",
+ "id": 1,
+ "is_suspended": false,
+ "label": "DevOps Base Images",
+ "updated": "2025-04-14T22:44:03",
+ "uuid": "1533863e-16a4-47b5-b829-ac0f35c13278"
+}''']
diff --git a/plugins/module_utils/doc_fragments/image.py b/plugins/module_utils/doc_fragments/image.py
index a6e70cb2..c5aa3e59 100644
--- a/plugins/module_utils/doc_fragments/image.py
+++ b/plugins/module_utils/doc_fragments/image.py
@@ -34,31 +34,41 @@
state: absent''']
result_image_samples = ['''{
- "capabilities": [],
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
"created": "2021-08-14T22:44:02",
- "created_by": "my-account",
+ "created_by": "linode",
"deprecated": false,
- "description": "Example Image description.",
+ "description": "Example image description.",
"eol": "2026-07-01T04:00:00",
"expiry": null,
- "id": "private/123",
- "is_public": true,
- "label": "my-image",
- "size": 2500,
- "status": null,
- "type": "manual",
- "updated": "2021-08-14T22:44:02",
- "vendor": "Debian",
- "tags": ["test"],
- "total_size": 5000,
+ "id": "private/15",
+ "image_sharing": {
+ "shared_by": null,
+ "shared_with": {
+ "sharegroup_count": 0,
+ "sharegroup_list_url": "/images/private/15/sharegroups"
+ }
+ },
+ "is_public": false,
+ "is_shared": false,
+ "label": "Debian 11",
"regions": [
{
- "region": "us-east",
- "status": "available"
- },
- {
- "region": "us-central",
- "status": "pending"
+ "region": "us-iad",
+ "status": "available"
}
- ]
+ ],
+ "size": 2500,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 1234567,
+ "type": "manual",
+ "updated": "2021-08-14T22:44:02",
+ "vendor": "Debian"
}''']
diff --git a/plugins/module_utils/doc_fragments/image_list.py b/plugins/module_utils/doc_fragments/image_list.py
index 589d39c9..37396626 100644
--- a/plugins/module_utils/doc_fragments/image_list.py
+++ b/plugins/module_utils/doc_fragments/image_list.py
@@ -15,31 +15,43 @@
values: Alpine''']
result_images_samples = ['''[
- {
- "created":"2021-08-14T22:44:02",
- "created_by":"my-account",
- "deprecated":false,
- "description":"Example Image description.",
- "eol":"2026-07-01T04:00:00",
- "expiry":null,
- "id":"private/123",
- "is_public":false,
- "label":"test",
- "size":2500,
- "status":null,
- "type":"manual",
- "updated":"2021-08-14T22:44:02",
- "vendor":"Debian",
- "tags": ["test"],
- "total_size": 5000,
+ {
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
+ "created": "2021-08-14T22:44:02",
+ "created_by": "linode",
+ "deprecated": false,
+ "description": "Example image description.",
+ "eol": "2026-07-01T04:00:00",
+ "expiry": null,
+ "id": "private/15",
+ "image_sharing": {
+ "shared_by": null,
+ "shared_with": {
+ "sharegroup_count": 0,
+ "sharegroup_list_url": "/images/private/15/sharegroups"
+ }
+ },
+ "is_public": false,
+ "is_shared": false,
+ "label": "Debian 11",
"regions": [
{
- "region": "us-east",
- "status": "available"
- },
- {
- "region": "us-central",
- "status": "pending"
- }]
- }
+ "region": "us-iad",
+ "status": "available"
+ }
+ ],
+ "size": 2500,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 1234567,
+ "type": "manual",
+ "updated": "2021-08-14T22:44:02",
+ "vendor": "Debian"
+ }
]''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group.py b/plugins/module_utils/doc_fragments/image_share_group.py
new file mode 100644
index 00000000..b3770375
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group.py
@@ -0,0 +1,34 @@
+"""Documentation fragments for the Image Share Group module"""
+specdoc_examples = ['''
+- name: Create a basic image share group
+ linode.cloud.image_share_group:
+ label: "my-sharegroup"
+ description: "My image share group."
+ state: present''', '''
+- name: Create a basic image share group with an image
+ linode.cloud.image_share_group:
+ label: "my-sharegroup"
+ description: "My image share group."
+ images:
+ - id: "private/123"
+ label: "My shared image"
+ description: "An image shared in the group."
+ state: present
+ ''', '''
+- name: Delete an image share group
+ linode.cloud.image_share_group:
+ label: "my-sharegroup"
+ state: absent''']
+
+result_image_share_group_samples = ['''{
+ "created": "2025-04-14T22:44:02",
+ "description": "My image share group.",
+ "expiry": null,
+ "id": 1,
+ "images_count": 0,
+ "is_suspended": false,
+ "label": "my-sharegroup",
+ "members_count": 0,
+ "updated": null,
+ "uuid": "1533863e-16a4-47b5-b829-ac0f35c13278"
+}''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_image_list.py b/plugins/module_utils/doc_fragments/image_share_group_image_list.py
new file mode 100644
index 00000000..7fd437bc
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_image_list.py
@@ -0,0 +1,50 @@
+"""Documentation fragments for the image_share_group_image_list module"""
+
+specdoc_examples = ['''
+- name: List all of the Image Share Group Images for the specified Share Group
+ linode.cloud.image_share_group_image_list:
+ sharegroup_id: 123''']
+
+result_image_share_group_images_samples = ['''[
+ {
+ "capabilities": [
+ "cloud-init",
+ "distributed-sites"
+ ],
+ "created": "2025-08-04T10:07:59",
+ "created_by": null,
+ "deprecated": true,
+ "description": "Official Debian Linux image for server deployment",
+ "eol": "2025-12-31T18:13:44.756Z",
+ "expiry": "2025-12-31T18:13:44.756Z",
+ "id": "shared/1",
+ "image_sharing": {
+ "shared_by": {
+ "sharegroup_id": 123,
+ "sharegroup_label": "DevOps Base Images",
+ "sharegroup_uuid": "8d64b99e-92f7-4c7b-a616-8f622fffb94c",
+ "source_image_id": "private/15"
+ },
+ "shared_with": null
+ },
+ "is_public": true,
+ "is_shared": "none",
+ "label": "Linux Debian",
+ "regions": [
+ {
+ "region": "us-iad",
+ "status": "available"
+ }
+ ],
+ "size": 256,
+ "status": "available",
+ "tags": [
+ "repair-image",
+ "fix-1"
+ ],
+ "total_size": 256,
+ "type": "shared",
+ "updated": null,
+ "vendor": "string"
+ }
+]''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_info.py b/plugins/module_utils/doc_fragments/image_share_group_info.py
new file mode 100644
index 00000000..baa6e402
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_info.py
@@ -0,0 +1,19 @@
+"""Documentation fragments for the image_share_group_info module"""
+
+specdoc_examples = ['''
+- name: Get info about an Image Share Group by label
+ linode.cloud.image_share_group_info:
+ label: example-image-share-group''']
+
+result_image_share_group_samples = ['''{
+ "created": "2025-04-14T22:44:02",
+ "description": "Example.",
+ "expiry": "2025-04-14T22:44:02",
+ "id": 1,
+ "images_count": 0,
+ "is_suspended": false,
+ "label": "example-image-share-group",
+ "members_count": 0,
+ "updated": "2025-04-14T22:44:02",
+ "uuid": "1533863e-16a4-47b5-b829-ac0f35c13278"
+}''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_list.py b/plugins/module_utils/doc_fragments/image_share_group_list.py
new file mode 100644
index 00000000..271ca492
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_list.py
@@ -0,0 +1,23 @@
+"""Documentation fragments for the image_share_group_list module"""
+
+specdoc_examples = ['''
+- name: List all of the Image Share Groups for the current Linode Account
+ linode.cloud.image_share_group_list: {}''', '''
+- name: List all of the Image Share Groups that contain a specific private image
+ linode.cloud.image_share_group_list:
+ image_id: "private/12345"''']
+
+result_image_share_groups_samples = ['''[
+ {
+ "created": "2025-04-14T22:44:02",
+ "description": "Group of base operating system images and engineers used for CI/CD pipelines and infrastructure automation",
+ "expiry": null,
+ "id": 1,
+ "images_count": 0,
+ "is_suspended": false,
+ "label": "DevOps Base Images",
+ "members_count": 0,
+ "updated": null,
+ "uuid": "1533863e-16a4-47b5-b829-ac0f35c13278"
+ }
+]''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_member.py b/plugins/module_utils/doc_fragments/image_share_group_member.py
new file mode 100644
index 00000000..8810793d
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_member.py
@@ -0,0 +1,21 @@
+"""Documentation fragments for the Image Share Group Member module"""
+specdoc_examples = ['''
+- name: Create an image share group member
+ linode.cloud.image_share_group_member:
+ label: "my-sharegroup-member"
+ token: "abcdefghijklmnopqrstuvwxyz1234567890"
+ state: present''', '''
+- name: Delete an image share group member
+ linode.cloud.image_share_group_member:
+ label: "my-sharegroup-member"
+ state: absent''']
+
+result_image_share_group_member_samples = ['''{
+ "token_uuid": "24wef-243qg-45wgg-q343q",
+ "status": "active",
+ "label": "my-sharegroup-member",
+ "created": "2016-03-16T17:30:49",
+ "updated": "2016-03-18T17:30:49",
+ "expiry": "2016-03-18T17:30:49"
+}
+''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_member_info.py b/plugins/module_utils/doc_fragments/image_share_group_member_info.py
new file mode 100644
index 00000000..1e5670ec
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_member_info.py
@@ -0,0 +1,16 @@
+"""Documentation fragments for the image_share_group_member_info module"""
+
+specdoc_examples = ['''
+- name: Get info about an Image Share Group Member by label
+ linode.cloud.image_share_group_member_info:
+ sharegroup_id: 123456
+ label: example-image-share-group-member''']
+
+result_image_share_group_member_samples = ['''{
+ "created": "2025-08-04T10:07:59",
+ "expiry": "2025-08-04T10:08:01",
+ "label": "Engineering - Backend",
+ "status": "active",
+ "token_uuid": "4591075e-4ba8-43c9-a521-928c3d4a135d",
+ "updated": "2025-08-04T10:08:00"
+}''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_member_list.py b/plugins/module_utils/doc_fragments/image_share_group_member_list.py
new file mode 100644
index 00000000..594f49bb
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_member_list.py
@@ -0,0 +1,17 @@
+"""Documentation fragments for the image_share_group_member_list module"""
+
+specdoc_examples = ['''
+- name: List all of the Image Share Group Members for the specified Share Group
+ linode.cloud.image_share_group_member_list:
+ sharegroup_id: 123''']
+
+result_image_share_group_members_samples = ['''[
+ {
+ "created": "2025-08-04T10:07:59",
+ "expiry": "2025-08-04T10:08:01",
+ "label": "member-label",
+ "status": "active",
+ "token_uuid": "4591075e-4ba8-43c9-a521-928c3d4a135d",
+ "updated": "2025-08-04T10:08:00"
+ }
+]''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_token.py b/plugins/module_utils/doc_fragments/image_share_group_token.py
new file mode 100644
index 00000000..ddd0ba9d
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_token.py
@@ -0,0 +1,27 @@
+"""Documentation fragments for the Image Share Group Token module"""
+specdoc_examples = ['''
+- name: Create an image share group token
+ linode.cloud.image_share_group_token:
+ label: "my-sharegroup-token"
+ valid_for_sharegroup_uuid: "1533863e-16a4-47b5-b829-ac0f35c13278"
+ state: present''', '''
+- name: Delete an image share group token
+ linode.cloud.image_share_group_token:
+ label: "my-sharegroup-token"
+ state: absent''']
+
+result_image_share_group_token_samples = ['''{
+ "created": "2025-08-04T10:09:09",
+ "expiry": null,
+ "label": "Backend Services - Engineering",
+ "sharegroup_label": "DevOps Base Images",
+ "sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359",
+ "status": "active",
+ "token_uuid": "13428362-5458-4dad-b14b-8d0d4d648f8c",
+ "updated": null,
+ "valid_for_sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359"
+}''']
+
+result_single_use_token_samples = ['''{
+ "token": "abcdefghijklmnopqrstuvwxyz1234567890"
+}''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_token_info.py b/plugins/module_utils/doc_fragments/image_share_group_token_info.py
new file mode 100644
index 00000000..c9a2d772
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_token_info.py
@@ -0,0 +1,18 @@
+"""Documentation fragments for the image_share_group_token_info module"""
+
+specdoc_examples = ['''
+- name: Get info about an Image Share Group Token by label
+ linode.cloud.image_share_group_token_info:
+ label: example-image-share-group-token''']
+
+result_image_share_group_token_samples = ['''{
+ "created": "2025-08-04T10:09:09",
+ "expiry": "2025-08-04T10:09:11",
+ "label": "example-token",
+ "sharegroup_label": "example-sharegroup",
+ "sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359",
+ "status": "active",
+ "token_uuid": "13428362-5458-4dad-b14b-8d0d4d648f8c",
+ "updated": "2025-08-04T10:09:10",
+ "valid_for_sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359"
+}''']
diff --git a/plugins/module_utils/doc_fragments/image_share_group_token_list.py b/plugins/module_utils/doc_fragments/image_share_group_token_list.py
new file mode 100644
index 00000000..495b44d1
--- /dev/null
+++ b/plugins/module_utils/doc_fragments/image_share_group_token_list.py
@@ -0,0 +1,19 @@
+"""Documentation fragments for the image_share_group_token_list module"""
+
+specdoc_examples = ['''
+- name: List all of the Image Share Group Tokens for the current Linode Account
+ linode.cloud.image_share_group_token_list: {}''']
+
+result_image_share_group_tokens_samples = ['''[
+ {
+ "created": "2025-08-04T10:09:09",
+ "expiry": "2025-08-04T10:09:11",
+ "label": "example-token",
+ "sharegroup_label": "example-sharegroup",
+ "sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359",
+ "status": "active",
+ "token_uuid": "13428362-5458-4dad-b14b-8d0d4d648f8c",
+ "updated": "2025-08-04T10:09:10",
+ "valid_for_sharegroup_uuid": "e1d0e58b-f89f-4237-84ab-b82077342359"
+ }
+]''']
diff --git a/plugins/modules/consumer_image_share_group_image_list.py b/plugins/modules/consumer_image_share_group_image_list.py
new file mode 100644
index 00000000..38ecee46
--- /dev/null
+++ b/plugins/modules/consumer_image_share_group_image_list.py
@@ -0,0 +1,47 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module allows Consumers to list the Images in an Image Share Group a specific
+Image Share Group Token gives access to."""
+
+from __future__ import absolute_import, division, print_function
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ consumer_image_share_group_image_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="Image Share Group Images",
+ result_field_name="image_share_group_images",
+ endpoint_template="/images/sharegroups/tokens/{token_uuid}/sharegroup/images",
+ result_docs_url=(
+ "https://techdocs.akamai.com/linode-api/reference/"
+ "get-sharegroup-images-by-token"
+ ),
+ result_samples=docs.result_consumer_image_share_group_images_samples,
+ examples=docs.specdoc_examples,
+ params=[
+ ListModuleParam(
+ display_name="Token",
+ name="token_uuid",
+ type=FieldType.string,
+ ),
+ ],
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/plugins/modules/consumer_image_share_group_info.py b/plugins/modules/consumer_image_share_group_info.py
new file mode 100644
index 00000000..962d5602
--- /dev/null
+++ b/plugins/modules/consumer_image_share_group_info.py
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module contains the functionality for the Consumer Image Share Group info module.
+This module allows a consumer to retrieve information about the Image Share Group a specific
+Image Share Group Token gives access to."""
+
+from __future__ import absolute_import, division, print_function
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ consumer_image_share_group_info as docs,
+)
+from ansible_collections.linode.cloud.plugins.module_utils.linode_common_info import (
+ InfoModule,
+ InfoModuleParam,
+ InfoModuleResult,
+)
+from ansible_specdoc.objects import FieldType
+from linode_api4 import ImageShareGroupToken
+
+module = InfoModule(
+ primary_result=InfoModuleResult(
+ field_name="image_share_group",
+ field_type=FieldType.dict,
+ display_name="Image Share Group",
+ docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup-by-token",
+ samples=docs.result_consumer_image_share_group_samples,
+ get=lambda client, params, _current=None: (
+ client.load(ImageShareGroupToken, params["token_uuid"])
+ .get_sharegroup()
+ .__dict__
+ ),
+ ),
+ params=[
+ InfoModuleParam(
+ display_name="Token",
+ name="token_uuid",
+ type=FieldType.string,
+ )
+ ],
+ examples=docs.specdoc_examples,
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/plugins/modules/image_share_group.py b/plugins/modules/image_share_group.py
new file mode 100644
index 00000000..80d51661
--- /dev/null
+++ b/plugins/modules/image_share_group.py
@@ -0,0 +1,372 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module contains all the functionality for Image Share Groups for a Producer."""
+
+from __future__ import absolute_import, division, print_function
+
+import copy
+from typing import Any, Optional
+
+import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.image_share_group 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 (
+ filter_null_values_recursive,
+ handle_updates,
+)
+from ansible_specdoc.objects import (
+ FieldType,
+ SpecDocMeta,
+ SpecField,
+ SpecReturnValue,
+)
+from linode_api4 import (
+ ImageShareGroup,
+ ImageShareGroupImagesToAdd,
+ ImageShareGroupImageToAdd,
+ ImageShareGroupImageToUpdate,
+)
+
+image_share_group_images_spec = {
+ "id": SpecField(
+ type=FieldType.string,
+ required=True,
+ description=[
+ "The id of the Private Image to include in an Image Share Group."
+ ],
+ ),
+ "label": SpecField(
+ type=FieldType.string,
+ description=[
+ "A label to assign to the Image within the context of an Image Share Group."
+ ],
+ ),
+ "description": SpecField(
+ type=FieldType.string,
+ description=[
+ "A description to assign to the Image within the context of an Image Share Group."
+ ],
+ ),
+}
+
+SPEC = {
+ "label": SpecField(
+ type=FieldType.string,
+ description=["This Image Share Group's unique label."],
+ required=True,
+ ),
+ "description": SpecField(
+ type=FieldType.string,
+ description=["A description of this Image Share Group."],
+ ),
+ "images": SpecField(
+ type=FieldType.list,
+ element_type=FieldType.dict,
+ suboptions=image_share_group_images_spec,
+ description=["A list of images to include in this Image Share Group."],
+ ),
+ "state": SpecField(
+ type=FieldType.string,
+ description=["The desired state of the target."],
+ choices=["present", "absent"],
+ required=True,
+ ),
+}
+
+SPECDOC_META = SpecDocMeta(
+ description=["Manage an Image Share Group."],
+ requirements=global_requirements,
+ author=global_authors,
+ options=SPEC,
+ examples=docs.specdoc_examples,
+ return_values={
+ "image_share_group": SpecReturnValue(
+ description="The Image Share Group in JSON serialized form.",
+ docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup",
+ type=FieldType.dict,
+ sample=docs.result_image_share_group_samples,
+ )
+ },
+)
+
+MUTABLE_FIELDS = {"description"}
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+
+class Module(LinodeModuleBase):
+ """Module for creating and destroying Image Share Groups"""
+
+ def __init__(self) -> None:
+ self.module_arg_spec = SPECDOC_META.ansible_spec
+ self.results = {
+ "changed": False,
+ "actions": [],
+ "image_share_group": None,
+ }
+
+ super().__init__(module_arg_spec=self.module_arg_spec)
+
+ def _get_image_share_group_by_label(
+ self, label: str
+ ) -> Optional[ImageShareGroup]:
+ try:
+ return self.client.sharegroups(ImageShareGroup.label == label)[0]
+ except IndexError:
+ return None
+ except Exception as exception:
+ return self.fail(
+ msg="failed to get image share group {0}: {1}".format(
+ label, exception
+ )
+ )
+
+ def _create(self) -> Optional[ImageShareGroup]:
+ params = filter_null_values_recursive(
+ {
+ "label": self.module.params.get("label"),
+ "description": self.module.params.get("description"),
+ "images": self.module.params.get("images"),
+ }
+ )
+
+ try:
+ return self.client.sharegroups.create_sharegroup(**params)
+ except Exception as exception:
+ return self.fail(
+ msg="failed to create Image Share Group: {0}".format(exception)
+ )
+
+ def _update(
+ self, image_share_group: ImageShareGroup
+ ) -> Optional[ImageShareGroup]:
+ image_share_group._api_get()
+
+ new_params = filter_null_values_recursive(
+ copy.deepcopy(self.module.params)
+ )
+ new_params = {
+ k: v for k, v in new_params.items() if k in MUTABLE_FIELDS
+ }
+
+ images_to_update = self.module.params.get("images")
+
+ handle_updates(
+ image_share_group, new_params, MUTABLE_FIELDS, self.register_action
+ )
+
+ # Only touch images if explicitly provided
+ if images_to_update is not None:
+ self._update_images(image_share_group, images_to_update)
+
+ return image_share_group
+
+ # pylint: disable=too-many-statements
+ def _update_images(
+ self, image_share_group: ImageShareGroup, desired_images: list
+ ) -> None:
+ desired_images = desired_images or []
+
+ # Build a map of the desired state of images by their private IDs
+ plan_map = {img["id"]: img for img in desired_images}
+
+ # Build a map of the remote state of images by their private IDs
+ remote_map = {}
+ for img in image_share_group.get_image_shares():
+ shared_by = getattr(
+ getattr(img, "image_sharing", None),
+ "shared_by",
+ None,
+ )
+ private_id = getattr(shared_by, "source_image_id", None)
+ if not private_id:
+ continue
+
+ remote_map[private_id] = {
+ "shared_id": getattr(img, "id", None),
+ "label": getattr(img, "label", None),
+ "description": getattr(img, "description", None),
+ }
+
+ to_add = []
+ to_update = []
+ to_remove = []
+
+ # Determine which images to add and update
+ for private_id, desired_image in plan_map.items():
+ remote = remote_map.get(private_id)
+
+ if not remote:
+ # Not present remotely, should be added
+ to_add.append(
+ {
+ "id": private_id,
+ "label": desired_image.get("label"),
+ "description": desired_image.get("description"),
+ }
+ )
+ continue
+
+ # Present remotely, check if an update is needed
+ label_changed = desired_image.get("label") != remote.get("label")
+ desc_changed = desired_image.get("description") != remote.get(
+ "description"
+ )
+
+ if label_changed or desc_changed:
+ opts = {}
+ if label_changed:
+ opts["label"] = desired_image.get("label")
+ if desc_changed:
+ opts["description"] = desired_image.get("description")
+
+ to_update.append(
+ {
+ "shared_id": remote["shared_id"],
+ "opts": opts,
+ }
+ )
+
+ # Determine which images to remove
+ for private_id, remote in remote_map.items():
+ if private_id not in plan_map:
+ to_remove.append(remote["shared_id"])
+
+ # Add
+ if to_add:
+ try:
+ images_to_add = ImageShareGroupImagesToAdd(
+ images=[
+ ImageShareGroupImageToAdd(
+ id=img["id"],
+ label=img.get("label"),
+ description=img.get("description"),
+ )
+ for img in to_add
+ ]
+ )
+
+ image_share_group.add_images(images_to_add)
+
+ for img in to_add:
+ self.register_action(f"Added image {img['id']}")
+
+ self.results["changed"] = True
+
+ except Exception as e:
+ self.fail(msg=f"Failed to add images: {e}")
+
+ # Update
+ for update in to_update:
+ try:
+ kwargs = {}
+ if "label" in update["opts"]:
+ kwargs["label"] = update["opts"]["label"]
+ if "description" in update["opts"]:
+ kwargs["description"] = update["opts"]["description"]
+
+ images_to_update = ImageShareGroupImageToUpdate(
+ image_share_id=update["shared_id"], **kwargs
+ )
+
+ image_share_group.update_image_share(images_to_update)
+ self.register_action(f"Updated image {update['shared_id']}")
+ self.results["changed"] = True
+ except Exception as e:
+ self.fail(
+ msg=f"Failed to update image {update['shared_id']}: {e}"
+ )
+
+ # Remove
+ for img_shared_id in to_remove:
+ try:
+ image_share_group.revoke_image_share(img_shared_id)
+ self.register_action(f"Removed image {img_shared_id}")
+ self.results["changed"] = True
+ except Exception as e:
+ self.fail(msg=f"Failed to remove image {img_shared_id}: {e}")
+
+ def _populate_results(self, sharegroup: ImageShareGroup) -> None:
+ sharegroup._api_get()
+ raw = sharegroup._raw_json
+
+ images_param = self.module.params.get("images")
+
+ if images_param is not None:
+ # User explicitly provided images
+ raw["images"] = images_param
+ else:
+ # User omitted images so fetch current images from API
+ images = []
+ for img in sharegroup.get_image_shares():
+ shared_by = getattr(
+ getattr(img, "image_sharing", None), "shared_by", None
+ )
+ private_id = getattr(shared_by, "source_image_id", None)
+ if private_id:
+ images.append(
+ {
+ "id": private_id,
+ "label": getattr(img, "label", None),
+ "description": getattr(img, "description", None),
+ }
+ )
+ raw["images"] = images
+
+ self.results["image_share_group"] = raw
+
+ def _handle_present(self) -> None:
+ label = self.module.params.get("label")
+ image_share_group = self._get_image_share_group_by_label(label)
+
+ if not image_share_group:
+ image_share_group = self._create()
+ self.register_action(
+ "Created Image Share Group {0}".format(image_share_group.label)
+ )
+
+ self._update(image_share_group)
+
+ self._populate_results(image_share_group)
+
+ def _handle_absent(self) -> None:
+ label: str = self.module.params.get("label")
+
+ sharegroup = self._get_image_share_group_by_label(label)
+
+ if sharegroup is not None:
+ self.results["image_share_group"] = sharegroup._raw_json
+ sharegroup.delete()
+ self.register_action("Deleted image share group {0}".format(label))
+
+ def exec_module(self, **kwargs: Any) -> Optional[dict]:
+ """Entrypoint for Image Share Group module"""
+ state = kwargs.get("state")
+
+ if state == "absent":
+ self._handle_absent()
+ return self.results
+
+ self._handle_present()
+
+ return self.results
+
+
+def main() -> None:
+ """Constructs and calls the Image Share Group module"""
+ Module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/plugins/modules/image_share_group_image_list.py b/plugins/modules/image_share_group_image_list.py
new file mode 100644
index 00000000..75b81999
--- /dev/null
+++ b/plugins/modules/image_share_group_image_list.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module allows users to list Image Share Group Images."""
+
+from __future__ import absolute_import, division, print_function
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_image_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="Image Share Group Images",
+ result_field_name="image_share_group_images",
+ endpoint_template="/images/sharegroups/{sharegroup_id}/images",
+ result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup-images",
+ result_samples=docs.result_image_share_group_images_samples,
+ examples=docs.specdoc_examples,
+ params=[
+ ListModuleParam(
+ display_name="Image Share Group",
+ name="sharegroup_id",
+ type=FieldType.integer,
+ ),
+ ],
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/plugins/modules/image_share_group_info.py b/plugins/modules/image_share_group_info.py
new file mode 100644
index 00000000..ff707f97
--- /dev/null
+++ b/plugins/modules/image_share_group_info.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module contains the functionality for the Image Share Group info module."""
+
+from __future__ import absolute_import, division, print_function
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_info as docs,
+)
+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 (
+ safe_find,
+)
+from ansible_specdoc.objects import FieldType
+from linode_api4 import ImageShareGroup
+
+module = InfoModule(
+ primary_result=InfoModuleResult(
+ field_name="image_share_group",
+ field_type=FieldType.dict,
+ display_name="Image Share Group",
+ docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup",
+ samples=docs.result_image_share_group_samples,
+ ),
+ attributes=[
+ InfoModuleAttr(
+ display_name="ID",
+ name="id",
+ type=FieldType.integer,
+ get=lambda client, params: client.load(
+ ImageShareGroup,
+ params.get("id"),
+ )._raw_json,
+ ),
+ InfoModuleAttr(
+ display_name="label",
+ name="label",
+ type=FieldType.string,
+ get=lambda client, params: safe_find(
+ client.sharegroups,
+ ImageShareGroup.label == params.get("label"),
+ raise_not_found=True,
+ )._raw_json,
+ ),
+ ],
+ examples=docs.specdoc_examples,
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/plugins/modules/image_share_group_list.py b/plugins/modules/image_share_group_list.py
new file mode 100644
index 00000000..e55230e0
--- /dev/null
+++ b/plugins/modules/image_share_group_list.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module allows users to list Image Share Groups."""
+
+from __future__ import absolute_import, division, print_function
+
+from typing import Dict
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_list as docs,
+)
+from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import (
+ ListModule,
+)
+from ansible_specdoc.objects import FieldType, SpecField
+
+
+def custom_field_resolver(params: Dict[str, str]) -> Dict[str, str]:
+ """
+ Resolves the appropriate endpoint based on the 'image_id' parameter.
+
+ :param params: The parameters passed to the module.
+
+ :returns: The appropriate documentation and examples.
+ """
+ if params.get("image_id"):
+ return {
+ "endpoint_template": f"/images/{params.get('image_id')}/sharegroups",
+ }
+ return {
+ "endpoint_template": "/images/sharegroups",
+ }
+
+
+module = ListModule(
+ result_display_name="Image Share Groups",
+ result_field_name="image_share_groups",
+ endpoint_template="/images/sharegroups",
+ result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroups",
+ result_samples=docs.result_image_share_groups_samples,
+ examples=docs.specdoc_examples,
+ custom_options={
+ "image_id": SpecField(
+ type=FieldType.string,
+ description=[
+ "Specifies the private image ID to list share groups for.",
+ "If provided, only share groups containing the specified image will be returned.",
+ ],
+ required=False,
+ ),
+ },
+ custom_field_resolver=custom_field_resolver,
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/plugins/modules/image_share_group_member.py b/plugins/modules/image_share_group_member.py
new file mode 100644
index 00000000..ec83cb41
--- /dev/null
+++ b/plugins/modules/image_share_group_member.py
@@ -0,0 +1,196 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module contains all the functionality for Image Share Group Members for a Producer."""
+
+from __future__ import absolute_import, division, print_function
+
+from typing import Any, Dict, Optional
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_member 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_specdoc.objects import (
+ FieldType,
+ SpecDocMeta,
+ SpecField,
+ SpecReturnValue,
+)
+from linode_api4 import ImageShareGroup, ImageShareGroupMemberToAdd
+
+SPEC = {
+ "label": SpecField(
+ type=FieldType.string,
+ description=["This Image Share Group Member's unique label."],
+ required=True,
+ ),
+ "token": SpecField(
+ type=FieldType.string,
+ description=[
+ "A single-use Image Share Group Token provided by the Consumer. "
+ "This value is required when creating a member and is never returned."
+ ],
+ no_log=True,
+ ),
+ "sharegroup_id": SpecField(
+ type=FieldType.integer,
+ description=["The ID of the Image Share Group this member belongs to."],
+ required=True,
+ ),
+ "state": SpecField(
+ type=FieldType.string,
+ description=["The desired state of the target."],
+ choices=["present", "absent"],
+ required=True,
+ ),
+}
+
+SPECDOC_META = SpecDocMeta(
+ description=["Manage an Image Share Group Member."],
+ requirements=global_requirements,
+ author=global_authors,
+ options=SPEC,
+ examples=docs.specdoc_examples,
+ return_values={
+ "image_share_group_member": SpecReturnValue(
+ description="The Image Share Group Member in JSON serialized form.",
+ docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup-member-token",
+ type=FieldType.dict,
+ sample=docs.result_image_share_group_member_samples,
+ ),
+ },
+)
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+
+class Module(LinodeModuleBase):
+ """Module for creating and destroying Image Share Group Members"""
+
+ def __init__(self) -> None:
+ self.module_arg_spec = SPECDOC_META.ansible_spec
+ self.results = {
+ "changed": False,
+ "actions": [],
+ "image_share_group_member": None,
+ }
+
+ super().__init__(
+ module_arg_spec=self.module_arg_spec,
+ required_if=[
+ ("state", "present", ["token"]),
+ ],
+ )
+
+ def _get_image_share_group_member_by_label(
+ self, label: str
+ ) -> Optional[Dict[str, Any]]:
+ try:
+ sharegroup = self.client.load(
+ ImageShareGroup, self.module.params.get("sharegroup_id")
+ )
+ return next(
+ (
+ m.__dict__
+ for m in sharegroup.get_members()
+ if m.label == label
+ ),
+ None,
+ )
+ except Exception as exception:
+ return self.fail(
+ msg="failed to get image share group member for label {0}: {1}".format(
+ label, exception
+ )
+ )
+
+ def _create(self) -> Optional[Dict[str, Any]]:
+ try:
+ sharegroup = self.client.load(
+ ImageShareGroup,
+ self.module.params.get("sharegroup_id"),
+ )
+
+ member = ImageShareGroupMemberToAdd(
+ token=self.module.params.get("token"),
+ label=self.module.params.get("label"),
+ )
+
+ member_obj = sharegroup.add_member(member)
+ return member_obj.__dict__
+
+ except Exception as exception:
+ return self.fail(
+ msg="failed to create Image Share Group Member: {0}".format(
+ exception
+ )
+ )
+
+ def _handle_present(self) -> None:
+ label = self.module.params.get("label")
+ member = self._get_image_share_group_member_by_label(label)
+
+ if not member:
+ member = self._create()
+ self.register_action(
+ "Created Image Share Group Member {0}".format(label)
+ )
+
+ self.results["image_share_group_member"] = member
+
+ def _handle_absent(self) -> None:
+ label = self.module.params.get("label")
+ member = self._get_image_share_group_member_by_label(label)
+
+ if member is None:
+ return
+
+ sharegroup = self.client.load(
+ ImageShareGroup,
+ self.module.params.get("sharegroup_id"),
+ )
+
+ try:
+ token_uuid = member.get("token_uuid")
+ sharegroup.remove_member(token_uuid=token_uuid)
+ self.results["image_share_group_member"] = member
+ self.register_action(f"Deleted Image Share Group Member {label}")
+ except Exception as exception:
+ return self.fail(
+ msg="failed to delete Image Share Group Member {0}: {1}".format(
+ label, exception
+ )
+ )
+
+ def exec_module(self, **kwargs: Any) -> Optional[dict]:
+ """Entrypoint for Image Share Group Member module"""
+ state = kwargs.get("state")
+
+ if state == "absent":
+ self._handle_absent()
+ return self.results
+
+ self._handle_present()
+
+ return self.results
+
+
+def main() -> None:
+ """Constructs and calls the Image Share Group Member module"""
+ Module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/plugins/modules/image_share_group_member_info.py b/plugins/modules/image_share_group_member_info.py
new file mode 100644
index 00000000..44a7c9f0
--- /dev/null
+++ b/plugins/modules/image_share_group_member_info.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module contains the functionality for the Image Share Group Member info module."""
+
+from __future__ import absolute_import, division, print_function
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_member_info as docs,
+)
+from ansible_collections.linode.cloud.plugins.module_utils.linode_common_info import (
+ InfoModule,
+ InfoModuleAttr,
+ InfoModuleParam,
+ InfoModuleResult,
+)
+from ansible_specdoc.objects import FieldType
+from linode_api4 import ImageShareGroup
+
+module = InfoModule(
+ primary_result=InfoModuleResult(
+ field_name="image_share_group_member",
+ field_type=FieldType.dict,
+ display_name="Image Share Group Member",
+ docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup-member-token",
+ samples=docs.result_image_share_group_member_samples,
+ ),
+ params=[
+ InfoModuleParam(
+ display_name="Image Share Group",
+ name="sharegroup_id",
+ type=FieldType.integer,
+ )
+ ],
+ attributes=[
+ InfoModuleAttr(
+ display_name="Token UUID",
+ name="token_uuid",
+ type=FieldType.string,
+ get=lambda client, params: next(
+ (
+ m.__dict__
+ for m in client.load(
+ ImageShareGroup,
+ params.get("sharegroup_id"),
+ ).get_members()
+ if m.token_uuid == params.get("token_uuid")
+ ),
+ None,
+ ),
+ ),
+ InfoModuleAttr(
+ display_name="label",
+ name="label",
+ type=FieldType.string,
+ get=lambda client, params: next(
+ (
+ m.__dict__
+ for m in client.load(
+ ImageShareGroup,
+ params.get("sharegroup_id"),
+ ).get_members()
+ if m.label == params.get("label")
+ ),
+ None,
+ ),
+ ),
+ ],
+ examples=docs.specdoc_examples,
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/plugins/modules/image_share_group_member_list.py b/plugins/modules/image_share_group_member_list.py
new file mode 100644
index 00000000..9a617296
--- /dev/null
+++ b/plugins/modules/image_share_group_member_list.py
@@ -0,0 +1,43 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module allows users to list Image Share Group Members."""
+
+from __future__ import absolute_import, division, print_function
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_member_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="Image Share Group Members",
+ result_field_name="image_share_group_members",
+ endpoint_template="/images/sharegroups/{sharegroup_id}/members",
+ result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup-members",
+ result_samples=docs.result_image_share_group_members_samples,
+ examples=docs.specdoc_examples,
+ params=[
+ ListModuleParam(
+ display_name="Image Share Group",
+ name="sharegroup_id",
+ type=FieldType.integer,
+ ),
+ ],
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/plugins/modules/image_share_group_token.py b/plugins/modules/image_share_group_token.py
new file mode 100644
index 00000000..5a76727c
--- /dev/null
+++ b/plugins/modules/image_share_group_token.py
@@ -0,0 +1,196 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module contains all the functionality for Image Share Group Tokens for a Consumer."""
+
+from __future__ import absolute_import, division, print_function
+
+from typing import Any, Optional
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_token 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 (
+ filter_null_values,
+)
+from ansible_specdoc.objects import (
+ FieldType,
+ SpecDocMeta,
+ SpecField,
+ SpecReturnValue,
+)
+from linode_api4 import ImageShareGroupToken
+
+SPEC = {
+ "label": SpecField(
+ type=FieldType.string,
+ description=["This Image Share Group Token's unique label."],
+ required=True,
+ ),
+ "valid_for_sharegroup_uuid": SpecField(
+ type=FieldType.string,
+ description=[
+ "The UUID of the Image Share Group that this token is valid for."
+ ],
+ ),
+ "state": SpecField(
+ type=FieldType.string,
+ description=["The desired state of the target."],
+ choices=["present", "absent"],
+ required=True,
+ ),
+}
+
+SPECDOC_META = SpecDocMeta(
+ description=["Manage an Image Share Group Token."],
+ requirements=global_requirements,
+ author=global_authors,
+ options=SPEC,
+ examples=docs.specdoc_examples,
+ return_values={
+ "image_share_group_token": SpecReturnValue(
+ description="The Image Share Group Token in JSON serialized form.",
+ docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup-token",
+ type=FieldType.dict,
+ sample=docs.result_image_share_group_token_samples,
+ ),
+ "single_use_token": SpecReturnValue(
+ description="The single use token string to provide to a Image Share Group Producer "
+ "to be added to the share group.",
+ type=FieldType.string,
+ sample=docs.result_single_use_token_samples,
+ ),
+ },
+)
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+
+class Module(LinodeModuleBase):
+ """Module for creating and destroying Image Share Group Tokens"""
+
+ def __init__(self) -> None:
+ self.module_arg_spec = SPECDOC_META.ansible_spec
+ self.results = {
+ "changed": False,
+ "actions": [],
+ "image_share_group_token": None,
+ "single_use_token": None,
+ }
+
+ super().__init__(
+ module_arg_spec=self.module_arg_spec,
+ required_if=[
+ ("state", "present", ["valid_for_sharegroup_uuid"]),
+ ],
+ )
+
+ def _get_image_share_group_token_by_label(
+ self, label: str
+ ) -> Optional[ImageShareGroupToken]:
+ try:
+ return self.client.sharegroups.tokens(
+ ImageShareGroupToken.label == label
+ )[0]
+ except IndexError:
+ return None
+ except Exception as exception:
+ return self.fail(
+ msg="failed to get image share group token for label {0}: {1}".format(
+ label, exception
+ )
+ )
+
+ def _create(self) -> Optional[ImageShareGroupToken]:
+ params = filter_null_values(
+ {
+ "label": self.module.params.get("label"),
+ "valid_for_sharegroup_uuid": self.module.params.get(
+ "valid_for_sharegroup_uuid"
+ ),
+ }
+ )
+
+ try:
+ token_obj, single_use_token = self.client.sharegroups.create_token(
+ **params
+ )
+ self.results["single_use_token"] = single_use_token
+ return token_obj
+ except Exception as exception:
+ return self.fail(
+ msg="failed to create Image Share Group Token: {0}".format(
+ exception
+ )
+ )
+
+ def _handle_present(self) -> None:
+ label = self.module.params.get("label")
+ requested_uuid = self.module.params.get("valid_for_sharegroup_uuid")
+
+ token = self._get_image_share_group_token_by_label(label)
+
+ if token:
+ token._api_get()
+
+ existing_uuid = token.valid_for_sharegroup_uuid
+
+ if requested_uuid != existing_uuid:
+ self.fail(
+ msg=(
+ "failed to update {} -> {}: valid_for_sharegroup_uuid "
+ "is a non-updatable field"
+ ).format(existing_uuid, requested_uuid)
+ )
+ else:
+ token = self._create()
+ self.register_action(
+ "Created Image Share Group Token {0}".format(label)
+ )
+ token._api_get()
+
+ self.results["image_share_group_token"] = token._raw_json
+
+ def _handle_absent(self) -> None:
+ label: str = self.module.params.get("label")
+ token = self._get_image_share_group_token_by_label(label)
+
+ if token is not None:
+ self.results["image_share_group_token"] = token._raw_json
+ token.delete()
+ self.register_action(
+ "Deleted image share group token {0}".format(label)
+ )
+
+ def exec_module(self, **kwargs: Any) -> Optional[dict]:
+ """Entrypoint for Image Share Group Token module"""
+ state = kwargs.get("state")
+
+ if state == "absent":
+ self._handle_absent()
+ return self.results
+
+ self._handle_present()
+
+ return self.results
+
+
+def main() -> None:
+ """Constructs and calls the Image Share Group Token module"""
+ Module()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/plugins/modules/image_share_group_token_info.py b/plugins/modules/image_share_group_token_info.py
new file mode 100644
index 00000000..7d8ad58e
--- /dev/null
+++ b/plugins/modules/image_share_group_token_info.py
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module contains the functionality for the Image Share Group Token info module."""
+
+from __future__ import absolute_import, division, print_function
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_token_info as docs,
+)
+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 (
+ safe_find,
+)
+from ansible_specdoc.objects import FieldType
+from linode_api4 import ImageShareGroupToken
+
+module = InfoModule(
+ primary_result=InfoModuleResult(
+ field_name="image_share_group_token",
+ field_type=FieldType.dict,
+ display_name="Image Share Group Token",
+ docs_url="https://techdocs.akamai.com/linode-api/reference/get-sharegroup-token",
+ samples=docs.result_image_share_group_token_samples,
+ ),
+ attributes=[
+ InfoModuleAttr(
+ display_name="Token UUID",
+ name="token_uuid",
+ type=FieldType.string,
+ get=lambda client, params: client.load(
+ ImageShareGroupToken,
+ params.get("token_uuid"),
+ )._raw_json,
+ ),
+ InfoModuleAttr(
+ display_name="label",
+ name="label",
+ type=FieldType.string,
+ get=lambda client, params: safe_find(
+ client.sharegroups.tokens,
+ ImageShareGroupToken.label == params.get("label"),
+ raise_not_found=True,
+ )._raw_json,
+ ),
+ ],
+ examples=docs.specdoc_examples,
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/plugins/modules/image_share_group_token_list.py b/plugins/modules/image_share_group_token_list.py
new file mode 100644
index 00000000..7aa0fdbe
--- /dev/null
+++ b/plugins/modules/image_share_group_token_list.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+"""This module allows users to list Image Share Group Tokens."""
+
+from __future__ import absolute_import, division, print_function
+
+from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import (
+ image_share_group_token_list as docs,
+)
+from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import (
+ ListModule,
+)
+
+module = ListModule(
+ result_display_name="Image Share Group Tokens",
+ result_field_name="image_share_group_tokens",
+ endpoint_template="/images/sharegroups/tokens",
+ result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-user-tokens",
+ result_samples=docs.result_image_share_group_tokens_samples,
+ examples=docs.specdoc_examples,
+)
+
+SPECDOC_META = module.spec
+
+DOCUMENTATION = r"""
+"""
+EXAMPLES = r"""
+"""
+RETURN = r"""
+"""
+
+if __name__ == "__main__":
+ module.run()
diff --git a/requirements.txt b/requirements.txt
index 85c35e1a..119a88e8 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,3 @@
-linode-api4>=5.38.0
+linode-api4>=5.39.0
polling==0.3.2
ansible-specdoc>=0.0.19
diff --git a/tests/integration/targets/consumer_image_share_group_image_list/tasks/main.yaml b/tests/integration/targets/consumer_image_share_group_image_list/tasks/main.yaml
new file mode 100644
index 00000000..4a21e097
--- /dev/null
+++ b/tests/integration/targets/consumer_image_share_group_image_list/tasks/main.yaml
@@ -0,0 +1,218 @@
+- name: consumer_image_share_group_image_list
+ block:
+ - name: Normalize producer/consumer tokens
+ set_fact:
+ _producer_token: "{{ producer_api_token | default('', true) | trim }}"
+ _consumer_token: "{{ consumer_api_token | default('', true) | trim }}"
+
+ - name: Skip test if producer/consumer tokens are missing
+ meta: end_play
+ when: _producer_token == '' or _consumer_token == ''
+
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+ disallowed_image_regions: ["gb-lon", "au-mel", "sg-sin-2", "jp-tyo-3", "no-osl-1"]
+
+ - name: List regions
+ linode.cloud.region_list: { }
+ register: all_regions
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - set_fact:
+ capable_regions: '{{ ( all_regions.regions | selectattr("site_type", "equalto", "core") | selectattr("capabilities", "search", "Object Storage") | rejectattr("id", "in", disallowed_image_regions) | map(attribute="id") | list) }}'
+
+ - name: Create instance one to image
+ linode.cloud.instance:
+ label: 'ansible-test-{{ r }}-one'
+ region: '{{ capable_regions[1] }}'
+ type: g6-standard-1
+ image: linode/alpine3.19
+ state: present
+ firewall_id: '{{ firewall_id }}'
+ register: instance_one_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image one
+ linode.cloud.image:
+ disk_id: "{{ instance_one_create.disks.0.id }}"
+ label: image-one
+ description: first image
+ state: present
+ register: image_one_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create instance two to image
+ linode.cloud.instance:
+ label: 'ansible-test-{{ r }}-two'
+ region: '{{ capable_regions[1] }}'
+ type: g6-standard-1
+ image: linode/alpine3.19
+ state: present
+ firewall_id: '{{ firewall_id }}'
+ register: instance_two_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image two
+ linode.cloud.image:
+ disk_id: "{{ instance_two_create.disks.0.id }}"
+ label: image-two
+ description: second-image
+ state: present
+ register: image_two_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image share group (producer task)
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ images:
+ - id: '{{ image_one_create.image.id }}'
+ label: 'image-one'
+ description: 'first image'
+ - id: '{{ image_two_create.image.id }}'
+ label: 'image-two'
+ description: 'second image'
+ state: present
+ register: share_group_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Add consumer as member to share group (producer task)
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}"
+ token: "{{ share_group_token_create.single_use_token }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: present
+ register: share_group_member_add
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: List image share group images with no filter
+ linode.cloud.consumer_image_share_group_image_list:
+ token_uuid: "{{ share_group_token_create.image_share_group_token.token_uuid }}"
+ count: 2
+ register: no_filter
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert consumer_image_share_group_image_list with no filter
+ assert:
+ that:
+ - no_filter.image_share_group_images | length == 2
+
+ - name: List image share group images with filter on label
+ linode.cloud.consumer_image_share_group_image_list:
+ token_uuid: "{{ share_group_token_create.image_share_group_token.token_uuid }}"
+ count: 1
+ order_by: created
+ order: desc
+ filters:
+ - name: label
+ values: 'image-one'
+ register: filter
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert consumer_image_share_group_image_list with filter on label
+ assert:
+ that:
+ - filter.image_share_group_images | length == 1
+ - filter.image_share_group_images[0].label == "image-one"
+
+ - name: Remove remaining images in share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_create.image_share_group.label }}'
+ images: [ ]
+ state: present
+ register: share_group_images_removed
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Assert images removed from share group
+ assert:
+ that:
+ - share_group_images_removed.image_share_group.images | length == 0
+ - share_group_images_removed.image_share_group.images_count == 0
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group member
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create is defined
+ - share_group_token_create.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: "{{ share_group_create.image_share_group.label }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete image
+ linode.cloud.image:
+ label: '{{ image_one_create.image.label }}'
+ state: absent
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete image
+ linode.cloud.image:
+ label: '{{ image_two_create.image.label }}'
+ state: absent
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete instance
+ linode.cloud.instance:
+ label: '{{ instance_one_create.instance.label }}'
+ state: absent
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete instance
+ linode.cloud.instance:
+ label: '{{ instance_two_create.instance.label }}'
+ state: absent
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ environment:
+ LINODE_UA_PREFIX: "{{ ua_prefix }}"
+ LINODE_PRODUCER_API_TOKEN: "{{ producer_api_token }}"
+ LINODE_CONSUMER_API_TOKEN: "{{ consumer_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/consumer_image_share_group_info/tasks/main.yaml b/tests/integration/targets/consumer_image_share_group_info/tasks/main.yaml
new file mode 100644
index 00000000..b05e0c16
--- /dev/null
+++ b/tests/integration/targets/consumer_image_share_group_info/tasks/main.yaml
@@ -0,0 +1,94 @@
+- name: consumer_image_share_group_info
+ block:
+ - name: Normalize producer/consumer tokens
+ set_fact:
+ _producer_token: "{{ producer_api_token | default('', true) | trim }}"
+ _consumer_token: "{{ consumer_api_token | default('', true) | trim }}"
+
+ - name: Skip test if producer/consumer tokens are missing
+ meta: end_play
+ when: _producer_token == '' or _consumer_token == ''
+
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+
+ - name: Create image share group (producer task)
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ state: present
+ register: share_group_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Add consumer as member to share group (producer task)
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}"
+ token: "{{ share_group_token_create.single_use_token }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: present
+ register: share_group_member_add
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Get image share group info (consumer task)
+ linode.cloud.consumer_image_share_group_info:
+ token_uuid: "{{ share_group_token_create.image_share_group_token.token_uuid }}"
+ register: consumer_share_group_info
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert consumer image share group info is correct
+ assert:
+ that:
+ - consumer_share_group_info.image_share_group.label == "ansible-test-" ~ r
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group member
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create is defined
+ - share_group_token_create.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: "{{ share_group_create.image_share_group.label }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ environment:
+ LINODE_UA_PREFIX: "{{ ua_prefix }}"
+ LINODE_PRODUCER_API_TOKEN: "{{ producer_api_token }}"
+ LINODE_CONSUMER_API_TOKEN: "{{ consumer_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/image_basic/tasks/main.yaml b/tests/integration/targets/image_basic/tasks/main.yaml
index 69e6ea57..4f501215 100644
--- a/tests/integration/targets/image_basic/tasks/main.yaml
+++ b/tests/integration/targets/image_basic/tasks/main.yaml
@@ -41,6 +41,8 @@
- image_create.image.capabilities[0] == 'cloud-init'
- image_create.image.tags | length == 2
- image_create.image.size == image_create.image.total_size
+ - image_create.image.is_shared == false
+ - image_create.image.image_sharing.shared_with.sharegroup_count == 0
- name: Get image_info by ID
linode.cloud.image_info:
@@ -53,6 +55,8 @@
- info_id.image.status == 'available'
- info_id.image.description == 'cool'
- info_id.image.id == image_create.image.id
+ - info_id.image.is_shared == false
+ - info_id.image.image_sharing.shared_with.sharegroup_count == 0
- name: Get image_info by label
linode.cloud.image_info:
diff --git a/tests/integration/targets/image_share_group_basic/tasks/main.yaml b/tests/integration/targets/image_share_group_basic/tasks/main.yaml
new file mode 100644
index 00000000..1b338094
--- /dev/null
+++ b/tests/integration/targets/image_share_group_basic/tasks/main.yaml
@@ -0,0 +1,234 @@
+- name: image_share_group_basic
+ block:
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+ disallowed_image_regions: ["gb-lon", "au-mel", "sg-sin-2", "jp-tyo-3", "no-osl-1"]
+
+ - name: List regions
+ linode.cloud.region_list: { }
+ register: all_regions
+
+ - set_fact:
+ capable_regions: '{{ ( all_regions.regions | selectattr("site_type", "equalto", "core") | selectattr("capabilities", "search", "Object Storage") | rejectattr("id", "in", disallowed_image_regions) | map(attribute="id") | list) }}'
+
+ - name: Create instance one to image
+ linode.cloud.instance:
+ label: 'ansible-test-{{ r }}-one'
+ region: '{{ capable_regions[1] }}'
+ type: g6-standard-1
+ image: linode/alpine3.19
+ state: present
+ firewall_id: '{{ firewall_id }}'
+ register: instance_one_create
+
+ - name: Create image one
+ linode.cloud.image:
+ disk_id: "{{ instance_one_create.disks.0.id }}"
+ label: image-one
+ description: first image
+ state: present
+ register: image_one_create
+
+ - name: Create instance two to image
+ linode.cloud.instance:
+ label: 'ansible-test-{{ r }}-two'
+ region: '{{ capable_regions[1] }}'
+ type: g6-standard-1
+ image: linode/alpine3.19
+ state: present
+ firewall_id: '{{ firewall_id }}'
+ register: instance_two_create
+
+ - name: Create image two
+ linode.cloud.image:
+ disk_id: "{{ instance_two_create.disks.0.id }}"
+ label: image-two
+ description: second-image
+ state: present
+ register: image_two_create
+
+ - name: Assert images are created
+ assert:
+ that:
+ - image_one_create.image.status == 'available'
+ - image_two_create.image.status == 'available'
+ - image_one_create.image.image_sharing.shared_with.sharegroup_count == 0
+ - image_two_create.image.image_sharing.shared_with.sharegroup_count == 0
+
+ - name: Create an image share group without any images
+ linode.cloud.image_share_group:
+ label: 'ansible-share-group-empty'
+ description: 'share group desc'
+ state: present
+ register: share_group_empty_create
+
+ - name: Assert image share group is created
+ assert:
+ that:
+ - share_group_empty_create.image_share_group.label == 'ansible-share-group-empty'
+ - share_group_empty_create.image_share_group.description == 'share group desc'
+ - share_group_empty_create.image_share_group.images_count == 0
+
+ - name: Add images to share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_empty_create.image_share_group.label }}'
+ images:
+ - id: '{{ image_one_create.image.id }}'
+ label: 'image-one'
+ description: 'first image'
+ - id: '{{ image_two_create.image.id }}'
+ label: 'image-two'
+ state: present
+ register: share_group_empty_add_images
+
+ - name: Select images for assertions
+ set_fact:
+ img_one: "{{ share_group_empty_add_images.image_share_group.images | selectattr('id', 'equalto', image_one_create.image.id) | first }}"
+ img_two: "{{ share_group_empty_add_images.image_share_group.images | selectattr('id', 'equalto', image_two_create.image.id) | first }}"
+
+ - name: Assert images added to share group
+ assert:
+ that:
+ - img_one.label == 'image-one'
+ - img_one.description == 'first image'
+ - img_two.label == 'image-two'
+ - img_two.description is none
+ - share_group_empty_add_images.image_share_group.images | length == 2
+ - share_group_empty_add_images.image_share_group.images_count == 2
+
+ - name: Update images in share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_empty_add_images.image_share_group.label }}'
+ images:
+ - id: '{{ image_one_create.image.id }}'
+ label: 'image-one-updated'
+ description: 'first image updated'
+ state: present
+ register: share_group_empty_update_images
+
+ - name: Select updated images for assertions
+ set_fact:
+ img_one_updated: "{{ share_group_empty_update_images.image_share_group.images | selectattr('id', 'equalto', image_one_create.image.id) | first }}"
+ img_two_removed: "{{ share_group_empty_update_images.image_share_group.images | selectattr('id', 'equalto', image_two_create.image.id) | list }}"
+
+ - name: Assert images updated in share group
+ assert:
+ that:
+ - img_one_updated.label == 'image-one-updated'
+ - img_one_updated.description == 'first image updated'
+ - img_two_removed | length == 0
+ - share_group_empty_update_images.image_share_group.images | length == 1
+ - share_group_empty_update_images.image_share_group.images_count == 1
+
+ - name: Remove remaining images in share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_empty_update_images.image_share_group.label }}'
+ images: []
+ state: present
+ register: share_group_empty_images_removed
+
+ - name: Select removed images for assertions
+ set_fact:
+ img_one_removed: "{{ share_group_empty_images_removed.image_share_group.images | selectattr('id', 'equalto', image_one_create.image.id) | list }}"
+ img_two_removed: "{{ share_group_empty_images_removed.image_share_group.images | selectattr('id', 'equalto', image_two_create.image.id) | list }}"
+
+ - name: Assert images removed from share group
+ assert:
+ that:
+ - img_one_removed | length == 0
+ - img_two_removed | length == 0
+ - share_group_empty_images_removed.image_share_group.images | length == 0
+ - share_group_empty_images_removed.image_share_group.images_count == 0
+
+ - name: Update image share group details
+ linode.cloud.image_share_group:
+ label: '{{ share_group_empty_images_removed.image_share_group.label }}'
+ description: 'share group desc updated'
+ state: present
+ register: share_group_update_details
+
+ - name: Assert image share group details updated
+ assert:
+ that:
+ - share_group_update_details.image_share_group.description == 'share group desc updated'
+
+ - name: Create an image share group with an image
+ linode.cloud.image_share_group:
+ label: 'ansible-share-group-populated'
+ images:
+ - id: '{{ image_one_create.image.id }}'
+ label: 'image-one'
+ description: 'first image'
+ state: present
+ register: share_group_populated_create
+
+ - name: Assert image share group is created
+ assert:
+ that:
+ - share_group_populated_create.image_share_group.label == 'ansible-share-group-populated'
+ - share_group_populated_create.image_share_group.images_count == 1
+
+ - name: Check that removing images field leaves images unchanged
+ linode.cloud.image_share_group:
+ label: '{{ share_group_populated_create.image_share_group.label }}'
+ state: present
+ register: share_group_populated_no_change
+
+ - name: Assert images unchanged in share group
+ assert:
+ that:
+ - share_group_populated_no_change.image_share_group.images | length == 1
+ - share_group_populated_no_change.image_share_group.images_count == 1
+
+ - name: Remove remaining images in share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_populated_create.image_share_group.label }}'
+ images: []
+ state: present
+ register: share_group_populated_images_removed
+
+ - name: Assert images removed from share group
+ assert:
+ that:
+ - share_group_populated_images_removed.image_share_group.images | length == 0
+ - share_group_populated_images_removed.image_share_group.images_count == 0
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_update_details.image_share_group.label }}'
+ state: absent
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_populated_images_removed.image_share_group.label }}'
+ state: absent
+
+ - name: Delete image
+ linode.cloud.image:
+ label: '{{ image_one_create.image.label }}'
+ state: absent
+
+ - name: Delete image
+ linode.cloud.image:
+ label: '{{ image_two_create.image.label }}'
+ state: absent
+
+ - name: Delete instance
+ linode.cloud.instance:
+ label: '{{ instance_one_create.instance.label }}'
+ state: absent
+
+ - name: Delete instance
+ linode.cloud.instance:
+ label: '{{ instance_two_create.instance.label }}'
+ state: absent
+
+ 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/image_share_group_image_list/tasks/main.yaml b/tests/integration/targets/image_share_group_image_list/tasks/main.yaml
new file mode 100644
index 00000000..4572cb50
--- /dev/null
+++ b/tests/integration/targets/image_share_group_image_list/tasks/main.yaml
@@ -0,0 +1,145 @@
+- name: image_share_group_image_list
+ block:
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+ disallowed_image_regions: ["gb-lon", "au-mel", "sg-sin-2", "jp-tyo-3", "no-osl-1"]
+
+ - name: List regions
+ linode.cloud.region_list: { }
+ register: all_regions
+
+ - set_fact:
+ capable_regions: '{{ ( all_regions.regions | selectattr("site_type", "equalto", "core") | selectattr("capabilities", "search", "Object Storage") | rejectattr("id", "in", disallowed_image_regions) | map(attribute="id") | list) }}'
+
+ - name: Create instance one to image
+ linode.cloud.instance:
+ label: 'ansible-test-{{ r }}-one'
+ region: '{{ capable_regions[1] }}'
+ type: g6-standard-1
+ image: linode/alpine3.19
+ state: present
+ firewall_id: '{{ firewall_id }}'
+ register: instance_one_create
+
+ - name: Create image one
+ linode.cloud.image:
+ disk_id: "{{ instance_one_create.disks.0.id }}"
+ label: image-one
+ description: first image
+ state: present
+ register: image_one_create
+
+ - name: Create instance two to image
+ linode.cloud.instance:
+ label: 'ansible-test-{{ r }}-two'
+ region: '{{ capable_regions[1] }}'
+ type: g6-standard-1
+ image: linode/alpine3.19
+ state: present
+ firewall_id: '{{ firewall_id }}'
+ register: instance_two_create
+
+ - name: Create image two
+ linode.cloud.image:
+ disk_id: "{{ instance_two_create.disks.0.id }}"
+ label: image-two
+ description: second-image
+ state: present
+ register: image_two_create
+
+ - name: Assert images are created
+ assert:
+ that:
+ - image_one_create.image.status == 'available'
+ - image_two_create.image.status == 'available'
+ - image_one_create.image.image_sharing.shared_with.sharegroup_count == 0
+ - image_two_create.image.image_sharing.shared_with.sharegroup_count == 0
+
+ - name: Create an image share group
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ images:
+ - id: '{{ image_one_create.image.id }}'
+ label: 'image-one'
+ description: 'first image'
+ - id: '{{ image_two_create.image.id }}'
+ label: 'image-two'
+ description: 'second image'
+ state: present
+ register: share_group_create
+
+ - name: List image share group images with no filter
+ linode.cloud.image_share_group_image_list:
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ count: 2
+ register: no_filter
+
+ - name: Assert image_share_group_image_list with no filter
+ assert:
+ that:
+ - no_filter.image_share_group_images | length == 2
+
+ - name: List image share group images with filter on label
+ linode.cloud.image_share_group_image_list:
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ count: 1
+ order_by: created
+ order: desc
+ filters:
+ - name: label
+ values: 'image-one'
+ register: filter
+
+ - name: Assert image_share_group_image_list with filter on label
+ assert:
+ that:
+ - filter.image_share_group_images | length == 1
+ - filter.image_share_group_images[0].label == "image-one"
+
+ - name: Remove remaining images in share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_create.image_share_group.label }}'
+ images: []
+ state: present
+ register: share_group_images_removed
+
+ - name: Assert images removed from share group
+ assert:
+ that:
+ - share_group_images_removed.image_share_group.images | length == 0
+ - share_group_images_removed.image_share_group.images_count == 0
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_images_removed.image_share_group.label }}'
+ state: absent
+
+ - name: Delete image
+ linode.cloud.image:
+ label: '{{ image_one_create.image.label }}'
+ state: absent
+
+ - name: Delete image
+ linode.cloud.image:
+ label: '{{ image_two_create.image.label }}'
+ state: absent
+
+ - name: Delete instance
+ linode.cloud.instance:
+ label: '{{ instance_one_create.instance.label }}'
+ state: absent
+
+ - name: Delete instance
+ linode.cloud.instance:
+ label: '{{ instance_two_create.instance.label }}'
+ state: absent
+
+ 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 "" }}'
diff --git a/tests/integration/targets/image_share_group_info/tasks/main.yaml b/tests/integration/targets/image_share_group_info/tasks/main.yaml
new file mode 100644
index 00000000..4d9192d3
--- /dev/null
+++ b/tests/integration/targets/image_share_group_info/tasks/main.yaml
@@ -0,0 +1,35 @@
+- name: image_share_group_info
+ block:
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+
+ - name: Create an image share group
+ linode.cloud.image_share_group:
+ label: 'ansible-test-{{ r }}'
+ state: present
+ register: share_group_create
+
+ - name: Get information about the Image Share Group
+ linode.cloud.image_share_group_info:
+ label: "{{ share_group_create.image_share_group.label }}"
+ register: share_group_info
+
+ - name: Assert Image Share Group information
+ assert:
+ that:
+ - share_group_info.image_share_group.label == "ansible-test-" ~ r
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_create.image_share_group.label }}'
+ state: absent
+
+ 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/image_share_group_list/tasks/main.yaml b/tests/integration/targets/image_share_group_list/tasks/main.yaml
new file mode 100644
index 00000000..dfaf93b1
--- /dev/null
+++ b/tests/integration/targets/image_share_group_list/tasks/main.yaml
@@ -0,0 +1,156 @@
+- name: image_share_group_list
+ block:
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+ disallowed_image_regions: [ "gb-lon", "au-mel", "sg-sin-2", "jp-tyo-3", "no-osl-1" ]
+
+ - name: List regions
+ linode.cloud.region_list: { }
+ register: all_regions
+
+ - set_fact:
+ capable_regions: '{{ ( all_regions.regions | selectattr("site_type", "equalto", "core") | selectattr("capabilities", "search", "Object Storage") | rejectattr("id", "in", disallowed_image_regions) | map(attribute="id") | list) }}'
+
+ - name: Create an instance to image
+ linode.cloud.instance:
+ label: 'ansible-test-{{ r }}'
+ region: '{{ capable_regions[1] }}'
+ type: g6-standard-1
+ image: linode/alpine3.19
+ state: present
+ firewall_id: '{{ firewall_id }}'
+ register: instance_create
+
+ - name: Create an image
+ linode.cloud.image:
+ disk_id: "{{ instance_create.disks.0.id }}"
+ label: 'ansible-test-{{ r }}'
+ state: present
+ register: image_create
+
+ - name: Create an image share group
+ linode.cloud.image_share_group:
+ label: 'ansible-test-{{ r }}-one'
+ images:
+ - id: '{{ image_create.image.id }}'
+ state: present
+ register: share_group_one_create
+
+ - name: Create another image share group
+ linode.cloud.image_share_group:
+ label: 'ansible-test-{{ r }}-two'
+ images:
+ - id: '{{ image_create.image.id }}'
+ state: present
+ register: share_group_two_create
+
+ - name: Create another image share group
+ linode.cloud.image_share_group:
+ label: 'ansible-test-{{ r }}-three'
+ state: present
+ register: share_group_three_create
+
+ - name: List Image Share Groups with no filter
+ linode.cloud.image_share_group_list:
+ count: 3
+ register: no_filter
+
+ - name: Assert image_share_group_list with no filter
+ assert:
+ that:
+ - no_filter.image_share_groups | length == 3
+
+ - name: List Image Share Groups with filter on label
+ linode.cloud.image_share_group_list:
+ count: 1
+ order_by: created
+ order: desc
+ filters:
+ - name: label
+ values: 'ansible-test-{{ r }}-one'
+ register: filter
+
+ - name: Assert image_share_group_list with filter on label
+ assert:
+ that:
+ - filter.image_share_groups | length == 1
+ - filter.image_share_groups[0].label == "ansible-test-" ~ r ~ "-one"
+
+ - name: List Image Share Groups by Image ID with no filter
+ linode.cloud.image_share_group_list:
+ count: 2
+ order_by: created
+ order: desc
+ image_id: '{{ image_create.image.id }}'
+ register: by_image_id_no_filter
+
+ - name: Assert image_share_group_list by Image ID with no filter
+ assert:
+ that:
+ - by_image_id_no_filter.image_share_groups | length == 2
+
+ - name: List Image Share Groups by Image ID with filter on label
+ linode.cloud.image_share_group_list:
+ count: 1
+ order_by: created
+ order: desc
+ image_id: '{{ image_create.image.id }}'
+ filters:
+ - name: label
+ values: 'ansible-test-{{ r }}-one'
+ register: by_image_id_filter
+
+ - name: Assert image_share_group_list by Image ID with filter on label
+ assert:
+ that:
+ - by_image_id_filter.image_share_groups | length == 1
+ - by_image_id_filter.image_share_groups[0].label == "ansible-test-" ~ r ~ "-one"
+
+ - name: Remove remaining images in share group one
+ linode.cloud.image_share_group:
+ label: '{{ share_group_one_create.image_share_group.label }}'
+ images: []
+ state: present
+ register: share_group_one_empty
+
+ - name: Remove remaining images in share group two
+ linode.cloud.image_share_group:
+ label: '{{ share_group_two_create.image_share_group.label }}'
+ images: [ ]
+ state: present
+ register: share_group_two_empty
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image
+ linode.cloud.image:
+ label: '{{ image_create.image.label }}'
+ state: absent
+
+ - name: Delete instance
+ linode.cloud.instance:
+ label: '{{ instance_create.instance.label }}'
+ state: absent
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_one_create.image_share_group.label }}'
+ state: absent
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_two_create.image_share_group.label }}'
+ state: absent
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: '{{ share_group_three_create.image_share_group.label }}'
+ state: absent
+
+ 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 "" }}'
diff --git a/tests/integration/targets/image_share_group_member/tasks/main.yaml b/tests/integration/targets/image_share_group_member/tasks/main.yaml
new file mode 100644
index 00000000..32850727
--- /dev/null
+++ b/tests/integration/targets/image_share_group_member/tasks/main.yaml
@@ -0,0 +1,102 @@
+- name: image_share_group_member
+ block:
+ - name: Normalize producer/consumer tokens
+ set_fact:
+ _producer_token: "{{ producer_api_token | default('', true) | trim }}"
+ _consumer_token: "{{ consumer_api_token | default('', true) | trim }}"
+
+ - name: Skip test if producer/consumer tokens are missing
+ meta: end_play
+ when: _producer_token == '' or _consumer_token == ''
+
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+
+ - name: Create image share group (producer task)
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ state: present
+ register: share_group_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Assert image share group is created
+ assert:
+ that:
+ - share_group_create.image_share_group.label == "ansible-test-" ~ r
+ - share_group_create.image_share_group.images_count == 0
+ - share_group_create.image_share_group.members_count == 0
+
+ - name: Create image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert image share group token is created
+ assert:
+ that:
+ - share_group_token_create.image_share_group_token.label == "ansible-test-" ~ r
+ - share_group_token_create.image_share_group_token.valid_for_sharegroup_uuid == share_group_create.image_share_group.uuid
+ - share_group_token_create.single_use_token is defined
+ - share_group_token_create.single_use_token | length > 0
+
+ - name: Add consumer as member to share group (producer task)
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}"
+ token: "{{ share_group_token_create.single_use_token }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: present
+ register: share_group_member_add
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Assert image share group member is added
+ assert:
+ that:
+ - share_group_member_add.image_share_group_member.label == "ansible-test-" ~ r
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group member
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create is defined
+ - share_group_token_create.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: "{{ share_group_create.image_share_group.label }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ environment:
+ LINODE_UA_PREFIX: "{{ ua_prefix }}"
+ LINODE_PRODUCER_API_TOKEN: "{{ producer_api_token }}"
+ LINODE_CONSUMER_API_TOKEN: "{{ consumer_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/image_share_group_member_info/tasks/main.yaml b/tests/integration/targets/image_share_group_member_info/tasks/main.yaml
new file mode 100644
index 00000000..ddad9ff0
--- /dev/null
+++ b/tests/integration/targets/image_share_group_member_info/tasks/main.yaml
@@ -0,0 +1,108 @@
+- name: image_share_group_member_info
+ block:
+ - name: Normalize producer/consumer tokens
+ set_fact:
+ _producer_token: "{{ producer_api_token | default('', true) | trim }}"
+ _consumer_token: "{{ consumer_api_token | default('', true) | trim }}"
+
+ - name: Skip test if producer/consumer tokens are missing
+ meta: end_play
+ when: _producer_token == '' or _consumer_token == ''
+
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+
+ - name: Create image share group (producer task)
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ state: present
+ register: share_group_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Add consumer as member to share group (producer task)
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}"
+ token: "{{ share_group_token_create.single_use_token }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: present
+ register: share_group_member_add
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Get information about the Image Share Group Member by label
+ linode.cloud.image_share_group_member_info:
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ label: "{{ share_group_member_add.image_share_group_member.label }}"
+ register: share_group_member_info_label
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Assert Image Share Group Member information
+ assert:
+ that:
+ - share_group_member_info_label.image_share_group_member.label == "ansible-test-" ~ r
+
+ - name: Get information about the Image Share Group Member by token_uuid
+ linode.cloud.image_share_group_member_info:
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ token_uuid: "{{ share_group_member_add.image_share_group_member.token_uuid }}"
+ register: share_group_member_info_token_uuid
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Assert Image Share Group Member information
+ assert:
+ that:
+ - share_group_member_info_token_uuid.image_share_group_member.label == "ansible-test-" ~ r
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group member
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create is defined
+ - share_group_token_create.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: "{{ share_group_create.image_share_group.label }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ environment:
+ LINODE_UA_PREFIX: "{{ ua_prefix }}"
+ LINODE_PRODUCER_API_TOKEN: "{{ producer_api_token }}"
+ LINODE_CONSUMER_API_TOKEN: "{{ consumer_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/image_share_group_member_list/tasks/main.yaml b/tests/integration/targets/image_share_group_member_list/tasks/main.yaml
new file mode 100644
index 00000000..cd2166ad
--- /dev/null
+++ b/tests/integration/targets/image_share_group_member_list/tasks/main.yaml
@@ -0,0 +1,154 @@
+- name: image_share_group_member_list
+ block:
+ - name: Normalize producer/consumer tokens
+ set_fact:
+ _producer_token: "{{ producer_api_token | default('', true) | trim }}"
+ _consumer_token: "{{ consumer_api_token | default('', true) | trim }}"
+
+ - name: Skip test if producer/consumer tokens are missing
+ meta: end_play
+ when: _producer_token == '' or _consumer_token == ''
+
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+
+ - name: Create image share group (producer task)
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ state: present
+ register: share_group_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}-one"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create_one
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Create another image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}-two"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create_two
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Add consumer as member to share group (producer task)
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}-one"
+ token: "{{ share_group_token_create_one.single_use_token }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: present
+ register: share_group_member_add_one
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Add consumer as member to share group (producer task)
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}-two"
+ token: "{{ share_group_token_create_two.single_use_token }}"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: present
+ register: share_group_member_add_two
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: List image share group members with no filter
+ linode.cloud.image_share_group_member_list:
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ count: 2
+ register: no_filter
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Assert image_share_group_member_list with no filter
+ assert:
+ that:
+ - no_filter.image_share_group_members | length == 2
+
+ - name: List image share group members with filter on label
+ linode.cloud.image_share_group_member_list:
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ count: 1
+ order_by: created
+ order: desc
+ filters:
+ - name: label
+ values: 'ansible-test-{{ r }}-two'
+ register: filter
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Assert image_share_group_member_list with filter on label
+ assert:
+ that:
+ - filter.image_share_group_members | length == 1
+ - filter.image_share_group_members[0].label == "ansible-test-" ~ r ~ "-two"
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group member
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}-one"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete image share group member
+ linode.cloud.image_share_group_member:
+ label: "ansible-test-{{ r }}-two"
+ sharegroup_id: "{{ share_group_create.image_share_group.id }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create_one.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create_one is defined
+ - share_group_token_create_one.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create_two.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create_two is defined
+ - share_group_token_create_two.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: "{{ share_group_create.image_share_group.label }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ environment:
+ LINODE_UA_PREFIX: "{{ ua_prefix }}"
+ LINODE_PRODUCER_API_TOKEN: "{{ producer_api_token }}"
+ LINODE_CONSUMER_API_TOKEN: "{{ consumer_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/image_share_group_token/tasks/main.yaml b/tests/integration/targets/image_share_group_token/tasks/main.yaml
new file mode 100644
index 00000000..07bad84b
--- /dev/null
+++ b/tests/integration/targets/image_share_group_token/tasks/main.yaml
@@ -0,0 +1,92 @@
+- name: image_share_group_token
+ block:
+ - name: Normalize producer/consumer tokens
+ set_fact:
+ _producer_token: "{{ producer_api_token | default('', true) | trim }}"
+ _consumer_token: "{{ consumer_api_token | default('', true) | trim }}"
+
+ - name: Skip test if producer/consumer tokens are missing
+ meta: end_play
+ when: _producer_token == '' or _consumer_token == ''
+
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+
+ - name: Create image share group (producer task)
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ state: present
+ register: share_group_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Assert image share group is created
+ assert:
+ that:
+ - share_group_create.image_share_group.label == "ansible-test-" ~ r
+ - share_group_create.image_share_group.images_count == 0
+ - share_group_create.image_share_group.members_count == 0
+
+ - name: Create image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert image share group token is created
+ assert:
+ that:
+ - share_group_token_create.image_share_group_token.label == "ansible-test-" ~ r
+ - share_group_token_create.image_share_group_token.valid_for_sharegroup_uuid == share_group_create.image_share_group.uuid
+ - share_group_token_create.single_use_token is defined
+ - share_group_token_create.single_use_token | length > 0
+
+ - name: Attempt to update image share group token with modified share group UUID (should fail)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}x"
+ state: present
+ register: share_group_token_update_attempt
+ failed_when: false
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert image share group token update fails for non-mutable field
+ assert:
+ that:
+ - share_group_token_update_attempt.msg is defined
+ - "'non-updatable field' in share_group_token_update_attempt.msg"
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create is defined
+ - share_group_token_create.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: "{{ share_group_create.image_share_group.label }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ environment:
+ LINODE_UA_PREFIX: "{{ ua_prefix }}"
+ LINODE_PRODUCER_API_TOKEN: "{{ producer_api_token }}"
+ LINODE_CONSUMER_API_TOKEN: "{{ consumer_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/image_share_group_token_info/tasks/main.yaml b/tests/integration/targets/image_share_group_token_info/tasks/main.yaml
new file mode 100644
index 00000000..940a6c91
--- /dev/null
+++ b/tests/integration/targets/image_share_group_token_info/tasks/main.yaml
@@ -0,0 +1,85 @@
+- name: image_share_group_token_info
+ block:
+ - name: Normalize producer/consumer tokens
+ set_fact:
+ _producer_token: "{{ producer_api_token | default('', true) | trim }}"
+ _consumer_token: "{{ consumer_api_token | default('', true) | trim }}"
+
+ - name: Skip test if producer/consumer tokens are missing
+ meta: end_play
+ when: _producer_token == '' or _consumer_token == ''
+
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+
+ - name: Create image share group (producer task)
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ state: present
+ register: share_group_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Get information about the Image Share Group Token by label
+ linode.cloud.image_share_group_token_info:
+ label: "{{ share_group_token_create.image_share_group_token.label }}"
+ register: share_group_token_info_label
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert Image Share Group Token information
+ assert:
+ that:
+ - share_group_token_info_label.image_share_group_token.label == "ansible-test-" ~ r
+
+ - name: Get information about the Image Share Group Token by Token UUID
+ linode.cloud.image_share_group_token_info:
+ token_uuid: "{{ share_group_token_create.image_share_group_token.token_uuid }}"
+ register: share_group_token_info_token_uuid
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert Image Share Group Token information
+ assert:
+ that:
+ - share_group_token_info_token_uuid.image_share_group_token.label == "ansible-test-" ~ r
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create is defined
+ - share_group_token_create.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: "{{ share_group_create.image_share_group.label }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ environment:
+ LINODE_UA_PREFIX: "{{ ua_prefix }}"
+ LINODE_PRODUCER_API_TOKEN: "{{ producer_api_token }}"
+ LINODE_CONSUMER_API_TOKEN: "{{ consumer_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/image_share_group_token_list/tasks/main.yaml b/tests/integration/targets/image_share_group_token_list/tasks/main.yaml
new file mode 100644
index 00000000..416e5066
--- /dev/null
+++ b/tests/integration/targets/image_share_group_token_list/tasks/main.yaml
@@ -0,0 +1,110 @@
+- name: image_share_group_token_list
+ block:
+ - name: Normalize producer/consumer tokens
+ set_fact:
+ _producer_token: "{{ producer_api_token | default('', true) | trim }}"
+ _consumer_token: "{{ consumer_api_token | default('', true) | trim }}"
+
+ - name: Skip test if producer/consumer tokens are missing
+ meta: end_play
+ when: _producer_token == '' or _consumer_token == ''
+
+ - set_fact:
+ r: "{{ 1000000000 | random }}"
+
+ - name: Create image share group (producer task)
+ linode.cloud.image_share_group:
+ label: "ansible-test-{{ r }}"
+ state: present
+ register: share_group_create
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ - name: Create image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}-one"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create_one
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Create another image share group token (consumer task)
+ linode.cloud.image_share_group_token:
+ label: "ansible-test-{{ r }}-two"
+ valid_for_sharegroup_uuid: "{{ share_group_create.image_share_group.uuid }}"
+ state: present
+ register: share_group_token_create_two
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: List Image Share Group Tokens with no filter
+ linode.cloud.image_share_group_token_list:
+ count: 2
+ register: no_filter
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert image_share_group_token_list with no filter
+ assert:
+ that:
+ - no_filter.image_share_group_tokens | length == 2
+
+ - name: List Image Share Group Tokens with filter on label
+ linode.cloud.image_share_group_token_list:
+ count: 1
+ order_by: created
+ order: desc
+ filters:
+ - name: label
+ values: 'ansible-test-{{ r }}-one'
+ register: filter
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Assert image_share_group_token_list with filter on label
+ assert:
+ that:
+ - filter.image_share_group_tokens | length == 1
+ - filter.image_share_group_tokens[0].label == "ansible-test-" ~ r ~ "-one"
+
+ always:
+ - ignore_errors: yes
+ block:
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create_one.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create_one is defined
+ - share_group_token_create_one.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group token
+ linode.cloud.image_share_group_token:
+ label: "{{ share_group_token_create_two.image_share_group_token.label }}"
+ state: absent
+ when:
+ - share_group_token_create_two is defined
+ - share_group_token_create_two.image_share_group_token is defined
+ environment:
+ LINODE_API_TOKEN: "{{ consumer_api_token }}"
+
+ - name: Delete image share group
+ linode.cloud.image_share_group:
+ label: "{{ share_group_create.image_share_group.label }}"
+ state: absent
+ when:
+ - share_group_create is defined
+ - share_group_create.image_share_group is defined
+ environment:
+ LINODE_API_TOKEN: "{{ producer_api_token }}"
+
+ environment:
+ LINODE_UA_PREFIX: "{{ ua_prefix }}"
+ LINODE_PRODUCER_API_TOKEN: "{{ producer_api_token }}"
+ LINODE_CONSUMER_API_TOKEN: "{{ consumer_api_token }}"
+ LINODE_API_URL: "{{ api_url }}"
+ LINODE_API_VERSION: "{{ api_version }}"
+ LINODE_CA: "{{ ca_file or '' }}"
\ No newline at end of file