diff --git a/README.md b/README.md index 9fd273d9..321eba22 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Name | Description | [linode.cloud.ip_share](./docs/modules/ip_share.md)|Manage the Linode shared IPs.| [linode.cloud.lke_cluster](./docs/modules/lke_cluster.md)|Manage Linode LKE clusters.| [linode.cloud.lke_node_pool](./docs/modules/lke_node_pool.md)|Manage Linode LKE cluster node pools.| +[linode.cloud.monitor_services_alert_definition](./docs/modules/monitor_services_alert_definition.md)|Manage an alert definition for a specific service type. Akamai refers to these as user alerts. You need read_only access to the scope for the selected serviceType. | [linode.cloud.nodebalancer](./docs/modules/nodebalancer.md)|Manage a Linode NodeBalancer.| [linode.cloud.nodebalancer_node](./docs/modules/nodebalancer_node.md)|Manage Linode NodeBalancer Nodes.| [linode.cloud.nodebalancer_stats](./docs/modules/nodebalancer_stats.md)|Get info about a Linode Node Balancer Stats.| @@ -80,6 +81,7 @@ Name | Description | [linode.cloud.ipv6_range_info](./docs/modules/ipv6_range_info.md)|Get info about a Linode IPv6 range.| [linode.cloud.lke_cluster_info](./docs/modules/lke_cluster_info.md)|Get info about a Linode LKE cluster.| [linode.cloud.lke_version_info](./docs/modules/lke_version_info.md)|Get info about a Linode LKE Version.| +[linode.cloud.monitor_services_alert_definition_info](./docs/modules/monitor_services_alert_definition_info.md)|Get info about a Linode Alert Definition.| [linode.cloud.nodebalancer_info](./docs/modules/nodebalancer_info.md)|Get info about a Linode Node Balancer.| [linode.cloud.object_cluster_info](./docs/modules/object_cluster_info.md)|**NOTE: This module has been deprecated because it relies on deprecated API endpoints. Going forward, `region` will be the preferred way to designate where Object Storage resources should be created.**| [linode.cloud.object_storage_quota_info](./docs/modules/object_storage_quota_info.md)|Get info about a Linode Object Storage Quota.| @@ -118,6 +120,9 @@ Name | Description | [linode.cloud.lke_type_list](./docs/modules/lke_type_list.md)|List and filter on LKE Types.| [linode.cloud.lke_version_list](./docs/modules/lke_version_list.md)|List and filter on LKE Versions.| [linode.cloud.maintenance_policy_list](./docs/modules/maintenance_policy_list.md)|List and filter on Maintenance Policies.| +[linode.cloud.monitor_alert_channel_list](./docs/modules/monitor_alert_channel_list.md)|List and filter on Alert Channels.| +[linode.cloud.monitor_services_alert_definition_by_service_type_list](./docs/modules/monitor_services_alert_definition_by_service_type_list.md)|The return alert definitions by service type. **Note: filters and order are currently NOT supported by this endpoint.| +[linode.cloud.monitor_services_alert_definition_list](./docs/modules/monitor_services_alert_definition_list.md)|List and filter on Alert Definitions.| [linode.cloud.network_transfer_prices_list](./docs/modules/network_transfer_prices_list.md)|List and filter on Network Transfer Prices.| [linode.cloud.nodebalancer_list](./docs/modules/nodebalancer_list.md)|List and filter on Node Balancers.| [linode.cloud.nodebalancer_type_list](./docs/modules/nodebalancer_type_list.md)|List and filter on Node Balancer Types.| diff --git a/docs/modules/monitor_alert_channel_list.md b/docs/modules/monitor_alert_channel_list.md new file mode 100644 index 00000000..0d4d84af --- /dev/null +++ b/docs/modules/monitor_alert_channel_list.md @@ -0,0 +1,85 @@ +# monitor_alert_channel_list + +List and filter on Alert Channels. + +WARNING! This module makes use of beta endpoints and requires the C(api_version) field be explicitly set to C(v4beta). + +- [Minimum Required Fields](#minimum-required-fields) +- [Examples](#examples) +- [Parameters](#parameters) +- [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 available alert channels to the account + linode.cloud.monitor_alert_channel_list: + api_version: v4beta +``` + + +## Parameters + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `order` |
`str`
|
Optional
| The order to list Alert Channels in. **(Choices: `desc`, `asc`; Default: `asc`)** | +| `order_by` |
`str`
|
Optional
| The attribute to order Alert Channels by. | +| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting Alert Channels. | +| `count` |
`int`
|
Optional
| The number of Alert Channels 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-alert-channels). | +| `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 + +- `alert_channels` - The returned Alert Channels. + + - Sample Response: + ```json + [ + { + "alerts": [ + { + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "type": "alerts-definitions", + "url": "/monitor/alerts-definitions/10000" + }, + { + "id": 10001, + "label": "High Memory Usage Plan Shared", + "type": "alerts-definitions", + "url": "/monitor/alerts-definitions/10001" + } + ], + "channel_type": "email", + "content": { + "email": { + "email_addresses": [ + "Users-with-read-write-access-to-resources" + ] + } + }, + "created": "2025-03-20T01:41:09", + "created_by": "system", + "id": 10000, + "label": "Read-Write Channel", + "type": "system", + "updated": "2025-03-20T01:41:09", + "updated_by": "system" + } + ] + + ``` + - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-alert-channels) for a list of returned fields + + diff --git a/docs/modules/monitor_services_alert_definition.md b/docs/modules/monitor_services_alert_definition.md new file mode 100644 index 00000000..f1a9ef9e --- /dev/null +++ b/docs/modules/monitor_services_alert_definition.md @@ -0,0 +1,174 @@ +# monitor_services_alert_definition + +Manage an alert definition for a specific service type. Akamai refers to these as user alerts. You need read_only access to the scope for the selected serviceType. + +- [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 alert definition for a service type (dbaas) + linode.cloud.monitor_services_alert_definition: + service_type: 'dbaas' + description: 'An alert definition for ansible test.' + label: 'ansible-test' + severity: 1 + rule_criteria: + rules: + - aggregate_function: 'avg' + dimension_filters: + - dimension_label: 'node_type' + label: 'Node Type' + operator: 'eq' + value: 'primary' + label: 'Memory Usage' + metric: 'memory_usage' + operator: 'gt' + threshold: 90 + unit: 'percent' + trigger_conditions: + criteria_condition: 'ALL' + evaluation_period_seconds: 300 + polling_interval_seconds: 300 + trigger_occurrences: 1 + channel_ids: '{{ alert_channels }}' + state: present +``` + +```yaml +- name: Delete alert definition + linode.cloud.monitor_services_alert_definition: + service_type: 'dbaas' + id: 123 + state: absent + register: delete +``` + + +## Parameters + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `service_type` |
`str`
|
**Required**
| The Akamai Cloud Computing service being monitored. | +| `channel_ids` |
`list`
|
**Required**
| The identifiers for the alert channels to use for the alert. Run the List alert channels operation and store the id for the applicable channels. **(Updatable)** | +| `label` |
`str`
|
**Required**
| The name of the alert definition. This is used for display purposes in Akamai Cloud Manager. **(Updatable)** | +| [`rule_criteria` (sub-options)](#rule_criteria) |
`dict`
|
**Required**
| Details for the rules required to trigger the alert. **(Updatable)** | +| `severity` |
`int`
|
**Required**
| The severity of the alert. Supported values include 3 for info, 2 for low, 1 for medium, and 0 for severe. **(Choices: `0`, `1`, `2`, `3`; Updatable)** | +| [`trigger_conditions` (sub-options)](#trigger_conditions) |
`dict`
|
**Required**
| The conditions that need to be met to send a notification for the alert. **(Updatable)** | +| `state` |
`str`
|
**Required**
| The desired state of the target. **(Choices: `present`, `absent`)** | +| `description` |
`str`
|
Optional
| An additional description for the alert definition. **(Updatable)** | +| `entity_ids` |
`list`
|
Optional
| The id for each individual entity from a service_type. Get this value by running the list operation for the appropriate entity. For example, if your entity is one of your PostgreSQL databases, run the List PostgreSQL Managed Databases operation and store the id for the appropriate database from the response. You also need read_only access to the scope for the service_type for each of the entity_ids. **(Updatable)** | +| `id` |
`int`
|
Optional
| The unique identifier assigned to the alert definition. Run the List alert definitions operation and store the id for the applicable alert definition. Required for updating. | +| `status` |
`str`
|
Optional
| The current status of the alert. **(Choices: `enabled`, `disabled`; Updatable)** | +| `wait` |
`bool`
|
Optional
| Wait for the alert definition ready (not in progress). **(Default: `False`)** | +| `wait_timeout` |
`int`
|
Optional
| The amount of time, in seconds, to wait for the alert definition. **(Default: `600`)** | + +### rule_criteria + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| [`rules` (sub-options)](#rules) |
`list`
|
Optional
| The individual rules that make up the alert definition. | + +### rules + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `aggregate_function` |
`str`
|
Optional
| The aggregation function applied to the metric. **(Choices: `avg`, `sum`, `min`, `max`)** | +| [`dimension_filters` (sub-options)](#dimension_filters) |
`list`
|
Optional
| Individual objects that define dimension filters for the rule. | +| `metric` |
`str`
|
Optional
| The metric to query. | +| `operator` |
`str`
|
Optional
| The operator to apply to the metric. Available values are eq for equal, gt for greater than, lt for less than, gte for greater than or equal, and lte for less than or equal. **(Choices: `eq`, `gt`, `lt`, `gte`, `lte`)** | +| `threshold` |
`float`
|
Optional
| The predefined value or condition that triggers an alert when met or exceeded. | + +### dimension_filters + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `dimension_label` |
`str`
|
Optional
| The name of the dimension to be used in the filter. | +| `operator` |
`str`
|
Optional
| The operator to apply to the dimension filter. Available values are eq for equal, neq for not equal, startswith, and endswith. **(Choices: `eq`, `neq`, `startswith`, `endswith`)** | +| `value` |
`str`
|
Optional
| The value to compare the dimension_label against. | + +### trigger_conditions + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `criteria_condition` |
`str`
|
Optional
| Signifies the logical operation applied when multiple metrics are set for an alert definition. For example, if you wanted to apply both cpu_usage > 90 and memory_usage > 80, ALL is the criteria_condition. Currently, only ALL is supported. **(Choices: `ALL`)** | +| `evaluation_period_seconds` |
`int`
|
Optional
| The time period over which data is collected before evaluating whether the alert definition's threshold has been met or exceeded. | +| `polling_interval_seconds` |
`int`
|
Optional
| The frequency at which the metric is checked for a change in state. For example, with cpu_usage set as your metric and this set to 300, your cpu_usage is checked every 5 minutes for some change in its state. | +| `trigger_occurrences` |
`int`
|
Optional
| The minimum number of consecutive polling_interval_seconds periods that the threshold needs to be breached to trigger the alert. | + +## Return Values + +- `alert_definition` - The alert definition in JSON serialized form. + + - Sample Response: + ```json + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": "dedicated", + "created": "2025-03-20T01:42:11", + "created_by": "system", + "description": "Alert triggers when dedicated plan nodes consistently reach critical memory usage, risking application performance degradation.", + "entity_ids": [ + "126905", + "126906", + "137435", + "141496", + "190003", + "257625", + "257626" + ], + "has_more_resources": false, + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "system", + "updated": "2025-03-20T01:42:11", + "updated_by": "system" + } + ``` + - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-alert-definition) for a list of returned fields + + diff --git a/docs/modules/monitor_services_alert_definition_by_service_type_list.md b/docs/modules/monitor_services_alert_definition_by_service_type_list.md new file mode 100644 index 00000000..6e7c05a5 --- /dev/null +++ b/docs/modules/monitor_services_alert_definition_by_service_type_list.md @@ -0,0 +1,162 @@ +# monitor_services_alert_definition_by_service_type_list + +The return alert definitions by service type. **Note: filters and order are currently NOT supported by this endpoint. + +WARNING! This module makes use of beta endpoints and requires the C(api_version) field be explicitly set to C(v4beta). + +- [Minimum Required Fields](#minimum-required-fields) +- [Examples](#examples) +- [Parameters](#parameters) +- [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 available alert definitions by service type to the account + linode.cloud.monitor_services_alert_definition_by_service_type_list: + service_type: dbaas + api_version: v4beta +``` + + +## Parameters + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `service_type` |
`str`
|
**Required**
| The parent Service Type for the Alert Definitions. | +| `count` |
`int`
|
Optional
| The number of Alert Definitions to return. If undefined, all results will be returned. | + +## Return Values + +- `alert_definitions` - The returned Alert Definitions. + + - Sample Response: + ```json + [ + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": "dedicated", + "created": "2025-03-20T01:42:11", + "created_by": "system", + "description": "Alert triggers when dedicated plan nodes consistently reach critical memory usage, risking application performance degradation.", + "entity_ids": [ + "126905", + "126906", + "137435", + "141496", + "190003", + "257625", + "257626" + ], + "has_more_resources": false, + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "system", + "updated": "2025-03-20T01:42:11", + "updated_by": "system" + }, + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": null, + "created": "2025-03-20T02:15:18", + "created_by": "John Q. Linode", + "description": "Custom alert set up for high memory usage for shared plan nodes.", + "entity_ids": [ + "126907", + "126908", + "137436", + "141497", + "190004", + "257627", + "257628" + ], + "has_more_resources": false, + "id": 10001, + "label": "High Memory Usage Plan Shared", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "user", + "updated": "2025-03-20T02:15:18", + "updated_by": "John Q. Linode" + } + ] + + ``` + - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-alert-definitions-for-service-type) for a list of returned fields + + diff --git a/docs/modules/monitor_services_alert_definition_info.md b/docs/modules/monitor_services_alert_definition_info.md new file mode 100644 index 00000000..e2c8075d --- /dev/null +++ b/docs/modules/monitor_services_alert_definition_info.md @@ -0,0 +1,99 @@ +# monitor_services_alert_definition_info + +Get info about a Linode Alert Definition. + +- [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 +- linode.cloud.monitor_services_alert_definition_info: + service_type: 'dbaas' + id: 12345 + api_version: v4beta +``` + + +## Parameters + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `service_type` |
`str`
|
**Required**
| The ID of the Service Type for this resource. | +| `id` |
`int`
|
**Required**
| The ID of the Alert Definition to resolve. | + +## Return Values + +- `alert_definition` - The returned Alert Definition. + + - Sample Response: + ```json + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": "dedicated", + "created": "2025-03-20T01:42:11", + "created_by": "system", + "description": "Alert triggers when dedicated plan nodes consistently reach critical memory usage, risking application performance degradation.", + "entity_ids": [ + "126905", + "126906", + "137435", + "141496", + "190003", + "257625", + "257626" + ], + "has_more_resources": false, + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "system", + "updated": "2025-03-20T01:42:11", + "updated_by": "system" + } + ``` + - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-alert-definition) for a list of returned fields + + diff --git a/docs/modules/monitor_services_alert_definition_list.md b/docs/modules/monitor_services_alert_definition_list.md new file mode 100644 index 00000000..fd650404 --- /dev/null +++ b/docs/modules/monitor_services_alert_definition_list.md @@ -0,0 +1,170 @@ +# monitor_services_alert_definition_list + +List and filter on Alert Definitions. + +WARNING! This module makes use of beta endpoints and requires the C(api_version) field be explicitly set to C(v4beta). + +- [Minimum Required Fields](#minimum-required-fields) +- [Examples](#examples) +- [Parameters](#parameters) +- [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 available alert definitions to the account + linode.cloud.monitor_services_alert_definition_list: + api_version: v4beta +``` + + +## Parameters + +| Field | Type | Required | Description | +|-----------|------|----------|------------------------------------------------------------------------------| +| `order` |
`str`
|
Optional
| The order to list Alert Definitions in. **(Choices: `desc`, `asc`; Default: `asc`)** | +| `order_by` |
`str`
|
Optional
| The attribute to order Alert Definitions by. | +| [`filters` (sub-options)](#filters) |
`list`
|
Optional
| A list of filters to apply to the resulting Alert Definitions. | +| `count` |
`int`
|
Optional
| The number of Alert Definitions 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-alert-definitions). | +| `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 + +- `alert_definitions` - The returned Alert Definitions. + + - Sample Response: + ```json + [ + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": "dedicated", + "created": "2025-03-20T01:42:11", + "created_by": "system", + "description": "Alert triggers when dedicated plan nodes consistently reach critical memory usage, risking application performance degradation.", + "entity_ids": [ + "126905", + "126906", + "137435", + "141496", + "190003", + "257625", + "257626" + ], + "has_more_resources": false, + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "system", + "updated": "2025-03-20T01:42:11", + "updated_by": "system" + }, + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": null, + "created": "2025-03-20T02:15:18", + "created_by": "John Q. Linode", + "description": "Custom alert set up for high memory usage for shared plan nodes.", + "entity_ids": [ + "126907", + "126908", + "137436", + "141497", + "190004", + "257627", + "257628" + ], + "has_more_resources": false, + "id": 10001, + "label": "High Memory Usage Plan Shared", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "user", + "updated": "2025-03-20T02:15:18", + "updated_by": "John Q. Linode" + } + ] + + ``` + - See the [Linode API response documentation](https://techdocs.akamai.com/linode-api/reference/get-alert-definitions) for a list of returned fields + + diff --git a/plugins/module_utils/doc_fragments/alert_channels_list.py b/plugins/module_utils/doc_fragments/alert_channels_list.py new file mode 100644 index 00000000..3ef3c7cc --- /dev/null +++ b/plugins/module_utils/doc_fragments/alert_channels_list.py @@ -0,0 +1,41 @@ +"""Documentation fragments for the monitor_alert_channel_list module""" + +specdoc_examples = [''' +- name: List all of available alert channels to the account + linode.cloud.monitor_alert_channel_list: + api_version: v4beta'''] + +result_alert_channels_samples = ['''[ + { + "alerts": [ + { + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "type": "alerts-definitions", + "url": "/monitor/alerts-definitions/10000" + }, + { + "id": 10001, + "label": "High Memory Usage Plan Shared", + "type": "alerts-definitions", + "url": "/monitor/alerts-definitions/10001" + } + ], + "channel_type": "email", + "content": { + "email": { + "email_addresses": [ + "Users-with-read-write-access-to-resources" + ] + } + }, + "created": "2025-03-20T01:41:09", + "created_by": "system", + "id": 10000, + "label": "Read-Write Channel", + "type": "system", + "updated": "2025-03-20T01:41:09", + "updated_by": "system" + } +] +'''] diff --git a/plugins/module_utils/doc_fragments/alert_definition.py b/plugins/module_utils/doc_fragments/alert_definition.py new file mode 100644 index 00000000..b5e76f93 --- /dev/null +++ b/plugins/module_utils/doc_fragments/alert_definition.py @@ -0,0 +1,94 @@ +"""Documentation fragments for the monitor_services_alert_definition module""" + +specdoc_examples = [''' +- name: Create an alert definition for a service type (dbaas) + linode.cloud.monitor_services_alert_definition: + service_type: 'dbaas' + description: 'An alert definition for ansible test.' + label: 'ansible-test' + severity: 1 + rule_criteria: + rules: + - aggregate_function: 'avg' + dimension_filters: + - dimension_label: 'node_type' + label: 'Node Type' + operator: 'eq' + value: 'primary' + label: 'Memory Usage' + metric: 'memory_usage' + operator: 'gt' + threshold: 90 + unit: 'percent' + trigger_conditions: + criteria_condition: 'ALL' + evaluation_period_seconds: 300 + polling_interval_seconds: 300 + trigger_occurrences: 1 + channel_ids: '{{ alert_channels }}' + state: present''', ''' +- name: Delete alert definition + linode.cloud.monitor_services_alert_definition: + service_type: 'dbaas' + id: 123 + state: absent + register: delete'''] + +result_aclp_alert_definition_sample = ['''{ + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": "dedicated", + "created": "2025-03-20T01:42:11", + "created_by": "system", + "description": "Alert triggers when dedicated plan nodes consistently reach critical memory usage, risking application performance degradation.", + "entity_ids": [ + "126905", + "126906", + "137435", + "141496", + "190003", + "257625", + "257626" + ], + "has_more_resources": false, + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "system", + "updated": "2025-03-20T01:42:11", + "updated_by": "system" +}'''] diff --git a/plugins/module_utils/doc_fragments/alert_definition_info.py b/plugins/module_utils/doc_fragments/alert_definition_info.py new file mode 100644 index 00000000..4a8acd7e --- /dev/null +++ b/plugins/module_utils/doc_fragments/alert_definition_info.py @@ -0,0 +1,66 @@ +"""Documentation fragments for the monitor_services_alert_definition_info module""" + +specdoc_examples = [''' +- linode.cloud.monitor_services_alert_definition_info: + service_type: 'dbaas' + id: 12345 + api_version: v4beta'''] + +result_alert_definition_samples = ['''{ + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": "dedicated", + "created": "2025-03-20T01:42:11", + "created_by": "system", + "description": "Alert triggers when dedicated plan nodes consistently reach critical memory usage, risking application performance degradation.", + "entity_ids": [ + "126905", + "126906", + "137435", + "141496", + "190003", + "257625", + "257626" + ], + "has_more_resources": false, + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "system", + "updated": "2025-03-20T01:42:11", + "updated_by": "system" +}'''] diff --git a/plugins/module_utils/doc_fragments/alert_definitions_by_service_type_list.py b/plugins/module_utils/doc_fragments/alert_definitions_by_service_type_list.py new file mode 100644 index 00000000..e9a22018 --- /dev/null +++ b/plugins/module_utils/doc_fragments/alert_definitions_by_service_type_list.py @@ -0,0 +1,127 @@ +"""Documentation fragments for the alert_definitions_by_service_type_list module""" + +specdoc_examples = [''' +- name: List all of available alert definitions by service type to the account + linode.cloud.monitor_services_alert_definition_by_service_type_list: + service_type: dbaas + api_version: v4beta'''] + +result_alert_definitions_by_service_type_samples = ['''[ + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": "dedicated", + "created": "2025-03-20T01:42:11", + "created_by": "system", + "description": "Alert triggers when dedicated plan nodes consistently reach critical memory usage, risking application performance degradation.", + "entity_ids": [ + "126905", + "126906", + "137435", + "141496", + "190003", + "257625", + "257626" + ], + "has_more_resources": false, + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "system", + "updated": "2025-03-20T01:42:11", + "updated_by": "system" + }, + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": null, + "created": "2025-03-20T02:15:18", + "created_by": "John Q. Linode", + "description": "Custom alert set up for high memory usage for shared plan nodes.", + "entity_ids": [ + "126907", + "126908", + "137436", + "141497", + "190004", + "257627", + "257628" + ], + "has_more_resources": false, + "id": 10001, + "label": "High Memory Usage Plan Shared", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "user", + "updated": "2025-03-20T02:15:18", + "updated_by": "John Q. Linode" + } + ] +'''] diff --git a/plugins/module_utils/doc_fragments/alert_definitions_list.py b/plugins/module_utils/doc_fragments/alert_definitions_list.py new file mode 100644 index 00000000..5527b52e --- /dev/null +++ b/plugins/module_utils/doc_fragments/alert_definitions_list.py @@ -0,0 +1,126 @@ +"""Documentation fragments for the monitor_services_alert_definition_list module""" + +specdoc_examples = [''' +- name: List all of available alert definitions to the account + linode.cloud.monitor_services_alert_definition_list: + api_version: v4beta'''] + +result_alert_definitions_samples = ['''[ + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": "dedicated", + "created": "2025-03-20T01:42:11", + "created_by": "system", + "description": "Alert triggers when dedicated plan nodes consistently reach critical memory usage, risking application performance degradation.", + "entity_ids": [ + "126905", + "126906", + "137435", + "141496", + "190003", + "257625", + "257626" + ], + "has_more_resources": false, + "id": 10000, + "label": "High Memory Usage Plan Dedicated", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "system", + "updated": "2025-03-20T01:42:11", + "updated_by": "system" + }, + { + "alert_channels": [ + { + "id": 10000, + "label": "Read-Write Channel", + "type": "alert-channels", + "url": "/monitor/alert-channels/10000" + } + ], + "class": null, + "created": "2025-03-20T02:15:18", + "created_by": "John Q. Linode", + "description": "Custom alert set up for high memory usage for shared plan nodes.", + "entity_ids": [ + "126907", + "126908", + "137436", + "141497", + "190004", + "257627", + "257628" + ], + "has_more_resources": false, + "id": 10001, + "label": "High Memory Usage Plan Shared", + "rule_criteria": { + "rules": [ + { + "aggregate_function": "avg", + "dimension_filters": [ + { + "dimension_label": "node_type", + "label": "Node Type", + "operator": "eq", + "value": "primary" + } + ], + "label": "Memory Usage", + "metric": "memory_usage", + "operator": "gt", + "threshold": 95, + "unit": "percent" + } + ] + }, + "service_type": "dbaas", + "severity": 2, + "status": "enabled", + "trigger_conditions": { + "criteria_condition": "ALL", + "evaluation_period_seconds": 300, + "polling_interval_seconds": 300, + "trigger_occurrences": 3 + }, + "type": "user", + "updated": "2025-03-20T02:15:18", + "updated_by": "John Q. Linode" + } + ] +'''] diff --git a/plugins/module_utils/linode_common_list.py b/plugins/module_utils/linode_common_list.py index e89e6d59..d27b4286 100644 --- a/plugins/module_utils/linode_common_list.py +++ b/plugins/module_utils/linode_common_list.py @@ -58,6 +58,7 @@ def __init__( result_samples: List[str] = None, requires_beta: bool = False, deprecated: bool = False, + disable_filters: bool = False, deprecation_message: Optional[str] = None, custom_options: Optional[Dict[str, SpecField]] = None, custom_field_resolver: Optional[callable] = None, @@ -91,6 +92,7 @@ def __init__( # Store custom options if provided self.custom_options = custom_options or {} + self.disable_filters = disable_filters self.module_arg_spec = self.spec.ansible_spec self.results: Dict[str, Any] = {self.result_field_name: []} @@ -108,9 +110,13 @@ def exec_module(self, **kwargs: Any) -> Optional[dict]: # Use custom API filter constructor if provided filter_dict = ( - self.custom_api_filter_constructor(self.module.params) - if self.custom_api_filter_constructor - else construct_api_filter(self.module.params) + ( + self.custom_api_filter_constructor(self.module.params) + if self.custom_api_filter_constructor + else construct_api_filter(self.module.params) + ) + if not self.disable_filters + else None ) # Dynamically resolve fields if custom logic is provided @@ -151,37 +157,48 @@ def spec(self): ), } - options = { - "order": SpecField( - type=FieldType.string, - description=[ - f"The order to list {self.result_display_name} in." - ], - default="asc", - choices=["desc", "asc"], - ), - "order_by": SpecField( - type=FieldType.string, - description=[ - f"The attribute to order {self.result_display_name} by." - ], - ), - "filters": SpecField( - type=FieldType.list, - element_type=FieldType.dict, - suboptions=spec_filter, - description=[ - f"A list of filters to apply to the resulting {self.result_display_name}." - ], - ), - "count": SpecField( - type=FieldType.integer, - description=[ - f"The number of {self.result_display_name} to return.", - "If undefined, all results will be returned.", - ], - ), - } + if not self.disable_filters: + options = { + "order": SpecField( + type=FieldType.string, + description=[ + f"The order to list {self.result_display_name} in." + ], + default="asc", + choices=["desc", "asc"], + ), + "order_by": SpecField( + type=FieldType.string, + description=[ + f"The attribute to order {self.result_display_name} by." + ], + ), + "filters": SpecField( + type=FieldType.list, + element_type=FieldType.dict, + suboptions=spec_filter, + description=[ + f"A list of filters to apply to the resulting {self.result_display_name}." + ], + ), + "count": SpecField( + type=FieldType.integer, + description=[ + f"The number of {self.result_display_name} to return.", + "If undefined, all results will be returned.", + ], + ), + } + else: + options = { + "count": SpecField( + type=FieldType.integer, + description=[ + f"The number of {self.result_display_name} to return.", + "If undefined, all results will be returned.", + ], + ), + } options.update(self.custom_options) diff --git a/plugins/module_utils/linode_helper.py b/plugins/module_utils/linode_helper.py index e509ca12..c7e46e45 100644 --- a/plugins/module_utils/linode_helper.py +++ b/plugins/module_utils/linode_helper.py @@ -658,3 +658,39 @@ def __attempt_delete() -> bool: step=4, timeout=timeout_ctx.seconds_remaining, ) + + +def api_filter_constructor_for_aclp_monitor_services( + params: Dict[str, Any], +) -> Dict[str, Any]: + """ + Customize a filter string for listing ACLP Monitor Services, + because on the API side only the `+and` and `+or` operators are supported, + and you can't nest filter operators. `order_by` and `order` are not supported either + and will be ignored if provided. + """ + filters = params.get("filters") + value_filters = {} + + if filters is not None and len(filters) > 0: + if len(filters) == 1: + # filter on single field with `+or` + value_filters = { + "+or": [ + {filters[0]["name"]: value} + for value in filters[0]["values"] + ] + } + else: + result = [] + for filter_opt in filters: + flat_filters = [ + {filter_opt["name"]: v} + for v in filter_opt.get("values", []) + ] + result.extend(flat_filters) + + # filter on multiple fields with `+and` + value_filters = {"+and": result} + + return value_filters diff --git a/plugins/modules/monitor_alert_channel_list.py b/plugins/modules/monitor_alert_channel_list.py new file mode 100644 index 00000000..8eafda85 --- /dev/null +++ b/plugins/modules/monitor_alert_channel_list.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +"""This module allows users to list ACLP Monitor Service Alert Channel. +NOTE: This module is under v4beta. +""" +from __future__ import absolute_import, division, print_function + +from typing import Any, Dict + +from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import ( + alert_channels_list as docs, +) +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import ( + ListModule, +) +from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( + api_filter_constructor_for_aclp_monitor_services, +) + + +def custom_api_filter_constructor(params: Dict[str, Any]) -> Dict[str, Any]: + """ + Customize a filter string for listing Monitor Service Alert Channels, + because on the API side only the `+and` and `+or` operators are supported, + and you can't nest filter operators. + """ + if params.get("order_by") is not None or params.get("order") is not None: + module.warn( + "order or order_by is currently not supported in listing the alert channels, " + "and will be ignored if provided. " + "Please refer to the API documentation for more information." + ) + + return api_filter_constructor_for_aclp_monitor_services(params) + + +module = ListModule( + result_display_name="Alert Channels", + result_field_name="alert_channels", + endpoint_template="/monitor/alert-channels", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-alert-channels", + examples=docs.specdoc_examples, + result_samples=docs.result_alert_channels_samples, + requires_beta=True, + custom_api_filter_constructor=custom_api_filter_constructor, +) + +SPECDOC_META = module.spec + +DOCUMENTATION = r""" +""" +EXAMPLES = r""" +""" +RETURN = r""" +""" + +if __name__ == "__main__": + module.run() diff --git a/plugins/modules/monitor_services_alert_definition.py b/plugins/modules/monitor_services_alert_definition.py new file mode 100644 index 00000000..13fb8382 --- /dev/null +++ b/plugins/modules/monitor_services_alert_definition.py @@ -0,0 +1,431 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""This module allows users to manage ACLP alert definitions. +NOTE: This module is under v4beta.""" + +from __future__ import absolute_import, division, print_function + +from typing import Any, List, Optional + +import ansible_collections.linode.cloud.plugins.module_utils.doc_fragments.alert_definition as docs +import polling +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, + handle_updates, +) +from ansible_specdoc.objects import ( + FieldType, + SpecDocMeta, + SpecField, + SpecReturnValue, +) +from linode_api4 import AlertDefinition + +dimension_filter_spec: dict = { + "dimension_label": SpecField( + type=FieldType.string, + description=["The name of the dimension to be used in the filter."], + ), + "operator": SpecField( + type=FieldType.string, + choices=["eq", "neq", "startswith", "endswith"], + description=[ + "The operator to apply to the dimension filter. " + "Available values are eq for equal, neq for not equal, startswith, and endswith." + ], + ), + "value": SpecField( + type=FieldType.string, + description=["The value to compare the dimension_label against."], + ), +} + +rule_spec: dict = { + "aggregate_function": SpecField( + type=FieldType.string, + choices=["avg", "sum", "min", "max"], + description=["The aggregation function applied to the metric."], + ), + "dimension_filters": SpecField( + type=FieldType.list, + element_type=FieldType.dict, + suboptions=dimension_filter_spec, + description=[ + "Individual objects that define dimension filters for the rule." + ], + ), + "metric": SpecField( + type=FieldType.string, description=["The metric to query."] + ), + "operator": SpecField( + type=FieldType.string, + choices=["eq", "gt", "lt", "gte", "lte"], + description=[ + "The operator to apply to the metric. " + "Available values are eq for equal, " + "gt for greater than, " + "lt for less than, " + "gte for greater than or equal, " + "and lte for less than or equal." + ], + ), + "threshold": SpecField( + type=FieldType.float, + description=[ + "The predefined value or condition that triggers an alert when met or exceeded." + ], + ), +} + +rule_criteria_spec: dict = { + "rules": SpecField( + type=FieldType.list, + element_type=FieldType.dict, + suboptions=rule_spec, + description=["The individual rules that make up the alert definition."], + ) +} + +trigger_conditions_spec: dict = { + "criteria_condition": SpecField( + type=FieldType.string, + choices=["ALL"], + description=[ + "Signifies the logical operation applied when multiple metrics " + "are set for an alert definition. " + "For example, if you wanted to apply both cpu_usage > 90 and memory_usage > 80, " + "ALL is the criteria_condition. " + "Currently, only ALL is supported." + ], + ), + "evaluation_period_seconds": SpecField( + type=FieldType.integer, + description=[ + "The time period over which data is collected before evaluating " + "whether the alert definition's threshold has been met or exceeded." + ], + ), + "polling_interval_seconds": SpecField( + type=FieldType.integer, + description=[ + "The frequency at which the metric is checked for a change in state. " + "For example, with cpu_usage set as your metric and this set to 300, " + "your cpu_usage is checked every 5 minutes for some change in its state." + ], + ), + "trigger_occurrences": SpecField( + type=FieldType.integer, + description=[ + "The minimum number of consecutive polling_interval_seconds periods that " + "the threshold needs to be breached to trigger the alert." + ], + ), +} + +spec: dict = { + "service_type": SpecField( + type=FieldType.string, + required=True, + description=["The Akamai Cloud Computing service being monitored."], + ), + "channel_ids": SpecField( + type=FieldType.list, + required=True, + editable=True, + description=[ + "The identifiers for the alert channels to use for the alert. " + "Run the List alert channels operation and store the id for the applicable channels." + ], + ), + "description": SpecField( + type=FieldType.string, + editable=True, + description=["An additional description for the alert definition."], + ), + "entity_ids": SpecField( + type=FieldType.list, + editable=True, + description=[ + "The id for each individual entity from a service_type. " + "Get this value by running the list operation for the appropriate entity. " + "For example, if your entity is one of your PostgreSQL databases, " + "run the List PostgreSQL Managed Databases operation " + "and store the id for the appropriate database from the response. " + "You also need read_only access to the scope for the service_type " + "for each of the entity_ids." + ], + ), + "label": SpecField( + type=FieldType.string, + required=True, + editable=True, + description=[ + "The name of the alert definition. " + "This is used for display purposes in Akamai Cloud Manager." + ], + ), + "rule_criteria": SpecField( + type=FieldType.dict, + suboptions=rule_criteria_spec, + required=True, + editable=True, + description=["Details for the rules required to trigger the alert."], + ), + "severity": SpecField( + type=FieldType.integer, + required=True, + editable=True, + choices=[0, 1, 2, 3], + description=[ + "The severity of the alert. " + "Supported values include 3 for info, " + "2 for low, 1 for medium, and 0 for severe." + ], + ), + "trigger_conditions": SpecField( + type=FieldType.dict, + required=True, + editable=True, + suboptions=trigger_conditions_spec, + description=[ + "The conditions that need to be met to send a notification for the alert." + ], + ), + "id": SpecField( + type=FieldType.integer, + description=[ + "The unique identifier assigned to the alert definition. " + "Run the List alert definitions operation and store the id " + "for the applicable alert definition. " + "Required for updating." + ], + ), + "status": SpecField( + type=FieldType.string, + editable=True, + choices=["enabled", "disabled"], + description=["The current status of the alert."], + ), + "state": SpecField( + type=FieldType.string, + description=["The desired state of the target."], + choices=["present", "absent"], + required=True, + ), + "wait": SpecField( + type=FieldType.bool, + default=False, + description=["Wait for the alert definition ready (not in progress)."], + ), + "wait_timeout": SpecField( + type=FieldType.integer, + default=600, + description=[ + "The amount of time, in seconds, to wait for the alert definition." + ], + ), +} + +SPECDOC_META = SpecDocMeta( + description=[ + "Manage an alert definition for a specific service type. " + "Akamai refers to these as user alerts. " + "You need read_only access to the scope for the selected serviceType. " + ], + requirements=global_requirements, + author=global_authors, + options=spec, + examples=docs.specdoc_examples, + return_values={ + "alert_definition": SpecReturnValue( + description="The alert definition in JSON serialized form.", + docs_url="https://techdocs.akamai.com/linode-api/reference/get-alert-definition", + type=FieldType.dict, + sample=docs.result_aclp_alert_definition_sample, + ), + }, +) + +# Fields that can be updated on an existing ACLP alert definition +MUTABLE_FIELDS = { + "channel_ids", + "description", + "entity_ids", + "label", + "rule_criteria", + "severity", + "status", + "trigger_conditions", +} + +DOCUMENTATION = r""" +""" +EXAMPLES = r""" +""" +RETURN = r""" +""" + + +class LinodeMonitorServicesAlertDefinition(LinodeModuleBase): + """Module for creating and destroying ACLP Monitor Services Alert Definition""" + + def __init__(self) -> None: + self.module_arg_spec = SPECDOC_META.ansible_spec + self.required_one_of: List[str] = [] + self.results = { + "changed": False, + "actions": [], + "alert_definition": None, + } + + self._alert_definition: Optional[AlertDefinition] = None + + super().__init__( + module_arg_spec=self.module_arg_spec, + required_one_of=self.required_one_of, + ) + + def _wait_for_alert_definition_ready( + self, alert_definition: AlertDefinition + ) -> None: + def poll_func() -> bool: + alert_definition._api_get() + return alert_definition.status not in ["in progress"] + + # Initial attempt + if poll_func(): + return + + try: + polling.poll( + poll_func, + step=10, + timeout=self._timeout_ctx.seconds_remaining, + ) + except polling.TimeoutException: + self.fail( + "failed to wait for alert definition status: timeout period expired" + ) + + def _get_alert_definition( + self, alert_id: int, service_type: str + ) -> Optional[AlertDefinition]: + try: + alert_definition = self.client.load( + AlertDefinition, alert_id, service_type + ) + + return alert_definition + except Exception as exception: + return self.fail( + msg="failed to get an alert definition id {0} service type {1}: {2}".format( + alert_id, service_type, exception + ) + ) + + def _create_alert_definition(self) -> Optional[AlertDefinition]: + params = self.module.params + service_type = params.pop("service_type") + + try: + self.register_action( + "Created alert definition for service type {0}".format( + service_type + ) + ) + return self.client.monitor.create_alert_definition( + service_type=service_type, + label=params.pop("label"), + severity=params.pop("severity"), + description=params.pop("description"), + channel_ids=params.pop("channel_ids"), + rule_criteria=params.pop("rule_criteria"), + trigger_conditions=params.pop("trigger_conditions"), + ) + except Exception as exception: + return self.fail( + msg="failed to create alert definition: {0}".format(exception) + ) + + def _update_alert_definition(self) -> None: + """Handles all update functionality for the current Alert Definition""" + + handle_updates( + self._alert_definition, + filter_null_values(self.module.params), + MUTABLE_FIELDS, + self.register_action, + ) + + if self.module.params.get("wait"): + self._wait_for_alert_definition_ready(self._alert_definition) + + def _handle_alert_definition(self) -> None: + params = self.module.params + + service_type: str = params.get("service_type") + alert_id: int = params.get("id") + + if alert_id: + self._alert_definition = self._get_alert_definition( + alert_id, service_type + ) + + # Create the alert definition if it does not already exist + if self._alert_definition is None: + self._alert_definition = self._create_alert_definition() + if params.get("wait"): + self._wait_for_alert_definition_ready(self._alert_definition) + + self._update_alert_definition() + + # Force lazy-loading + self._alert_definition._api_get() + + self.results["alert_definition"] = self._alert_definition._raw_json + + def _handle_alert_definition_absent(self) -> None: + service_type: str = self.module.params.get("service_type") + alert_id: int = self.module.params.get("id") + + self._alert_definition = self._get_alert_definition( + alert_id, service_type + ) + + if self._alert_definition is not None: + self.results["alert_definition"] = self._alert_definition._raw_json + + self._alert_definition.delete() + self.register_action( + "Deleted alert definition {0} service type {1}".format( + alert_id, service_type + ) + ) + + def exec_module(self, **kwargs: Any) -> Optional[dict]: + """Entrypoint for Monitor Services Alert Definition module""" + state = kwargs.get("state") + + if state == "absent": + self._handle_alert_definition_absent() + return self.results + + self._handle_alert_definition() + + return self.results + + +def main() -> None: + """Constructs and calls the Linode Monitor Services Alert Definition module""" + LinodeMonitorServicesAlertDefinition() + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/monitor_services_alert_definition_by_service_type_list.py b/plugins/modules/monitor_services_alert_definition_by_service_type_list.py new file mode 100644 index 00000000..42d78ad6 --- /dev/null +++ b/plugins/modules/monitor_services_alert_definition_by_service_type_list.py @@ -0,0 +1,55 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +"""This module allows users to list ACLP Monitor Service Alert Definitions +for a specific service type. +NOTE: This module is under v4beta.""" +from __future__ import absolute_import, division, print_function + +from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import ( + alert_definitions_by_service_type_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="Alert Definitions", + result_field_name="alert_definitions", + description=[ + "The return alert definitions by service type. " + "**Note: filters and order are currently NOT supported by this endpoint." + ], + endpoint_template="/monitor/services/{service_type}/alert-definitions", + result_docs_url="https://techdocs.akamai.com/linode-api/reference" + "/get-alert-definitions-for-service-type", + examples=docs.specdoc_examples, + result_samples=docs.result_alert_definitions_by_service_type_samples, + requires_beta=True, + params=[ + ListModuleParam( + display_name="Service Type", + name="service_type", + type=FieldType.string, + ) + ], + # filtering is currently not supported by this module + disable_filters=True, +) + + +SPECDOC_META = module.spec + +DOCUMENTATION = r""" +""" +EXAMPLES = r""" +""" +RETURN = r""" +""" + +if __name__ == "__main__": + module.run() diff --git a/plugins/modules/monitor_services_alert_definition_info.py b/plugins/modules/monitor_services_alert_definition_info.py new file mode 100644 index 00000000..49342efd --- /dev/null +++ b/plugins/modules/monitor_services_alert_definition_info.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +"""This module allows users to retrieve information about a ACLP Monitor Service Alert Definition. +NOTE: This module is under v4beta.""" + +from __future__ import absolute_import, division, print_function + +from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import ( + alert_definition_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 AlertDefinition + +module = InfoModule( + examples=docs.specdoc_examples, + primary_result=InfoModuleResult( + display_name="Alert Definition", + field_name="alert_definition", + field_type=FieldType.dict, + docs_url="https://techdocs.akamai.com/linode-api/reference/get-alert-definition", + samples=docs.result_alert_definition_samples, + ), + params=[ + InfoModuleParam( + display_name="Service Type", + name="service_type", + type=FieldType.string, + ) + ], + attributes=[ + InfoModuleAttr( + name="id", + display_name="ID", + type=FieldType.integer, + get=lambda client, params: client.load( + AlertDefinition, params.get("id"), params.get("service_type") + )._raw_json, + ), + ], +) + +SPECDOC_META = module.spec + +DOCUMENTATION = r""" +""" +EXAMPLES = r""" +""" +RETURN = r""" +""" + +if __name__ == "__main__": + module.run() diff --git a/plugins/modules/monitor_services_alert_definition_list.py b/plugins/modules/monitor_services_alert_definition_list.py new file mode 100644 index 00000000..9932de54 --- /dev/null +++ b/plugins/modules/monitor_services_alert_definition_list.py @@ -0,0 +1,59 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +"""This module allows users to list ACLP Monitor Service Alert Definitions. +NOTE: This module is under v4beta.""" +from __future__ import absolute_import, division, print_function + +from typing import Any, Dict + +from ansible_collections.linode.cloud.plugins.module_utils.doc_fragments import ( + alert_definitions_list as docs, +) +from ansible_collections.linode.cloud.plugins.module_utils.linode_common_list import ( + ListModule, +) +from ansible_collections.linode.cloud.plugins.module_utils.linode_helper import ( + api_filter_constructor_for_aclp_monitor_services, +) + + +def custom_api_filter_constructor(params: Dict[str, Any]) -> Dict[str, Any]: + """ + Customize a filter string for listing Monitor Service Alert Definitions, + because on the API side only the `+and` and `+or` operators are supported, + and you can't nest filter operators. + """ + if params.get("order_by") is not None or params.get("order") is not None: + module.warn( + "order or order_by is currently not supported in " + "listing the alert definitions, " + "and will be ignored if provided. " + "Please refer to the API documentation for more information." + ) + + return api_filter_constructor_for_aclp_monitor_services(params) + + +module = ListModule( + result_display_name="Alert Definitions", + result_field_name="alert_definitions", + endpoint_template="/monitor/alert-definitions", + result_docs_url="https://techdocs.akamai.com/linode-api/reference/get-alert-definitions", + examples=docs.specdoc_examples, + result_samples=docs.result_alert_definitions_samples, + requires_beta=True, + custom_api_filter_constructor=custom_api_filter_constructor, +) + +SPECDOC_META = module.spec + +DOCUMENTATION = r""" +""" +EXAMPLES = r""" +""" +RETURN = r""" +""" + +if __name__ == "__main__": + module.run() diff --git a/tests/integration/targets/monitor_services_alert_definition/tasks/main.yaml b/tests/integration/targets/monitor_services_alert_definition/tasks/main.yaml new file mode 100644 index 00000000..501ef666 --- /dev/null +++ b/tests/integration/targets/monitor_services_alert_definition/tasks/main.yaml @@ -0,0 +1,181 @@ +- name: monitor_services_alert_definition + block: + - set_fact: + r: "{{ 1000000000 | random }}" + + - name: List available alert channels + linode.cloud.monitor_alert_channel_list: + register: alert_channel_list + + - name: Only create alert definition when there are alert channels available + block: + - set_fact: + alert_channels: [ '{{ alert_channel_list.alert_channels[0].id if alert_channel_list.alert_channels | length > 0 }}' ] + label: 'ansible-test-{{ r }}' + + - name: Create an alert definition for dbaas + linode.cloud.monitor_services_alert_definition: + service_type: 'dbaas' + description: 'An alert definition for ansible test' + label: '{{ label }}' + severity: 1 + rule_criteria: + rules: + - aggregate_function: 'avg' + dimension_filters: + - dimension_label: 'node_type' + operator: 'eq' + value: 'primary' + metric: 'memory_usage' + operator: 'gt' + threshold: 90 + trigger_conditions: + criteria_condition: 'ALL' + evaluation_period_seconds: 300 + polling_interval_seconds: 300 + trigger_occurrences: 1 + channel_ids: '{{ alert_channels }}' + wait: yes + state: present + register: create + + - name: Assert alert definition is created + assert: + that: + - create.alert_definition.description == 'An alert definition for ansible test' + - create.alert_definition.label == label + - create.alert_definition.severity == 1 + - create.alert_definition.rule_criteria.rules[0].aggregate_function == 'avg' + - create.alert_definition.rule_criteria.rules[0].dimension_filters[0].dimension_label == 'node_type' + - create.alert_definition.trigger_conditions.criteria_condition == 'ALL' + - create.alert_definition.trigger_conditions.evaluation_period_seconds == 300 + - create.alert_definition.trigger_conditions.polling_interval_seconds == 300 + - create.alert_definition.trigger_conditions.trigger_occurrences == 1 + + - name: Update an alert definition + linode.cloud.monitor_services_alert_definition: + service_type: 'dbaas' + id: '{{ create.alert_definition.id }}' + description: 'An updated alert definition for ansible test' + label: '{{ label }}-updated' + severity: 1 + rule_criteria: + rules: + - aggregate_function: 'sum' + dimension_filters: + - dimension_label: 'node_type' + operator: 'eq' + value: 'primary' + metric: 'memory_usage' + operator: 'gt' + threshold: 90 + trigger_conditions: + criteria_condition: 'ALL' + evaluation_period_seconds: 300 + polling_interval_seconds: 300 + trigger_occurrences: 1 + channel_ids: '{{ alert_channels }}' + wait: yes + state: present + register: update + + - name: Assert alert definition is updated + assert: + that: + - update.changed + - update.alert_definition.label == (label + '-updated') + - update.alert_definition.description == 'An updated alert definition for ansible test' + - update.alert_definition.rule_criteria.rules[0].aggregate_function == 'sum' + + - name: Get alert definition information + linode.cloud.monitor_services_alert_definition_info: + service_type: '{{ create.alert_definition.service_type }}' + id: '{{ create.alert_definition.id }}' + register: info + + - name: Assert alert_definition_info response + assert: + that: + - info.alert_definition.id == update.alert_definition.id + - info.alert_definition.service_type == update.alert_definition.service_type + - info.alert_definition.label == update.alert_definition.label + + - name: List available alert definitions by service type + linode.cloud.monitor_services_alert_definition_by_service_type_list: + service_type: 'dbaas' + register: alert_definitions_list_by_service_type + + - name: Assert alert_definitions_list_by_service_type response + assert: + that: + - alert_definitions_list_by_service_type.alert_definitions | length > 0 + + - name: List available alert definitions + linode.cloud.monitor_services_alert_definition_list: + filters: + - name: id + values: ['{{ create.alert_definition.id }}'] + register: alert_definitions_list + + - name: Assert alert_definitions_list response + assert: + that: + - alert_definitions_list.alert_definitions | length > 0 + + - name: List available alert definitions and expect empty result with filter + linode.cloud.monitor_services_alert_definition_list: + filters: + - name: id + values: [ '{{ create.alert_definition.id }}' ] + - name: label + values: ["some label"] + register: monitor_services_alert_definition_list_empty + + - name: Assert monitor_services_alert_definition_list response + assert: + that: + - monitor_services_alert_definition_list_empty.alert_definitions | length == 0 + + when: alert_channel_list.alert_channels | length > 0 + + + always: + - ignore_errors: yes + block: + - name: Delete alert definition + linode.cloud.monitor_services_alert_definition: + service_type: 'dbaas' + id: '{{ create.alert_definition.id }}' + description: 'An updated alert definition for ansible test' + label: '{{ label }}-updated' + severity: 1 + rule_criteria: + rules: + - aggregate_function: 'sum' + dimension_filters: + - dimension_label: 'node_type' + operator: 'eq' + value: 'primary' + metric: 'memory_usage' + operator: 'gt' + threshold: 90 + trigger_conditions: + criteria_condition: 'ALL' + evaluation_period_seconds: 300 + polling_interval_seconds: 300 + trigger_occurrences: 1 + channel_ids: '{{ alert_channels }}' + state: absent + register: delete + + - name: Assert alert definition is deleted + assert: + that: + - delete.changed + - delete.alert_definition.id == create.alert_definition.id + environment: + LINODE_UA_PREFIX: '{{ ua_prefix }}' + LINODE_API_TOKEN: '{{ api_token }}' + LINODE_API_URL: '{{ api_url }}' + LINODE_API_VERSION: '{{ api_version }}' + LINODE_CA: '{{ ca_file or "" }}'