Repository: ansible-collections/amazon.aws

Issue:
amazon.aws.cloudwatch_metric_alarm to include "evaluate_low_sample_count_percentile"
### Summary

I am trying to add alarms that require `evaluate_low_sample_count_percentile` to be set.

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-alarm.html#cfn-cloudwatch-alarm-evaluatelowsamplecountpercentile

### Issue Type

Feature Idea

### Component Name

cloudwatch_metric_alarm

### Additional Information

<!--- Paste example playbooks or commands between quotes below -->
```yaml (paste below)

```


### Code of Conduct

- [X] I agree to follow the Ansible Code of Conduct


Discussion:

Resolving patch:
diff --git a/plugins/modules/cloudwatch_metric_alarm.py b/plugins/modules/cloudwatch_metric_alarm.py
--- a/plugins/modules/cloudwatch_metric_alarm.py
+++ b/plugins/modules/cloudwatch_metric_alarm.py
@@ -153,6 +153,14 @@
           - The time (in seconds) between metric evaluations.
         required: false
         type: int
+    evaluate_low_sample_count_percentile:
+        description:
+          - Used only for alarms based on percentiles.
+          - If you specify V(ignore), the alarm state does not change during periods with too few data points to be statistically significant.
+          - If you specify V(evaluate) or omit this parameter, alarm is evaluated and possibly changes state no matter how many data points are available.
+        type: str
+        choices: ['ignore', 'evaluate']
+        version_added: 9.0.0
     evaluation_periods:
         description:
           - The number of times in which the metric is evaluated before final calculation.
@@ -241,8 +249,6 @@
   - amazon.aws.boto3
 """
 
-RETURN = r""" # """
-
 EXAMPLES = r"""
 - name: create alarm
   amazon.aws.cloudwatch_metric_alarm:
@@ -255,6 +261,7 @@
     comparison: "LessThanOrEqualToThreshold"
     threshold: 5.0
     period: 300
+    evaluate_low_sample_count_percentile: "ignore"
     evaluation_periods: 3
     unit: "Percent"
     description: "This will alarm when a instance's CPU usage average is lower than 5% for 15 minutes"
@@ -299,6 +306,126 @@
     alarm_actions: ["arn:aws:automate:us-west-1:ec2:recover"]
 """
 
+RETURN = r"""
+actions_enabled:
+    description: Indicates whether actions should be executed during any changes to the alarm state.
+    returned: always
+    type: bool
+name:
+    description: Unique name for the alarm.
+    returned: always
+    type: str
+alarm_arn:
+    description: The Amazon Resource Name (ARN) of the alarm.
+    returned: always
+    type: str
+description:
+    description: The description of the alarm.
+    returned: always
+    type: str
+last_updated:
+    description: The time stamp of the last update to the alarm configuration.
+    returned: always
+    type: str
+ok_actions:
+    description: The actions to execute when this alarm transitions to an OK state from any other state.
+    returned: always
+    type: list
+    elements: str
+alarm_actions:
+    description: The actions to execute when this alarm transitions to an ALARM state from any other state.
+    returned: always
+    type: list
+    elements: str
+insufficient_data_actions:
+    description: The actions to execute when this alarm transitions to an INSUFFICIENT_DATA state from any other state.
+    returned: always
+    type: list
+    elements: str
+state_value:
+    description: The state value for the alarm.
+    returned: always
+    type: str
+state_reason:
+    description: An explanation for the alarm state, in text format.
+    returned: always
+    type: str
+metric:
+    description: Name of the monitored metric (e.g. C(CPUUtilization)).
+    returned: always
+    type: str
+metric_name:
+    description: Name of the monitored metric (e.g. C(CPUUtilization)).
+    returned: always
+    type: str
+namespace:
+    description:
+        - Name of the appropriate namespace (C(AWS/EC2), C(System/Linux), etc.).
+        - Determines the category it will appear under in CloudWatch.
+    returned: always
+    type: str
+statistic:
+    description: The statistic for the metric associated with the alarm, other than percentile.
+    returned: always
+    type: str
+extended_statistic:
+    description: The percentile statistic for the metric associated with the alarm.
+    returned: always
+    type: str
+dimensions:
+    description: The dimensions for the metric.
+    returned: always
+    type: list
+    elements: dict
+    contains:
+        name:
+            description: The name of the dimension.
+            returned: always
+            type: str
+        value:
+            description: The value of the dimension.
+            returned: always
+            type: str
+period:
+    description:
+        - The length, in seconds, used each time the metric specified in MetricName is evaluated.
+        - Valid values are 10, 30, and any multiple of 60.
+    returned: always
+    type: int
+unit:
+    description: Unit used when storing the metric
+    returned: always
+    type: str
+evaluation_periods:
+    description: The number of periods over which data is compared to the specified threshold.
+    returned: always
+    type: int
+threshold:
+    description: The value to compare with the specified statistic.
+    returned: always
+    type: float
+comparison:
+    description: The arithmetic operation to use when comparing the specified statistic and threshold.
+    returned: always
+    type: str
+treat_missing_data:
+    description: Sets how alarm is to handle missing data points.
+    returned: always
+    type: str
+evaluate_low_sample_count_percentile:
+    description:
+        - Used only for alarms based on percentiles.
+        - If I(ignore), the alarm state does not change during periods with too few data points to be statistically significant.
+        - If I(evaluate) or this parameter is not used, the alarm is always evaluated and possibly changes state.
+    returned: always
+    type: str
+metrics:
+    description: An array of MetricDataQuery structures, used in an alarm based on a metric math expression.
+    returned: always
+    type: list
+    elements: dict
+"""
+
 try:
     from botocore.exceptions import ClientError
 except ImportError:
@@ -381,6 +508,8 @@ def create_metric_alarm(connection, module, params):
         comparison=result.get("ComparisonOperator"),
         description=result.get("AlarmDescription"),
         dimensions=result.get("Dimensions"),
+        extended_statistic=result.get("ExtendedStatistic"),
+        evaluate_low_sample_count_percentile=result.get("EvaluateLowSampleCountPercentile"),
         evaluation_periods=result.get("EvaluationPeriods"),
         insufficient_data_actions=result.get("InsufficientDataActions"),
         last_updated=result.get("AlarmConfigurationUpdatedTimestamp"),
@@ -462,6 +591,7 @@ def main():
                 "None",
             ],
         ),
+        evaluate_low_sample_count_percentile=dict(type="str", choices=["ignore", "evaluate"]),
         evaluation_periods=dict(type="int"),
         extended_statistic=dict(type="str"),
         description=dict(type="str"),
@@ -503,6 +633,7 @@ def main():
     params["ComparisonOperator"] = module.params.get("comparison")
     params["Threshold"] = module.params.get("threshold")
     params["Period"] = module.params.get("period")
+    params["EvaluateLowSampleCountPercentile"] = module.params.get("evaluate_low_sample_count_percentile")
     params["EvaluationPeriods"] = module.params.get("evaluation_periods")
     if module.params.get("unit"):
         params["Unit"] = module.params.get("unit")


Test patch:
diff --git a/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml
--- a/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml
+++ b/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml
@@ -211,13 +211,14 @@
         name: "{{ alarm_full_name }}"
         metric: CPUUtilization
         namespace: AWS/EC2
-        statistic: Average
-        comparison: LessThanOrEqualToThreshold
+        extended_statistic: p50
+        comparison: GreaterThanOrEqualToThreshold
         threshold: 5.0
         period: 60
         evaluation_periods: 3
+        evaluate_low_sample_count_percentile: "evaluate"
         unit: Percent
-        description: This will alarm when an instance's cpu usage average is lower than 5% for 3 minutes
+        description: This will alarm when an instance's cpu usage percentage is greater than or equal to 50% for 3 minutes
       check_mode: true
       register: ec2_instance_metric_alarm_update_check
 
@@ -251,13 +252,14 @@
         name: "{{ alarm_full_name }}"
         metric: CPUUtilization
         namespace: AWS/EC2
-        statistic: Average
-        comparison: LessThanOrEqualToThreshold
+        extended_statistic: p50
+        comparison: GreaterThanOrEqualToThreshold
         threshold: 5.0
         period: 60
         evaluation_periods: 3
+        evaluate_low_sample_count_percentile: "evaluate"
         unit: Percent
-        description: This will alarm when an instance's cpu usage average is lower than 5% for 3 minutes
+        description: This will alarm when an instance's cpu usage percentage is greater than or equal to 50% for 3 minutes
       register: ec2_instance_metric_alarm_update
 
     - name: verify that alarm registers as updated
@@ -271,12 +273,12 @@
           - ec2_instance_metric_alarm_update.changed
           - ec2_instance_metric_alarm_update.period == 60 # Period should be 60, not matching old value
           - ec2_instance_metric_alarm_update.alarm_arn == ec2_instance_metric_alarm.alarm_arn
-          - ec2_instance_metric_alarm_update.statistic == alarm_info.metric_alarms[0].statistic
+          - ec2_instance_metric_alarm_update.extended_statistic ==  'p50'
+          - ec2_instance_metric_alarm_update.evaluate_low_sample_count_percentile ==  'evaluate'
           - ec2_instance_metric_alarm_update.name  == alarm_info.metric_alarms[0].alarm_name
           - ec2_instance_metric_alarm_update.metric == alarm_info.metric_alarms[0].metric_name
           - ec2_instance_metric_alarm_update.namespace == alarm_info.metric_alarms[0].namespace
-          - ec2_instance_metric_alarm_update.statistic == alarm_info.metric_alarms[0].statistic
-          - ec2_instance_metric_alarm_update.comparison == alarm_info.metric_alarms[0].comparison_operator
+          - ec2_instance_metric_alarm_update.comparison == 'GreaterThanOrEqualToThreshold'
           - ec2_instance_metric_alarm_update.threshold == alarm_info.metric_alarms[0].threshold
           - ec2_instance_metric_alarm_update.unit == alarm_info.metric_alarms[0].unit
           - ec2_instance_metric_alarm_update.evaluation_periods == alarm_info.metric_alarms[0].evaluation_periods