From bee5155385e4bb668d1abc8c71f623ec931b0bf4 Mon Sep 17 00:00:00 2001 From: Mark Chappell Date: Mon, 4 Jul 2022 17:02:00 +0200 Subject: [PATCH 1/8] Rename cloudwatch metrics_alarm (#1304) Rename cloudwatch metrics_alarm SUMMARY In line with the new naming guidelines rename ec2_metric_alarm to cloudwatch_metric_alarm ISSUE TYPE Feature Pull Request COMPONENT NAME plugins/modules/cloudwatch_metric_alarm.py plugins/modules/ec2_metric_alarm.py ADDITIONAL INFORMATION Reviewed-by: Alina Buzachis This commit was initially merged in https://github.com/ansible-collections/community.aws See: https://github.com/ansible-collections/community.aws/commit/88c62c51b908135fde0505f9582075ec0ab03fc8 --- plugins/modules/cloudwatch_metric_alarm.py | 352 +++++++++++++ .../targets/cloudwatch_metric_alarm/aliases | 1 + .../cloudwatch_metric_alarm/defaults/main.yml | 5 + .../cloudwatch_metric_alarm/meta/main.yml | 2 + .../tasks/env_cleanup.yml | 94 ++++ .../tasks/env_setup.yml | 62 +++ .../cloudwatch_metric_alarm/tasks/main.yml | 467 ++++++++++++++++++ .../cloudwatch_metric_alarm/vars/main.yml | 1 + 8 files changed, 984 insertions(+) create mode 100644 plugins/modules/cloudwatch_metric_alarm.py create mode 100644 tests/integration/targets/cloudwatch_metric_alarm/aliases create mode 100644 tests/integration/targets/cloudwatch_metric_alarm/defaults/main.yml create mode 100644 tests/integration/targets/cloudwatch_metric_alarm/meta/main.yml create mode 100644 tests/integration/targets/cloudwatch_metric_alarm/tasks/env_cleanup.yml create mode 100644 tests/integration/targets/cloudwatch_metric_alarm/tasks/env_setup.yml create mode 100644 tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml create mode 100644 tests/integration/targets/cloudwatch_metric_alarm/vars/main.yml diff --git a/plugins/modules/cloudwatch_metric_alarm.py b/plugins/modules/cloudwatch_metric_alarm.py new file mode 100644 index 00000000000..dbe6bf43f94 --- /dev/null +++ b/plugins/modules/cloudwatch_metric_alarm.py @@ -0,0 +1,352 @@ +#!/usr/bin/python +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +from __future__ import absolute_import, division, print_function +__metaclass__ = type + + +DOCUMENTATION = r''' +module: cloudwatch_metric_alarm +short_description: "Create/update or delete AWS CloudWatch 'metric alarms'" +version_added: 1.0.0 +description: + - Can create or delete AWS CloudWatch metric alarms. + - Metrics you wish to alarm on must already exist. + - Prior to release 5.0.0 this module was called C(community.aws.ec2_metric_alarm). + The usage did not change. +author: + - "Zacharie Eakin (@Zeekin)" +options: + state: + description: + - Register or deregister the alarm. + choices: ['present', 'absent'] + default: 'present' + type: str + name: + description: + - Unique name for the alarm. + required: true + type: str + metric: + description: + - Name of the monitored metric (e.g. C(CPUUtilization)). + - Metric must already exist. + required: false + type: str + namespace: + description: + - Name of the appropriate namespace (C(AWS/EC2), C(System/Linux), etc.), which determines the category it will appear under in CloudWatch. + required: false + type: str + statistic: + description: + - Operation applied to the metric. + - Works in conjunction with I(period) and I(evaluation_periods) to determine the comparison value. + required: false + choices: ['SampleCount','Average','Sum','Minimum','Maximum'] + type: str + comparison: + description: + - Determines how the threshold value is compared + required: false + type: str + choices: + - 'GreaterThanOrEqualToThreshold' + - 'GreaterThanThreshold' + - 'LessThanThreshold' + - 'LessThanOrEqualToThreshold' + threshold: + description: + - Sets the min/max bound for triggering the alarm. + required: false + type: float + period: + description: + - The time (in seconds) between metric evaluations. + required: false + type: int + evaluation_periods: + description: + - The number of times in which the metric is evaluated before final calculation. + required: false + type: int + unit: + description: + - The threshold's unit of measurement. + required: false + type: str + choices: + - 'Seconds' + - 'Microseconds' + - 'Milliseconds' + - 'Bytes' + - 'Kilobytes' + - 'Megabytes' + - 'Gigabytes' + - 'Terabytes' + - 'Bits' + - 'Kilobits' + - 'Megabits' + - 'Gigabits' + - 'Terabits' + - 'Percent' + - 'Count' + - 'Bytes/Second' + - 'Kilobytes/Second' + - 'Megabytes/Second' + - 'Gigabytes/Second' + - 'Terabytes/Second' + - 'Bits/Second' + - 'Kilobits/Second' + - 'Megabits/Second' + - 'Gigabits/Second' + - 'Terabits/Second' + - 'Count/Second' + - 'None' + description: + description: + - A longer description of the alarm. + required: false + type: str + dimensions: + description: + - A dictionary describing which metric the alarm is applied to. + - 'For more information see the AWS documentation:' + - U(https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Dimension) + required: false + type: dict + alarm_actions: + description: + - A list of the names action(s) taken when the alarm is in the C(alarm) status, denoted as Amazon Resource Name(s). + required: false + type: list + elements: str + insufficient_data_actions: + description: + - A list of the names of action(s) to take when the alarm is in the C(insufficient_data) status. + required: false + type: list + elements: str + ok_actions: + description: + - A list of the names of action(s) to take when the alarm is in the C(ok) status, denoted as Amazon Resource Name(s). + required: false + type: list + elements: str + treat_missing_data: + description: + - Sets how the alarm handles missing data points. + required: false + type: str + choices: + - 'breaching' + - 'notBreaching' + - 'ignore' + - 'missing' + default: 'missing' +extends_documentation_fragment: + - amazon.aws.aws + - amazon.aws.ec2 +''' + +EXAMPLES = r''' + - name: create alarm + community.aws.cloudwatch_metric_alarm: + state: present + region: ap-southeast-2 + name: "cpu-low" + metric: "CPUUtilization" + namespace: "AWS/EC2" + statistic: Average + comparison: "LessThanOrEqualToThreshold" + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: "Percent" + description: "This will alarm when a instance's CPU usage average is lower than 5% for 15 minutes" + dimensions: {'InstanceId':'i-XXX'} + alarm_actions: ["action1","action2"] + + - name: Create an alarm to recover a failed instance + community.aws.cloudwatch_metric_alarm: + state: present + region: us-west-1 + name: "recover-instance" + metric: "StatusCheckFailed_System" + namespace: "AWS/EC2" + statistic: "Minimum" + comparison: "GreaterThanOrEqualToThreshold" + threshold: 1.0 + period: 60 + evaluation_periods: 2 + unit: "Count" + description: "This will recover an instance when it fails" + dimensions: {"InstanceId":'i-XXX'} + alarm_actions: ["arn:aws:automate:us-west-1:ec2:recover"] +''' + +try: + from botocore.exceptions import ClientError +except ImportError: + pass # protected by AnsibleAWSModule + +from ansible_collections.amazon.aws.plugins.module_utils.core import AnsibleAWSModule + + +def create_metric_alarm(connection, module, params): + alarms = connection.describe_alarms(AlarmNames=[params['AlarmName']]) + + if not isinstance(params['Dimensions'], list): + fixed_dimensions = [] + for key, value in params['Dimensions'].items(): + fixed_dimensions.append({'Name': key, 'Value': value}) + params['Dimensions'] = fixed_dimensions + + if not alarms['MetricAlarms']: + try: + if not module.check_mode: + connection.put_metric_alarm(**params) + changed = True + except ClientError as e: + module.fail_json_aws(e) + + else: + changed = False + alarm = alarms['MetricAlarms'][0] + + # Workaround for alarms created before TreatMissingData was introduced + if 'TreatMissingData' not in alarm.keys(): + alarm['TreatMissingData'] = 'missing' + + for key in ['ActionsEnabled', 'StateValue', 'StateReason', + 'StateReasonData', 'StateUpdatedTimestamp', + 'AlarmArn', 'AlarmConfigurationUpdatedTimestamp']: + alarm.pop(key, None) + if alarm != params: + changed = True + alarm = params + + try: + if changed: + if not module.check_mode: + connection.put_metric_alarm(**alarm) + except ClientError as e: + module.fail_json_aws(e) + + try: + alarms = connection.describe_alarms(AlarmNames=[params['AlarmName']]) + except ClientError as e: + module.fail_json_aws(e) + + result = {} + if alarms['MetricAlarms']: + result = alarms['MetricAlarms'][0] + + module.exit_json(changed=changed, + name=result.get('AlarmName'), + actions_enabled=result.get('ActionsEnabled'), + alarm_actions=result.get('AlarmActions'), + alarm_arn=result.get('AlarmArn'), + comparison=result.get('ComparisonOperator'), + description=result.get('AlarmDescription'), + dimensions=result.get('Dimensions'), + evaluation_periods=result.get('EvaluationPeriods'), + insufficient_data_actions=result.get('InsufficientDataActions'), + last_updated=result.get('AlarmConfigurationUpdatedTimestamp'), + metric=result.get('MetricName'), + namespace=result.get('Namespace'), + ok_actions=result.get('OKActions'), + period=result.get('Period'), + state_reason=result.get('StateReason'), + state_value=result.get('StateValue'), + statistic=result.get('Statistic'), + threshold=result.get('Threshold'), + treat_missing_data=result.get('TreatMissingData'), + unit=result.get('Unit')) + + +def delete_metric_alarm(connection, module, params): + alarms = connection.describe_alarms(AlarmNames=[params['AlarmName']]) + + if alarms['MetricAlarms']: + try: + if not module.check_mode: + connection.delete_alarms(AlarmNames=[params['AlarmName']]) + module.exit_json(changed=True) + except (ClientError) as e: + module.fail_json_aws(e) + else: + module.exit_json(changed=False) + + +def main(): + argument_spec = dict( + name=dict(required=True, type='str'), + metric=dict(type='str'), + namespace=dict(type='str'), + statistic=dict(type='str', choices=['SampleCount', 'Average', 'Sum', 'Minimum', 'Maximum']), + comparison=dict(type='str', choices=['LessThanOrEqualToThreshold', 'LessThanThreshold', 'GreaterThanThreshold', + 'GreaterThanOrEqualToThreshold']), + threshold=dict(type='float'), + period=dict(type='int'), + unit=dict(type='str', choices=['Seconds', 'Microseconds', 'Milliseconds', 'Bytes', 'Kilobytes', 'Megabytes', 'Gigabytes', + 'Terabytes', 'Bits', 'Kilobits', 'Megabits', 'Gigabits', 'Terabits', 'Percent', 'Count', + 'Bytes/Second', 'Kilobytes/Second', 'Megabytes/Second', 'Gigabytes/Second', + 'Terabytes/Second', 'Bits/Second', 'Kilobits/Second', 'Megabits/Second', 'Gigabits/Second', + 'Terabits/Second', 'Count/Second', 'None']), + evaluation_periods=dict(type='int'), + description=dict(type='str'), + dimensions=dict(type='dict', default={}), + alarm_actions=dict(type='list', default=[], elements='str'), + insufficient_data_actions=dict(type='list', default=[], elements='str'), + ok_actions=dict(type='list', default=[], elements='str'), + treat_missing_data=dict(type='str', choices=['breaching', 'notBreaching', 'ignore', 'missing'], default='missing'), + state=dict(default='present', choices=['present', 'absent']), + ) + + module = AnsibleAWSModule(argument_spec=argument_spec, supports_check_mode=True) + + state = module.params.get('state') + + params = dict() + params['AlarmName'] = module.params.get('name') + params['MetricName'] = module.params.get('metric') + params['Namespace'] = module.params.get('namespace') + params['Statistic'] = module.params.get('statistic') + params['ComparisonOperator'] = module.params.get('comparison') + params['Threshold'] = module.params.get('threshold') + params['Period'] = module.params.get('period') + params['EvaluationPeriods'] = module.params.get('evaluation_periods') + if module.params.get('unit'): + params['Unit'] = module.params.get('unit') + params['AlarmDescription'] = module.params.get('description') + params['Dimensions'] = module.params.get('dimensions') + params['AlarmActions'] = module.params.get('alarm_actions', []) + params['InsufficientDataActions'] = module.params.get('insufficient_data_actions', []) + params['OKActions'] = module.params.get('ok_actions', []) + params['TreatMissingData'] = module.params.get('treat_missing_data') + + connection = module.client('cloudwatch') + + if state == 'present': + create_metric_alarm(connection, module, params) + elif state == 'absent': + delete_metric_alarm(connection, module, params) + + +if __name__ == '__main__': + main() diff --git a/tests/integration/targets/cloudwatch_metric_alarm/aliases b/tests/integration/targets/cloudwatch_metric_alarm/aliases new file mode 100644 index 00000000000..4ef4b2067d0 --- /dev/null +++ b/tests/integration/targets/cloudwatch_metric_alarm/aliases @@ -0,0 +1 @@ +cloud/aws diff --git a/tests/integration/targets/cloudwatch_metric_alarm/defaults/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/defaults/main.yml new file mode 100644 index 00000000000..af554c5dcef --- /dev/null +++ b/tests/integration/targets/cloudwatch_metric_alarm/defaults/main.yml @@ -0,0 +1,5 @@ +--- +# defaults file for ec2_instance +ec2_instance_name: '{{ resource_prefix }}-node' +ec2_instance_owner: 'integration-run-{{ resource_prefix }}' +alarm_prefix: "ansible-test" diff --git a/tests/integration/targets/cloudwatch_metric_alarm/meta/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/meta/main.yml new file mode 100644 index 00000000000..1471b11f658 --- /dev/null +++ b/tests/integration/targets/cloudwatch_metric_alarm/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: + - setup_ec2_facts diff --git a/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_cleanup.yml b/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_cleanup.yml new file mode 100644 index 00000000000..e90ddc64508 --- /dev/null +++ b/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_cleanup.yml @@ -0,0 +1,94 @@ +- name: remove any instances in the test VPC + ec2_instance: + filters: + vpc_id: "{{ testing_vpc.vpc.id }}" + state: absent + register: removed + until: removed is not failed + ignore_errors: yes + retries: 10 + +- name: remove ENIs + ec2_eni_info: + filters: + vpc-id: "{{ testing_vpc.vpc.id }}" + register: enis + +- name: delete all ENIs + ec2_eni: + eni_id: "{{ item.id }}" + state: absent + until: removed is not failed + with_items: "{{ enis.network_interfaces }}" + ignore_errors: yes + retries: 10 + +- name: remove the security group + ec2_group: + name: "{{ resource_prefix }}-sg" + description: a security group for ansible tests + vpc_id: "{{ testing_vpc.vpc.id }}" + state: absent + register: removed + until: removed is not failed + ignore_errors: yes + retries: 10 + +- name: remove routing rules + ec2_vpc_route_table: + state: absent + vpc_id: "{{ testing_vpc.vpc.id }}" + tags: + created: "{{ resource_prefix }}-route" + routes: + - dest: 0.0.0.0/0 + gateway_id: "{{ igw.gateway_id }}" + subnets: + - "{{ testing_subnet_a.subnet.id }}" + - "{{ testing_subnet_b.subnet.id }}" + register: removed + until: removed is not failed + ignore_errors: yes + retries: 10 + +- name: remove internet gateway + ec2_vpc_igw: + vpc_id: "{{ testing_vpc.vpc.id }}" + state: absent + register: removed + until: removed is not failed + ignore_errors: yes + retries: 10 + +- name: remove subnet A + ec2_vpc_subnet: + state: absent + vpc_id: "{{ testing_vpc.vpc.id }}" + cidr: 10.22.32.0/24 + register: removed + until: removed is not failed + ignore_errors: yes + retries: 10 + +- name: remove subnet B + ec2_vpc_subnet: + state: absent + vpc_id: "{{ testing_vpc.vpc.id }}" + cidr: 10.22.33.0/24 + register: removed + until: removed is not failed + ignore_errors: yes + retries: 10 + +- name: remove the VPC + ec2_vpc_net: + name: "{{ resource_prefix }}-vpc" + cidr_block: 10.22.32.0/23 + state: absent + tags: + Name: Ansible Testing VPC + tenancy: default + register: removed + until: removed is not failed + ignore_errors: yes + retries: 10 diff --git a/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_setup.yml b/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_setup.yml new file mode 100644 index 00000000000..80b49dbcf7e --- /dev/null +++ b/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_setup.yml @@ -0,0 +1,62 @@ +- name: Create VPC for use in testing + ec2_vpc_net: + name: "{{ resource_prefix }}-vpc" + cidr_block: 10.22.32.0/23 + tags: + Name: Ansible ec2_instance Testing VPC + tenancy: default + register: testing_vpc + +- name: Create internet gateway for use in testing + ec2_vpc_igw: + vpc_id: "{{ testing_vpc.vpc.id }}" + state: present + register: igw + +- name: Create default subnet in zone A + ec2_vpc_subnet: + state: present + vpc_id: "{{ testing_vpc.vpc.id }}" + cidr: 10.22.32.0/24 + az: "{{ aws_region }}a" + resource_tags: + Name: "{{ resource_prefix }}-subnet-a" + register: testing_subnet_a + +- name: Create secondary subnet in zone B + ec2_vpc_subnet: + state: present + vpc_id: "{{ testing_vpc.vpc.id }}" + cidr: 10.22.33.0/24 + az: "{{ aws_region }}b" + resource_tags: + Name: "{{ resource_prefix }}-subnet-b" + register: testing_subnet_b + +- name: create routing rules + ec2_vpc_route_table: + vpc_id: "{{ testing_vpc.vpc.id }}" + tags: + created: "{{ resource_prefix }}-route" + routes: + - dest: 0.0.0.0/0 + gateway_id: "{{ igw.gateway_id }}" + subnets: + - "{{ testing_subnet_a.subnet.id }}" + - "{{ testing_subnet_b.subnet.id }}" + +- name: create a security group with the vpc + ec2_group: + name: "{{ resource_prefix }}-sg" + description: a security group for ansible tests + vpc_id: "{{ testing_vpc.vpc.id }}" + rules: + - proto: tcp + from_port: 22 + to_port: 22 + cidr_ip: 0.0.0.0/0 + - proto: tcp + from_port: 80 + to_port: 80 + cidr_ip: 0.0.0.0/0 + register: sg diff --git a/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml new file mode 100644 index 00000000000..3503edeb694 --- /dev/null +++ b/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml @@ -0,0 +1,467 @@ +- name: run ec2_metric_alarm tests + module_defaults: + group/aws: + aws_access_key: "{{ aws_access_key }}" + aws_secret_key: "{{ aws_secret_key }}" + security_token: "{{ security_token | default(omit) }}" + region: "{{ aws_region }}" + collections: + - amazon.aws + + block: + - set_fact: + alarm_full_name: "{{ alarm_prefix }}-{{ resource_prefix }}-cpu-low" + + - name: set up environment for testing. + include_tasks: env_setup.yml + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query + + - name: Make instance in a default subnet of the VPC + ec2_instance: + name: "{{ resource_prefix }}-test-default-vpc" + image_id: "{{ ec2_ami_id }}" + tags: + TestId: "{{ resource_prefix }}" + security_groups: "{{ sg.group_id }}" + vpc_subnet_id: "{{ testing_subnet_a.subnet.id }}" + instance_type: t2.micro + wait: true + register: ec2_instance_results + + - name: ensure alarm doesn't exist for a clean test + ec2_metric_alarm: + state: absent + name: "{{ alarm_full_name }}" + + - name: create ec2 metric alarm on ec2 instance (check mode) + ec2_metric_alarm: + dimensions: + InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" + state: present + name: "{{ alarm_full_name }}" + metric: "CPUUtilization" + namespace: "AWS/EC2" + treat_missing_data: missing + statistic: Average + comparison: "LessThanOrEqualToThreshold" + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: "Percent" + description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" + check_mode: true + register: ec2_instance_metric_alarm_check + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query_check + + - name: convert it to an object + set_fact: + alarm_info_check: "{{ alarm_info_query_check.stdout | from_json }}" + + - name: "verify that an alarm was not created in check mode" + assert: + that: + - 'ec2_instance_metric_alarm_check.changed' + - 'not ec2_instance_metric_alarm_check.alarm_arn' + - 'alarm_info_check["MetricAlarms"] | length == 0' + + - name: create ec2 metric alarm on ec2 instance + ec2_metric_alarm: + dimensions: + InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" + state: present + name: "{{ alarm_full_name }}" + metric: "CPUUtilization" + namespace: "AWS/EC2" + treat_missing_data: missing + statistic: Average + comparison: "LessThanOrEqualToThreshold" + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: "Percent" + description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" + register: ec2_instance_metric_alarm + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query + + - name: convert it to an object + set_fact: + alarm_info: "{{ alarm_info_query.stdout | from_json }}" + + - name: "verify that an alarm was created" + assert: + that: + - 'ec2_instance_metric_alarm.changed' + - 'ec2_instance_metric_alarm.alarm_arn' + - 'ec2_instance_metric_alarm.statistic == alarm_info["MetricAlarms"][0].Statistic' + - 'ec2_instance_metric_alarm.name == alarm_info["MetricAlarms"][0].AlarmName' + - 'ec2_instance_metric_alarm.metric == alarm_info["MetricAlarms"][0].MetricName' + - 'ec2_instance_metric_alarm.namespace == alarm_info["MetricAlarms"][0].Namespace' + - 'ec2_instance_metric_alarm.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator' + - 'ec2_instance_metric_alarm.threshold == alarm_info["MetricAlarms"][0].Threshold' + - 'ec2_instance_metric_alarm.period == alarm_info["MetricAlarms"][0].Period' + - 'ec2_instance_metric_alarm.unit == alarm_info["MetricAlarms"][0].Unit' + - 'ec2_instance_metric_alarm.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods' + - 'ec2_instance_metric_alarm.description == alarm_info["MetricAlarms"][0].AlarmDescription' + - 'ec2_instance_metric_alarm.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData' + + - name: create ec2 metric alarm on ec2 instance (idempotent) (check mode) + ec2_metric_alarm: + dimensions: + InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" + state: present + name: "{{ alarm_full_name }}" + metric: "CPUUtilization" + namespace: "AWS/EC2" + treat_missing_data: missing + statistic: Average + comparison: "LessThanOrEqualToThreshold" + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: "Percent" + description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" + check_mode: true + register: ec2_instance_metric_alarm_idempotent_check + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query_idempotent_check + + - name: convert it to an object + set_fact: + alarm_info_idempotent_check: "{{ alarm_info_query_idempotent_check.stdout | from_json }}" + + - name: "Verify alarm does not register as changed after update in check mode" + assert: + that: + - not ec2_instance_metric_alarm_idempotent_check.changed + + - name: "Verify alarm did not change after updating in check mode" + assert: + that: + - "alarm_info['MetricAlarms'][0]['{{item}}'] == alarm_info_idempotent_check['MetricAlarms'][0]['{{ item }}']" + with_items: + - AlarmArn + - Statistic + - AlarmName + - MetricName + - Namespace + - ComparisonOperator + - Threshold + - Period + - Unit + - EvaluationPeriods + - AlarmDescription + - TreatMissingData + + - name: create ec2 metric alarm on ec2 instance (idempotent) + ec2_metric_alarm: + dimensions: + InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" + state: present + name: "{{ alarm_full_name }}" + metric: "CPUUtilization" + namespace: "AWS/EC2" + treat_missing_data: missing + statistic: Average + comparison: "LessThanOrEqualToThreshold" + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: "Percent" + description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" + register: ec2_instance_metric_alarm_idempotent + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query_idempotent + + - name: convert it to an object + set_fact: + alarm_info_idempotent: "{{ alarm_info_query_idempotent.stdout | from_json }}" + + - name: "Verify alarm does not register as changed after update" + assert: + that: + - not ec2_instance_metric_alarm_idempotent.changed + + - name: "Verify alarm did not change after updating" + assert: + that: + - "alarm_info['MetricAlarms'][0]['{{item}}'] == alarm_info_idempotent['MetricAlarms'][0]['{{ item }}']" + with_items: + - AlarmArn + - Statistic + - AlarmName + - MetricName + - Namespace + - ComparisonOperator + - Threshold + - Period + - Unit + - EvaluationPeriods + - AlarmDescription + - TreatMissingData + + - name: update alarm (check mode) + ec2_metric_alarm: + dimensions: + InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" + state: present + name: "{{ alarm_full_name }}" + metric: "CPUUtilization" + namespace: "AWS/EC2" + statistic: Average + comparison: "LessThanOrEqualToThreshold" + threshold: 5.0 + period: 60 + evaluation_periods: 3 + unit: "Percent" + description: "This will alarm when an instance's cpu usage average is lower than 5% for 3 minutes" + check_mode: true + register: ec2_instance_metric_alarm_update_check + + - name: "verify that alarm registers as updated in check mode" + assert: + that: + - 'ec2_instance_metric_alarm_check.changed' + + - name: "verify that properties were not changed in check mode" + assert: + that: + - 'ec2_instance_metric_alarm_update_check.changed' + - 'ec2_instance_metric_alarm_update_check.period == alarm_info["MetricAlarms"][0].Period' # Period of actual alarm should not change + - 'ec2_instance_metric_alarm_update_check.alarm_arn == ec2_instance_metric_alarm.alarm_arn' + - 'ec2_instance_metric_alarm_update_check.statistic == alarm_info["MetricAlarms"][0].Statistic' + - 'ec2_instance_metric_alarm_update_check.name == alarm_info["MetricAlarms"][0].AlarmName' + - 'ec2_instance_metric_alarm_update_check.metric == alarm_info["MetricAlarms"][0].MetricName' + - 'ec2_instance_metric_alarm_update_check.namespace == alarm_info["MetricAlarms"][0].Namespace' + - 'ec2_instance_metric_alarm_update_check.statistic == alarm_info["MetricAlarms"][0].Statistic' + - 'ec2_instance_metric_alarm_update_check.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator' + - 'ec2_instance_metric_alarm_update_check.threshold == alarm_info["MetricAlarms"][0].Threshold' + - 'ec2_instance_metric_alarm_update_check.unit == alarm_info["MetricAlarms"][0].Unit' + - 'ec2_instance_metric_alarm_update_check.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods' + - 'ec2_instance_metric_alarm_update_check.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData' + + - name: update alarm + ec2_metric_alarm: + dimensions: + InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" + state: present + name: "{{ alarm_full_name }}" + metric: "CPUUtilization" + namespace: "AWS/EC2" + statistic: Average + comparison: "LessThanOrEqualToThreshold" + threshold: 5.0 + period: 60 + evaluation_periods: 3 + unit: "Percent" + description: "This will alarm when an instance's cpu usage average is lower than 5% for 3 minutes" + register: ec2_instance_metric_alarm_update + + - name: "verify that alarm registers as updated" + assert: + that: + - 'ec2_instance_metric_alarm.changed' + + - name: "verify that properties were changed" + assert: + that: + - '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["MetricAlarms"][0].Statistic' + - 'ec2_instance_metric_alarm_update.name == alarm_info["MetricAlarms"][0].AlarmName' + - 'ec2_instance_metric_alarm_update.metric == alarm_info["MetricAlarms"][0].MetricName' + - 'ec2_instance_metric_alarm_update.namespace == alarm_info["MetricAlarms"][0].Namespace' + - 'ec2_instance_metric_alarm_update.statistic == alarm_info["MetricAlarms"][0].Statistic' + - 'ec2_instance_metric_alarm_update.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator' + - 'ec2_instance_metric_alarm_update.threshold == alarm_info["MetricAlarms"][0].Threshold' + - 'ec2_instance_metric_alarm_update.unit == alarm_info["MetricAlarms"][0].Unit' + - 'ec2_instance_metric_alarm_update.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods' + - 'ec2_instance_metric_alarm_update.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData' + + - name: try to remove the alarm (check mode) + ec2_metric_alarm: + state: absent + name: "{{ alarm_full_name }}" + check_mode: true + register: ec2_instance_metric_alarm_deletion_check + + - name: Verify that the alarm reports deleted/changed + assert: + that: + - 'ec2_instance_metric_alarm_deletion_check.changed' + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query_check + + - name: convert it to an object + set_fact: + alarm_info: "{{ alarm_info_query_check.stdout | from_json }}" + + - name: Verify that the alarm was not deleted in check mode using cli + assert: + that: + - 'alarm_info["MetricAlarms"] | length > 0' + + - name: try to remove the alarm + ec2_metric_alarm: + state: absent + name: "{{ alarm_full_name }}" + register: ec2_instance_metric_alarm_deletion + + - name: Verify that the alarm reports deleted/changed + assert: + that: + - 'ec2_instance_metric_alarm_deletion.changed' + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query + + - name: convert it to an object + set_fact: + alarm_info: "{{ alarm_info_query.stdout | from_json }}" + + - name: Verify that the alarm was deleted using cli + assert: + that: + - 'alarm_info["MetricAlarms"] | length == 0' + + - name: create ec2 metric alarm with no unit on ec2 instance + ec2_metric_alarm: + dimensions: + InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" + state: present + name: "{{ alarm_full_name }}" + metric: "CPUUtilization" + namespace: "AWS/EC2" + treat_missing_data: missing + statistic: Average + comparison: "LessThanOrEqualToThreshold" + threshold: 5.0 + period: 300 + evaluation_periods: 3 + description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" + register: ec2_instance_metric_alarm_no_unit + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query_no_unit + + - name: convert it to an object + set_fact: + alarm_info_no_unit: "{{ alarm_info_query_no_unit.stdout | from_json }}" + + - name: "verify that an alarm was created" + assert: + that: + - 'ec2_instance_metric_alarm_no_unit.changed' + - 'ec2_instance_metric_alarm_no_unit.alarm_arn' + - 'ec2_instance_metric_alarm_no_unit.statistic == alarm_info_no_unit["MetricAlarms"][0].Statistic' + - 'ec2_instance_metric_alarm_no_unit.name == alarm_info_no_unit["MetricAlarms"][0].AlarmName' + - 'ec2_instance_metric_alarm_no_unit.metric == alarm_info_no_unit["MetricAlarms"][0].MetricName' + - 'ec2_instance_metric_alarm_no_unit.namespace == alarm_info_no_unit["MetricAlarms"][0].Namespace' + - 'ec2_instance_metric_alarm_no_unit.comparison == alarm_info_no_unit["MetricAlarms"][0].ComparisonOperator' + - 'ec2_instance_metric_alarm_no_unit.threshold == alarm_info_no_unit["MetricAlarms"][0].Threshold' + - 'ec2_instance_metric_alarm_no_unit.period == alarm_info_no_unit["MetricAlarms"][0].Period' + - 'alarm_info_no_unit["MetricAlarms"][0].Unit is not defined' + - 'ec2_instance_metric_alarm_no_unit.evaluation_periods == alarm_info_no_unit["MetricAlarms"][0].EvaluationPeriods' + - 'ec2_instance_metric_alarm_no_unit.description == alarm_info_no_unit["MetricAlarms"][0].AlarmDescription' + - 'ec2_instance_metric_alarm_no_unit.treat_missing_data == alarm_info_no_unit["MetricAlarms"][0].TreatMissingData' + + - name: try to remove the alarm + ec2_metric_alarm: + state: absent + name: "{{ alarm_full_name }}" + register: ec2_instance_metric_alarm_deletion_no_unit + + - name: Verify that the alarm reports deleted/changed + assert: + that: + - 'ec2_instance_metric_alarm_deletion_no_unit.changed' + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" + AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: "{{ aws_region }}" + register: alarm_info_query_no_unit + + - name: convert it to an object + set_fact: + alarm_info_no_unit: "{{ alarm_info_query_no_unit.stdout | from_json }}" + + - name: Verify that the alarm was deleted using cli + assert: + that: + - 'alarm_info_no_unit["MetricAlarms"] | length == 0' + + always: + - name: try to delete the alarm + ec2_metric_alarm: + state: absent + name: "{{ alarm_full_name }}" + ignore_errors: true + + - name: try to stop the ec2 instance + ec2_instance: + instance_ids: "{{ ec2_instance_results.instances[0].instance_id }}" + state: terminated + ignore_errors: true + + - include_tasks: env_cleanup.yml diff --git a/tests/integration/targets/cloudwatch_metric_alarm/vars/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/vars/main.yml new file mode 100644 index 00000000000..ed97d539c09 --- /dev/null +++ b/tests/integration/targets/cloudwatch_metric_alarm/vars/main.yml @@ -0,0 +1 @@ +--- From 2793713f951e7455fb41715a12394d65334980ec Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 16 Sep 2022 18:18:52 +0200 Subject: [PATCH 2/8] Update runtime --- meta/runtime.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/meta/runtime.yml b/meta/runtime.yml index 4588e7e1071..9671892aad0 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -9,6 +9,7 @@ action_groups: - cloudformation_info - cloudtrail - cloudwatchevent_rule + - cloudwatch_metric_alarm - cloudwatchlogs_log_group - cloudwatchlogs_log_group_info - cloudwatchlogs_log_group_metric_filter @@ -81,6 +82,9 @@ plugin_routing: ec2_group_info: # Deprecation for this alias should not *start* prior to 2024-09-01 redirect: amazon.aws.ec2_security_group_info + ec2_metric_alarm: + # Deprecation for this alias should not *start* prior to 2024-09-01 + redirect: amazon.aws.cloudwatch_metric_alarm execute_lambda: # Deprecation for this alias should not *start* prior to 2024-09-01 redirect: amazon.aws.lambda_execute From a39e1380a65796c072a6d3fd8d39ae984fab8ad6 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 16 Sep 2022 18:18:53 +0200 Subject: [PATCH 3/8] Update FQDN --- plugins/modules/cloudwatch_metric_alarm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/cloudwatch_metric_alarm.py b/plugins/modules/cloudwatch_metric_alarm.py index dbe6bf43f94..3462d9aa74a 100644 --- a/plugins/modules/cloudwatch_metric_alarm.py +++ b/plugins/modules/cloudwatch_metric_alarm.py @@ -165,7 +165,7 @@ EXAMPLES = r''' - name: create alarm - community.aws.cloudwatch_metric_alarm: + amazon.aws.cloudwatch_metric_alarm: state: present region: ap-southeast-2 name: "cpu-low" @@ -182,7 +182,7 @@ alarm_actions: ["action1","action2"] - name: Create an alarm to recover a failed instance - community.aws.cloudwatch_metric_alarm: + amazon.aws.cloudwatch_metric_alarm: state: present region: us-west-1 name: "recover-instance" From 4aa4cccdf34aaad633e5b4cd550e28a8877c4e6a Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 16 Sep 2022 18:18:53 +0200 Subject: [PATCH 4/8] Remove collection reference inside the tests --- .../cloudwatch_metric_alarm/defaults/main.yml | 5 +- .../cloudwatch_metric_alarm/meta/main.yml | 2 +- .../tasks/env_cleanup.yml | 32 +- .../tasks/env_setup.yml | 48 +- .../cloudwatch_metric_alarm/tasks/main.yml | 929 +++++++++--------- 5 files changed, 511 insertions(+), 505 deletions(-) diff --git a/tests/integration/targets/cloudwatch_metric_alarm/defaults/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/defaults/main.yml index af554c5dcef..f65410b9523 100644 --- a/tests/integration/targets/cloudwatch_metric_alarm/defaults/main.yml +++ b/tests/integration/targets/cloudwatch_metric_alarm/defaults/main.yml @@ -1,5 +1,4 @@ ---- # defaults file for ec2_instance ec2_instance_name: '{{ resource_prefix }}-node' -ec2_instance_owner: 'integration-run-{{ resource_prefix }}' -alarm_prefix: "ansible-test" +ec2_instance_owner: integration-run-{{ resource_prefix }} +alarm_prefix: ansible-test diff --git a/tests/integration/targets/cloudwatch_metric_alarm/meta/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/meta/main.yml index 1471b11f658..1d40168d0ba 100644 --- a/tests/integration/targets/cloudwatch_metric_alarm/meta/main.yml +++ b/tests/integration/targets/cloudwatch_metric_alarm/meta/main.yml @@ -1,2 +1,2 @@ dependencies: - - setup_ec2_facts +- setup_ec2_facts diff --git a/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_cleanup.yml b/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_cleanup.yml index e90ddc64508..104f5798464 100644 --- a/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_cleanup.yml +++ b/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_cleanup.yml @@ -1,7 +1,7 @@ - name: remove any instances in the test VPC ec2_instance: filters: - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' state: absent register: removed until: removed is not failed @@ -11,23 +11,23 @@ - name: remove ENIs ec2_eni_info: filters: - vpc-id: "{{ testing_vpc.vpc.id }}" + vpc-id: '{{ testing_vpc.vpc.id }}' register: enis - name: delete all ENIs ec2_eni: - eni_id: "{{ item.id }}" + eni_id: '{{ item.id }}' state: absent until: removed is not failed - with_items: "{{ enis.network_interfaces }}" + with_items: '{{ enis.network_interfaces }}' ignore_errors: yes retries: 10 - name: remove the security group ec2_group: - name: "{{ resource_prefix }}-sg" + name: '{{ resource_prefix }}-sg' description: a security group for ansible tests - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' state: absent register: removed until: removed is not failed @@ -37,15 +37,15 @@ - name: remove routing rules ec2_vpc_route_table: state: absent - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' tags: - created: "{{ resource_prefix }}-route" + created: '{{ resource_prefix }}-route' routes: - - dest: 0.0.0.0/0 - gateway_id: "{{ igw.gateway_id }}" + - dest: 0.0.0.0/0 + gateway_id: '{{ igw.gateway_id }}' subnets: - - "{{ testing_subnet_a.subnet.id }}" - - "{{ testing_subnet_b.subnet.id }}" + - '{{ testing_subnet_a.subnet.id }}' + - '{{ testing_subnet_b.subnet.id }}' register: removed until: removed is not failed ignore_errors: yes @@ -53,7 +53,7 @@ - name: remove internet gateway ec2_vpc_igw: - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' state: absent register: removed until: removed is not failed @@ -63,7 +63,7 @@ - name: remove subnet A ec2_vpc_subnet: state: absent - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' cidr: 10.22.32.0/24 register: removed until: removed is not failed @@ -73,7 +73,7 @@ - name: remove subnet B ec2_vpc_subnet: state: absent - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' cidr: 10.22.33.0/24 register: removed until: removed is not failed @@ -82,7 +82,7 @@ - name: remove the VPC ec2_vpc_net: - name: "{{ resource_prefix }}-vpc" + name: '{{ resource_prefix }}-vpc' cidr_block: 10.22.32.0/23 state: absent tags: diff --git a/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_setup.yml b/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_setup.yml index 80b49dbcf7e..2153d876adb 100644 --- a/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_setup.yml +++ b/tests/integration/targets/cloudwatch_metric_alarm/tasks/env_setup.yml @@ -1,6 +1,6 @@ - name: Create VPC for use in testing ec2_vpc_net: - name: "{{ resource_prefix }}-vpc" + name: '{{ resource_prefix }}-vpc' cidr_block: 10.22.32.0/23 tags: Name: Ansible ec2_instance Testing VPC @@ -9,54 +9,54 @@ - name: Create internet gateway for use in testing ec2_vpc_igw: - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' state: present register: igw - name: Create default subnet in zone A ec2_vpc_subnet: state: present - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' cidr: 10.22.32.0/24 - az: "{{ aws_region }}a" + az: '{{ aws_region }}a' resource_tags: - Name: "{{ resource_prefix }}-subnet-a" + Name: '{{ resource_prefix }}-subnet-a' register: testing_subnet_a - name: Create secondary subnet in zone B ec2_vpc_subnet: state: present - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' cidr: 10.22.33.0/24 - az: "{{ aws_region }}b" + az: '{{ aws_region }}b' resource_tags: - Name: "{{ resource_prefix }}-subnet-b" + Name: '{{ resource_prefix }}-subnet-b' register: testing_subnet_b - name: create routing rules ec2_vpc_route_table: - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' tags: - created: "{{ resource_prefix }}-route" + created: '{{ resource_prefix }}-route' routes: - - dest: 0.0.0.0/0 - gateway_id: "{{ igw.gateway_id }}" + - dest: 0.0.0.0/0 + gateway_id: '{{ igw.gateway_id }}' subnets: - - "{{ testing_subnet_a.subnet.id }}" - - "{{ testing_subnet_b.subnet.id }}" + - '{{ testing_subnet_a.subnet.id }}' + - '{{ testing_subnet_b.subnet.id }}' - name: create a security group with the vpc ec2_group: - name: "{{ resource_prefix }}-sg" + name: '{{ resource_prefix }}-sg' description: a security group for ansible tests - vpc_id: "{{ testing_vpc.vpc.id }}" + vpc_id: '{{ testing_vpc.vpc.id }}' rules: - - proto: tcp - from_port: 22 - to_port: 22 - cidr_ip: 0.0.0.0/0 - - proto: tcp - from_port: 80 - to_port: 80 - cidr_ip: 0.0.0.0/0 + - proto: tcp + from_port: 22 + to_port: 22 + cidr_ip: 0.0.0.0/0 + - proto: tcp + from_port: 80 + to_port: 80 + cidr_ip: 0.0.0.0/0 register: sg diff --git a/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml index 3503edeb694..f713f973251 100644 --- a/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml +++ b/tests/integration/targets/cloudwatch_metric_alarm/tasks/main.yml @@ -1,467 +1,474 @@ - name: run ec2_metric_alarm tests module_defaults: group/aws: - aws_access_key: "{{ aws_access_key }}" - aws_secret_key: "{{ aws_secret_key }}" - security_token: "{{ security_token | default(omit) }}" - region: "{{ aws_region }}" - collections: - - amazon.aws - + aws_access_key: '{{ aws_access_key }}' + aws_secret_key: '{{ aws_secret_key }}' + security_token: '{{ security_token | default(omit) }}' + region: '{{ aws_region }}' block: - - set_fact: - alarm_full_name: "{{ alarm_prefix }}-{{ resource_prefix }}-cpu-low" - - - name: set up environment for testing. - include_tasks: env_setup.yml - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query - - - name: Make instance in a default subnet of the VPC - ec2_instance: - name: "{{ resource_prefix }}-test-default-vpc" - image_id: "{{ ec2_ami_id }}" - tags: - TestId: "{{ resource_prefix }}" - security_groups: "{{ sg.group_id }}" - vpc_subnet_id: "{{ testing_subnet_a.subnet.id }}" - instance_type: t2.micro - wait: true - register: ec2_instance_results - - - name: ensure alarm doesn't exist for a clean test - ec2_metric_alarm: - state: absent - name: "{{ alarm_full_name }}" - - - name: create ec2 metric alarm on ec2 instance (check mode) - ec2_metric_alarm: - dimensions: - InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" - state: present - name: "{{ alarm_full_name }}" - metric: "CPUUtilization" - namespace: "AWS/EC2" - treat_missing_data: missing - statistic: Average - comparison: "LessThanOrEqualToThreshold" - threshold: 5.0 - period: 300 - evaluation_periods: 3 - unit: "Percent" - description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" - check_mode: true - register: ec2_instance_metric_alarm_check - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query_check - - - name: convert it to an object - set_fact: - alarm_info_check: "{{ alarm_info_query_check.stdout | from_json }}" - - - name: "verify that an alarm was not created in check mode" - assert: - that: - - 'ec2_instance_metric_alarm_check.changed' - - 'not ec2_instance_metric_alarm_check.alarm_arn' - - 'alarm_info_check["MetricAlarms"] | length == 0' - - - name: create ec2 metric alarm on ec2 instance - ec2_metric_alarm: - dimensions: - InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" - state: present - name: "{{ alarm_full_name }}" - metric: "CPUUtilization" - namespace: "AWS/EC2" - treat_missing_data: missing - statistic: Average - comparison: "LessThanOrEqualToThreshold" - threshold: 5.0 - period: 300 - evaluation_periods: 3 - unit: "Percent" - description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" - register: ec2_instance_metric_alarm - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query - - - name: convert it to an object - set_fact: - alarm_info: "{{ alarm_info_query.stdout | from_json }}" - - - name: "verify that an alarm was created" - assert: - that: - - 'ec2_instance_metric_alarm.changed' - - 'ec2_instance_metric_alarm.alarm_arn' - - 'ec2_instance_metric_alarm.statistic == alarm_info["MetricAlarms"][0].Statistic' - - 'ec2_instance_metric_alarm.name == alarm_info["MetricAlarms"][0].AlarmName' - - 'ec2_instance_metric_alarm.metric == alarm_info["MetricAlarms"][0].MetricName' - - 'ec2_instance_metric_alarm.namespace == alarm_info["MetricAlarms"][0].Namespace' - - 'ec2_instance_metric_alarm.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator' - - 'ec2_instance_metric_alarm.threshold == alarm_info["MetricAlarms"][0].Threshold' - - 'ec2_instance_metric_alarm.period == alarm_info["MetricAlarms"][0].Period' - - 'ec2_instance_metric_alarm.unit == alarm_info["MetricAlarms"][0].Unit' - - 'ec2_instance_metric_alarm.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods' - - 'ec2_instance_metric_alarm.description == alarm_info["MetricAlarms"][0].AlarmDescription' - - 'ec2_instance_metric_alarm.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData' - - - name: create ec2 metric alarm on ec2 instance (idempotent) (check mode) - ec2_metric_alarm: - dimensions: - InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" - state: present - name: "{{ alarm_full_name }}" - metric: "CPUUtilization" - namespace: "AWS/EC2" - treat_missing_data: missing - statistic: Average - comparison: "LessThanOrEqualToThreshold" - threshold: 5.0 - period: 300 - evaluation_periods: 3 - unit: "Percent" - description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" - check_mode: true - register: ec2_instance_metric_alarm_idempotent_check - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query_idempotent_check - - - name: convert it to an object - set_fact: - alarm_info_idempotent_check: "{{ alarm_info_query_idempotent_check.stdout | from_json }}" - - - name: "Verify alarm does not register as changed after update in check mode" - assert: - that: - - not ec2_instance_metric_alarm_idempotent_check.changed - - - name: "Verify alarm did not change after updating in check mode" - assert: - that: - - "alarm_info['MetricAlarms'][0]['{{item}}'] == alarm_info_idempotent_check['MetricAlarms'][0]['{{ item }}']" - with_items: - - AlarmArn - - Statistic - - AlarmName - - MetricName - - Namespace - - ComparisonOperator - - Threshold - - Period - - Unit - - EvaluationPeriods - - AlarmDescription - - TreatMissingData - - - name: create ec2 metric alarm on ec2 instance (idempotent) - ec2_metric_alarm: - dimensions: - InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" - state: present - name: "{{ alarm_full_name }}" - metric: "CPUUtilization" - namespace: "AWS/EC2" - treat_missing_data: missing - statistic: Average - comparison: "LessThanOrEqualToThreshold" - threshold: 5.0 - period: 300 - evaluation_periods: 3 - unit: "Percent" - description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" - register: ec2_instance_metric_alarm_idempotent - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query_idempotent - - - name: convert it to an object - set_fact: - alarm_info_idempotent: "{{ alarm_info_query_idempotent.stdout | from_json }}" - - - name: "Verify alarm does not register as changed after update" - assert: - that: - - not ec2_instance_metric_alarm_idempotent.changed - - - name: "Verify alarm did not change after updating" - assert: - that: - - "alarm_info['MetricAlarms'][0]['{{item}}'] == alarm_info_idempotent['MetricAlarms'][0]['{{ item }}']" - with_items: - - AlarmArn - - Statistic - - AlarmName - - MetricName - - Namespace - - ComparisonOperator - - Threshold - - Period - - Unit - - EvaluationPeriods - - AlarmDescription - - TreatMissingData - - - name: update alarm (check mode) - ec2_metric_alarm: - dimensions: - InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" - state: present - name: "{{ alarm_full_name }}" - metric: "CPUUtilization" - namespace: "AWS/EC2" - statistic: Average - comparison: "LessThanOrEqualToThreshold" - threshold: 5.0 - period: 60 - evaluation_periods: 3 - unit: "Percent" - description: "This will alarm when an instance's cpu usage average is lower than 5% for 3 minutes" - check_mode: true - register: ec2_instance_metric_alarm_update_check - - - name: "verify that alarm registers as updated in check mode" - assert: - that: - - 'ec2_instance_metric_alarm_check.changed' - - - name: "verify that properties were not changed in check mode" - assert: - that: - - 'ec2_instance_metric_alarm_update_check.changed' - - 'ec2_instance_metric_alarm_update_check.period == alarm_info["MetricAlarms"][0].Period' # Period of actual alarm should not change - - 'ec2_instance_metric_alarm_update_check.alarm_arn == ec2_instance_metric_alarm.alarm_arn' - - 'ec2_instance_metric_alarm_update_check.statistic == alarm_info["MetricAlarms"][0].Statistic' - - 'ec2_instance_metric_alarm_update_check.name == alarm_info["MetricAlarms"][0].AlarmName' - - 'ec2_instance_metric_alarm_update_check.metric == alarm_info["MetricAlarms"][0].MetricName' - - 'ec2_instance_metric_alarm_update_check.namespace == alarm_info["MetricAlarms"][0].Namespace' - - 'ec2_instance_metric_alarm_update_check.statistic == alarm_info["MetricAlarms"][0].Statistic' - - 'ec2_instance_metric_alarm_update_check.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator' - - 'ec2_instance_metric_alarm_update_check.threshold == alarm_info["MetricAlarms"][0].Threshold' - - 'ec2_instance_metric_alarm_update_check.unit == alarm_info["MetricAlarms"][0].Unit' - - 'ec2_instance_metric_alarm_update_check.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods' - - 'ec2_instance_metric_alarm_update_check.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData' - - - name: update alarm - ec2_metric_alarm: - dimensions: - InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" - state: present - name: "{{ alarm_full_name }}" - metric: "CPUUtilization" - namespace: "AWS/EC2" - statistic: Average - comparison: "LessThanOrEqualToThreshold" - threshold: 5.0 - period: 60 - evaluation_periods: 3 - unit: "Percent" - description: "This will alarm when an instance's cpu usage average is lower than 5% for 3 minutes" - register: ec2_instance_metric_alarm_update - - - name: "verify that alarm registers as updated" - assert: - that: - - 'ec2_instance_metric_alarm.changed' - - - name: "verify that properties were changed" - assert: - that: - - '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["MetricAlarms"][0].Statistic' - - 'ec2_instance_metric_alarm_update.name == alarm_info["MetricAlarms"][0].AlarmName' - - 'ec2_instance_metric_alarm_update.metric == alarm_info["MetricAlarms"][0].MetricName' - - 'ec2_instance_metric_alarm_update.namespace == alarm_info["MetricAlarms"][0].Namespace' - - 'ec2_instance_metric_alarm_update.statistic == alarm_info["MetricAlarms"][0].Statistic' - - 'ec2_instance_metric_alarm_update.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator' - - 'ec2_instance_metric_alarm_update.threshold == alarm_info["MetricAlarms"][0].Threshold' - - 'ec2_instance_metric_alarm_update.unit == alarm_info["MetricAlarms"][0].Unit' - - 'ec2_instance_metric_alarm_update.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods' - - 'ec2_instance_metric_alarm_update.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData' - - - name: try to remove the alarm (check mode) - ec2_metric_alarm: - state: absent - name: "{{ alarm_full_name }}" - check_mode: true - register: ec2_instance_metric_alarm_deletion_check - - - name: Verify that the alarm reports deleted/changed - assert: - that: - - 'ec2_instance_metric_alarm_deletion_check.changed' - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query_check - - - name: convert it to an object - set_fact: - alarm_info: "{{ alarm_info_query_check.stdout | from_json }}" - - - name: Verify that the alarm was not deleted in check mode using cli - assert: - that: - - 'alarm_info["MetricAlarms"] | length > 0' - - - name: try to remove the alarm - ec2_metric_alarm: - state: absent - name: "{{ alarm_full_name }}" - register: ec2_instance_metric_alarm_deletion - - - name: Verify that the alarm reports deleted/changed - assert: - that: - - 'ec2_instance_metric_alarm_deletion.changed' - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query - - - name: convert it to an object - set_fact: - alarm_info: "{{ alarm_info_query.stdout | from_json }}" - - - name: Verify that the alarm was deleted using cli - assert: - that: - - 'alarm_info["MetricAlarms"] | length == 0' - - - name: create ec2 metric alarm with no unit on ec2 instance - ec2_metric_alarm: - dimensions: - InstanceId: "{{ ec2_instance_results.instances[0].instance_id }}" - state: present - name: "{{ alarm_full_name }}" - metric: "CPUUtilization" - namespace: "AWS/EC2" - treat_missing_data: missing - statistic: Average - comparison: "LessThanOrEqualToThreshold" - threshold: 5.0 - period: 300 - evaluation_periods: 3 - description: "This will alarm when an instance's cpu usage average is lower than 5% for 15 minutes" - register: ec2_instance_metric_alarm_no_unit - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query_no_unit - - - name: convert it to an object - set_fact: - alarm_info_no_unit: "{{ alarm_info_query_no_unit.stdout | from_json }}" - - - name: "verify that an alarm was created" - assert: - that: - - 'ec2_instance_metric_alarm_no_unit.changed' - - 'ec2_instance_metric_alarm_no_unit.alarm_arn' - - 'ec2_instance_metric_alarm_no_unit.statistic == alarm_info_no_unit["MetricAlarms"][0].Statistic' - - 'ec2_instance_metric_alarm_no_unit.name == alarm_info_no_unit["MetricAlarms"][0].AlarmName' - - 'ec2_instance_metric_alarm_no_unit.metric == alarm_info_no_unit["MetricAlarms"][0].MetricName' - - 'ec2_instance_metric_alarm_no_unit.namespace == alarm_info_no_unit["MetricAlarms"][0].Namespace' - - 'ec2_instance_metric_alarm_no_unit.comparison == alarm_info_no_unit["MetricAlarms"][0].ComparisonOperator' - - 'ec2_instance_metric_alarm_no_unit.threshold == alarm_info_no_unit["MetricAlarms"][0].Threshold' - - 'ec2_instance_metric_alarm_no_unit.period == alarm_info_no_unit["MetricAlarms"][0].Period' - - 'alarm_info_no_unit["MetricAlarms"][0].Unit is not defined' - - 'ec2_instance_metric_alarm_no_unit.evaluation_periods == alarm_info_no_unit["MetricAlarms"][0].EvaluationPeriods' - - 'ec2_instance_metric_alarm_no_unit.description == alarm_info_no_unit["MetricAlarms"][0].AlarmDescription' - - 'ec2_instance_metric_alarm_no_unit.treat_missing_data == alarm_info_no_unit["MetricAlarms"][0].TreatMissingData' - - - name: try to remove the alarm - ec2_metric_alarm: - state: absent - name: "{{ alarm_full_name }}" - register: ec2_instance_metric_alarm_deletion_no_unit - - - name: Verify that the alarm reports deleted/changed - assert: - that: - - 'ec2_instance_metric_alarm_deletion_no_unit.changed' - - - name: get info on alarms - command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} - environment: - AWS_ACCESS_KEY_ID: "{{ aws_access_key }}" - AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}" - AWS_SESSION_TOKEN: "{{ security_token | default('') }}" - AWS_DEFAULT_REGION: "{{ aws_region }}" - register: alarm_info_query_no_unit - - - name: convert it to an object - set_fact: - alarm_info_no_unit: "{{ alarm_info_query_no_unit.stdout | from_json }}" - - - name: Verify that the alarm was deleted using cli - assert: - that: - - 'alarm_info_no_unit["MetricAlarms"] | length == 0' + - set_fact: + alarm_full_name: '{{ alarm_prefix }}-{{ resource_prefix }}-cpu-low' + + - name: set up environment for testing. + include_tasks: env_setup.yml + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query + + - name: Make instance in a default subnet of the VPC + ec2_instance: + name: '{{ resource_prefix }}-test-default-vpc' + image_id: '{{ ec2_ami_id }}' + tags: + TestId: '{{ resource_prefix }}' + security_groups: '{{ sg.group_id }}' + vpc_subnet_id: '{{ testing_subnet_a.subnet.id }}' + instance_type: t2.micro + wait: true + register: ec2_instance_results + + - name: ensure alarm doesn't exist for a clean test + ec2_metric_alarm: + state: absent + name: '{{ alarm_full_name }}' + + - name: create ec2 metric alarm on ec2 instance (check mode) + ec2_metric_alarm: + dimensions: + InstanceId: '{{ ec2_instance_results.instances[0].instance_id }}' + state: present + name: '{{ alarm_full_name }}' + metric: CPUUtilization + namespace: AWS/EC2 + treat_missing_data: missing + statistic: Average + comparison: LessThanOrEqualToThreshold + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: Percent + description: This will alarm when an instance's cpu usage average is lower than + 5% for 15 minutes + check_mode: true + register: ec2_instance_metric_alarm_check + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query_check + + - name: convert it to an object + set_fact: + alarm_info_check: '{{ alarm_info_query_check.stdout | from_json }}' + + - name: verify that an alarm was not created in check mode + assert: + that: + - ec2_instance_metric_alarm_check.changed + - not ec2_instance_metric_alarm_check.alarm_arn + - alarm_info_check["MetricAlarms"] | length == 0 + + - name: create ec2 metric alarm on ec2 instance + ec2_metric_alarm: + dimensions: + InstanceId: '{{ ec2_instance_results.instances[0].instance_id }}' + state: present + name: '{{ alarm_full_name }}' + metric: CPUUtilization + namespace: AWS/EC2 + treat_missing_data: missing + statistic: Average + comparison: LessThanOrEqualToThreshold + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: Percent + description: This will alarm when an instance's cpu usage average is lower than + 5% for 15 minutes + register: ec2_instance_metric_alarm + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query + + - name: convert it to an object + set_fact: + alarm_info: '{{ alarm_info_query.stdout | from_json }}' + + - name: verify that an alarm was created + assert: + that: + - ec2_instance_metric_alarm.changed + - ec2_instance_metric_alarm.alarm_arn + - ec2_instance_metric_alarm.statistic == alarm_info["MetricAlarms"][0].Statistic + - ec2_instance_metric_alarm.name == alarm_info["MetricAlarms"][0].AlarmName + - ec2_instance_metric_alarm.metric == alarm_info["MetricAlarms"][0].MetricName + - ec2_instance_metric_alarm.namespace == alarm_info["MetricAlarms"][0].Namespace + - ec2_instance_metric_alarm.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator + - ec2_instance_metric_alarm.threshold == alarm_info["MetricAlarms"][0].Threshold + - ec2_instance_metric_alarm.period == alarm_info["MetricAlarms"][0].Period + - ec2_instance_metric_alarm.unit == alarm_info["MetricAlarms"][0].Unit + - ec2_instance_metric_alarm.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods + - ec2_instance_metric_alarm.description == alarm_info["MetricAlarms"][0].AlarmDescription + - ec2_instance_metric_alarm.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData + + - name: create ec2 metric alarm on ec2 instance (idempotent) (check mode) + ec2_metric_alarm: + dimensions: + InstanceId: '{{ ec2_instance_results.instances[0].instance_id }}' + state: present + name: '{{ alarm_full_name }}' + metric: CPUUtilization + namespace: AWS/EC2 + treat_missing_data: missing + statistic: Average + comparison: LessThanOrEqualToThreshold + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: Percent + description: This will alarm when an instance's cpu usage average is lower than + 5% for 15 minutes + check_mode: true + register: ec2_instance_metric_alarm_idempotent_check + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query_idempotent_check + + - name: convert it to an object + set_fact: + alarm_info_idempotent_check: '{{ alarm_info_query_idempotent_check.stdout | + from_json }}' + + - name: Verify alarm does not register as changed after update in check mode + assert: + that: + - not ec2_instance_metric_alarm_idempotent_check.changed + + - name: Verify alarm did not change after updating in check mode + assert: + that: + - alarm_info['MetricAlarms'][0]['{{item}}'] == alarm_info_idempotent_check['MetricAlarms'][0]['{{ + item }}'] + with_items: + - AlarmArn + - Statistic + - AlarmName + - MetricName + - Namespace + - ComparisonOperator + - Threshold + - Period + - Unit + - EvaluationPeriods + - AlarmDescription + - TreatMissingData + + - name: create ec2 metric alarm on ec2 instance (idempotent) + ec2_metric_alarm: + dimensions: + InstanceId: '{{ ec2_instance_results.instances[0].instance_id }}' + state: present + name: '{{ alarm_full_name }}' + metric: CPUUtilization + namespace: AWS/EC2 + treat_missing_data: missing + statistic: Average + comparison: LessThanOrEqualToThreshold + threshold: 5.0 + period: 300 + evaluation_periods: 3 + unit: Percent + description: This will alarm when an instance's cpu usage average is lower than + 5% for 15 minutes + register: ec2_instance_metric_alarm_idempotent + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query_idempotent + + - name: convert it to an object + set_fact: + alarm_info_idempotent: '{{ alarm_info_query_idempotent.stdout | from_json }}' + + - name: Verify alarm does not register as changed after update + assert: + that: + - not ec2_instance_metric_alarm_idempotent.changed + + - name: Verify alarm did not change after updating + assert: + that: + - alarm_info['MetricAlarms'][0]['{{item}}'] == alarm_info_idempotent['MetricAlarms'][0]['{{ + item }}'] + with_items: + - AlarmArn + - Statistic + - AlarmName + - MetricName + - Namespace + - ComparisonOperator + - Threshold + - Period + - Unit + - EvaluationPeriods + - AlarmDescription + - TreatMissingData + + - name: update alarm (check mode) + ec2_metric_alarm: + dimensions: + InstanceId: '{{ ec2_instance_results.instances[0].instance_id }}' + state: present + name: '{{ alarm_full_name }}' + metric: CPUUtilization + namespace: AWS/EC2 + statistic: Average + comparison: LessThanOrEqualToThreshold + threshold: 5.0 + period: 60 + evaluation_periods: 3 + unit: Percent + description: This will alarm when an instance's cpu usage average is lower than + 5% for 3 minutes + check_mode: true + register: ec2_instance_metric_alarm_update_check + + - name: verify that alarm registers as updated in check mode + assert: + that: + - ec2_instance_metric_alarm_check.changed + + - name: verify that properties were not changed in check mode + assert: + that: + - ec2_instance_metric_alarm_update_check.changed + - ec2_instance_metric_alarm_update_check.period == alarm_info["MetricAlarms"][0].Period # Period of actual alarm should not change + - ec2_instance_metric_alarm_update_check.alarm_arn == ec2_instance_metric_alarm.alarm_arn + - ec2_instance_metric_alarm_update_check.statistic == alarm_info["MetricAlarms"][0].Statistic + - ec2_instance_metric_alarm_update_check.name == alarm_info["MetricAlarms"][0].AlarmName + - ec2_instance_metric_alarm_update_check.metric == alarm_info["MetricAlarms"][0].MetricName + - ec2_instance_metric_alarm_update_check.namespace == alarm_info["MetricAlarms"][0].Namespace + - ec2_instance_metric_alarm_update_check.statistic == alarm_info["MetricAlarms"][0].Statistic + - ec2_instance_metric_alarm_update_check.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator + - ec2_instance_metric_alarm_update_check.threshold == alarm_info["MetricAlarms"][0].Threshold + - ec2_instance_metric_alarm_update_check.unit == alarm_info["MetricAlarms"][0].Unit + - ec2_instance_metric_alarm_update_check.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods + - ec2_instance_metric_alarm_update_check.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData + + - name: update alarm + ec2_metric_alarm: + dimensions: + InstanceId: '{{ ec2_instance_results.instances[0].instance_id }}' + state: present + name: '{{ alarm_full_name }}' + metric: CPUUtilization + namespace: AWS/EC2 + statistic: Average + comparison: LessThanOrEqualToThreshold + threshold: 5.0 + period: 60 + evaluation_periods: 3 + unit: Percent + description: This will alarm when an instance's cpu usage average is lower than + 5% for 3 minutes + register: ec2_instance_metric_alarm_update + + - name: verify that alarm registers as updated + assert: + that: + - ec2_instance_metric_alarm.changed + + - name: verify that properties were changed + assert: + that: + - 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["MetricAlarms"][0].Statistic + - ec2_instance_metric_alarm_update.name == alarm_info["MetricAlarms"][0].AlarmName + - ec2_instance_metric_alarm_update.metric == alarm_info["MetricAlarms"][0].MetricName + - ec2_instance_metric_alarm_update.namespace == alarm_info["MetricAlarms"][0].Namespace + - ec2_instance_metric_alarm_update.statistic == alarm_info["MetricAlarms"][0].Statistic + - ec2_instance_metric_alarm_update.comparison == alarm_info["MetricAlarms"][0].ComparisonOperator + - ec2_instance_metric_alarm_update.threshold == alarm_info["MetricAlarms"][0].Threshold + - ec2_instance_metric_alarm_update.unit == alarm_info["MetricAlarms"][0].Unit + - ec2_instance_metric_alarm_update.evaluation_periods == alarm_info["MetricAlarms"][0].EvaluationPeriods + - ec2_instance_metric_alarm_update.treat_missing_data == alarm_info["MetricAlarms"][0].TreatMissingData + + - name: try to remove the alarm (check mode) + ec2_metric_alarm: + state: absent + name: '{{ alarm_full_name }}' + check_mode: true + register: ec2_instance_metric_alarm_deletion_check + + - name: Verify that the alarm reports deleted/changed + assert: + that: + - ec2_instance_metric_alarm_deletion_check.changed + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query_check + + - name: convert it to an object + set_fact: + alarm_info: '{{ alarm_info_query_check.stdout | from_json }}' + + - name: Verify that the alarm was not deleted in check mode using cli + assert: + that: + - alarm_info["MetricAlarms"] | length > 0 + + - name: try to remove the alarm + ec2_metric_alarm: + state: absent + name: '{{ alarm_full_name }}' + register: ec2_instance_metric_alarm_deletion + + - name: Verify that the alarm reports deleted/changed + assert: + that: + - ec2_instance_metric_alarm_deletion.changed + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query + + - name: convert it to an object + set_fact: + alarm_info: '{{ alarm_info_query.stdout | from_json }}' + + - name: Verify that the alarm was deleted using cli + assert: + that: + - alarm_info["MetricAlarms"] | length == 0 + + - name: create ec2 metric alarm with no unit on ec2 instance + ec2_metric_alarm: + dimensions: + InstanceId: '{{ ec2_instance_results.instances[0].instance_id }}' + state: present + name: '{{ alarm_full_name }}' + metric: CPUUtilization + namespace: AWS/EC2 + treat_missing_data: missing + statistic: Average + comparison: LessThanOrEqualToThreshold + threshold: 5.0 + period: 300 + evaluation_periods: 3 + description: This will alarm when an instance's cpu usage average is lower than + 5% for 15 minutes + register: ec2_instance_metric_alarm_no_unit + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query_no_unit + + - name: convert it to an object + set_fact: + alarm_info_no_unit: '{{ alarm_info_query_no_unit.stdout | from_json }}' + + - name: verify that an alarm was created + assert: + that: + - ec2_instance_metric_alarm_no_unit.changed + - ec2_instance_metric_alarm_no_unit.alarm_arn + - ec2_instance_metric_alarm_no_unit.statistic == alarm_info_no_unit["MetricAlarms"][0].Statistic + - ec2_instance_metric_alarm_no_unit.name == alarm_info_no_unit["MetricAlarms"][0].AlarmName + - ec2_instance_metric_alarm_no_unit.metric == alarm_info_no_unit["MetricAlarms"][0].MetricName + - ec2_instance_metric_alarm_no_unit.namespace == alarm_info_no_unit["MetricAlarms"][0].Namespace + - ec2_instance_metric_alarm_no_unit.comparison == alarm_info_no_unit["MetricAlarms"][0].ComparisonOperator + - ec2_instance_metric_alarm_no_unit.threshold == alarm_info_no_unit["MetricAlarms"][0].Threshold + - ec2_instance_metric_alarm_no_unit.period == alarm_info_no_unit["MetricAlarms"][0].Period + - alarm_info_no_unit["MetricAlarms"][0].Unit is not defined + - ec2_instance_metric_alarm_no_unit.evaluation_periods == alarm_info_no_unit["MetricAlarms"][0].EvaluationPeriods + - ec2_instance_metric_alarm_no_unit.description == alarm_info_no_unit["MetricAlarms"][0].AlarmDescription + - ec2_instance_metric_alarm_no_unit.treat_missing_data == alarm_info_no_unit["MetricAlarms"][0].TreatMissingData + + - name: try to remove the alarm + ec2_metric_alarm: + state: absent + name: '{{ alarm_full_name }}' + register: ec2_instance_metric_alarm_deletion_no_unit + + - name: Verify that the alarm reports deleted/changed + assert: + that: + - ec2_instance_metric_alarm_deletion_no_unit.changed + + - name: get info on alarms + command: aws cloudwatch describe-alarms --alarm-names {{ alarm_full_name }} + environment: + AWS_ACCESS_KEY_ID: '{{ aws_access_key }}' + AWS_SECRET_ACCESS_KEY: '{{ aws_secret_key }}' + AWS_SESSION_TOKEN: "{{ security_token | default('') }}" + AWS_DEFAULT_REGION: '{{ aws_region }}' + register: alarm_info_query_no_unit + + - name: convert it to an object + set_fact: + alarm_info_no_unit: '{{ alarm_info_query_no_unit.stdout | from_json }}' + + - name: Verify that the alarm was deleted using cli + assert: + that: + - alarm_info_no_unit["MetricAlarms"] | length == 0 always: - - name: try to delete the alarm - ec2_metric_alarm: - state: absent - name: "{{ alarm_full_name }}" - ignore_errors: true - - - name: try to stop the ec2 instance - ec2_instance: - instance_ids: "{{ ec2_instance_results.instances[0].instance_id }}" - state: terminated - ignore_errors: true - - - include_tasks: env_cleanup.yml + - name: try to delete the alarm + ec2_metric_alarm: + state: absent + name: '{{ alarm_full_name }}' + ignore_errors: true + + - name: try to stop the ec2 instance + ec2_instance: + instance_ids: '{{ ec2_instance_results.instances[0].instance_id }}' + state: terminated + ignore_errors: true + + - include_tasks: env_cleanup.yml From 313c4de39f2b094e4c017f0fcd8fdb7d44e1d683 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 16 Sep 2022 18:18:53 +0200 Subject: [PATCH 5/8] Add changelog fragment --- changelogs/fragments/migrate_cloudwatch_metric_alarm.yml | 4 ++++ .../integration/targets/cloudwatch_metric_alarm/vars/main.yml | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelogs/fragments/migrate_cloudwatch_metric_alarm.yml delete mode 100644 tests/integration/targets/cloudwatch_metric_alarm/vars/main.yml diff --git a/changelogs/fragments/migrate_cloudwatch_metric_alarm.yml b/changelogs/fragments/migrate_cloudwatch_metric_alarm.yml new file mode 100644 index 00000000000..9a4003f33a5 --- /dev/null +++ b/changelogs/fragments/migrate_cloudwatch_metric_alarm.yml @@ -0,0 +1,4 @@ +major_changes: +- cloudwatch_metric_alarm - The module has been migrated from the ``community.aws`` + collection. Playbooks using the Fully Qualified Collection Name for this module + should be updated to use ``amazon.aws.cloudwatch_metric_alarm``. diff --git a/tests/integration/targets/cloudwatch_metric_alarm/vars/main.yml b/tests/integration/targets/cloudwatch_metric_alarm/vars/main.yml deleted file mode 100644 index ed97d539c09..00000000000 --- a/tests/integration/targets/cloudwatch_metric_alarm/vars/main.yml +++ /dev/null @@ -1 +0,0 @@ ---- From 25143a26d16798b118968ee47a2e32dcb0cc58ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A9ri=20Le=20Bouder?= Date: Wed, 21 Sep 2022 17:02:02 -0400 Subject: [PATCH 6/8] sort the action_groups --- meta/runtime.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/meta/runtime.yml b/meta/runtime.yml index 9671892aad0..00e2e17f09e 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -10,6 +10,7 @@ action_groups: - cloudtrail - cloudwatchevent_rule - cloudwatch_metric_alarm + - cloudwatch_metric_alarm - cloudwatchlogs_log_group - cloudwatchlogs_log_group_info - cloudwatchlogs_log_group_metric_filter From bd82276aaa1632ab3f441d594d6edaf3e6b7c822 Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Fri, 16 Sep 2022 18:24:50 +0200 Subject: [PATCH 7/8] Update runtime --- meta/runtime.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/meta/runtime.yml b/meta/runtime.yml index 00e2e17f09e..9671892aad0 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -10,7 +10,6 @@ action_groups: - cloudtrail - cloudwatchevent_rule - cloudwatch_metric_alarm - - cloudwatch_metric_alarm - cloudwatchlogs_log_group - cloudwatchlogs_log_group_info - cloudwatchlogs_log_group_metric_filter From 3b9860b4f682cd831b5a2fc22d6acda1dce9dd3e Mon Sep 17 00:00:00 2001 From: Alina Buzachis Date: Wed, 21 Sep 2022 17:02:02 +0200 Subject: [PATCH 8/8] Update runtime --- meta/runtime.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/meta/runtime.yml b/meta/runtime.yml index 9671892aad0..66ce85cec0d 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -10,6 +10,7 @@ action_groups: - cloudtrail - cloudwatchevent_rule - cloudwatch_metric_alarm + - cloudwatchevent_rule - cloudwatchlogs_log_group - cloudwatchlogs_log_group_info - cloudwatchlogs_log_group_metric_filter