diff --git a/changelogs/fragments/migrate_autoscaling_instance_refresh_autoscaling_instance_refresh_info.yaml b/changelogs/fragments/migrate_autoscaling_instance_refresh_autoscaling_instance_refresh_info.yaml new file mode 100644 index 00000000000..8f5a62d849c --- /dev/null +++ b/changelogs/fragments/migrate_autoscaling_instance_refresh_autoscaling_instance_refresh_info.yaml @@ -0,0 +1,8 @@ +--- +breaking_changes: + - autoscaling_instance_refresh - 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.autoscaling_instance_refresh`` (https://github.com/ansible-collections/community.aws/pull/2177). + - autoscaling_instance_refresh_info - 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.autoscaling_instance_refresh_info`` (https://github.com/ansible-collections/community.aws/pull/2177). diff --git a/meta/runtime.yml b/meta/runtime.yml index d9324dea195..6513c540dd3 100644 --- a/meta/runtime.yml +++ b/meta/runtime.yml @@ -10,8 +10,6 @@ action_groups: - api_gateway_info - application_autoscaling_policy - autoscaling_complete_lifecycle_action - - autoscaling_instance_refresh - - autoscaling_instance_refresh_info - autoscaling_launch_config - autoscaling_launch_config_find - autoscaling_launch_config_info @@ -94,8 +92,6 @@ action_groups: - ec2_ami_copy - ec2_asg - ec2_asg_info - - ec2_asg_instance_refresh - - ec2_asg_instance_refresh_info - ec2_asg_lifecycle_hook - ec2_asg_scheduled_action - ec2_customer_gateway @@ -371,10 +367,10 @@ plugin_routing: redirect: amazon.aws.autoscaling_group_info ec2_asg_instance_refresh: # Deprecation for this alias should not *start* prior to 2024-09-01 - redirect: community.aws.autoscaling_instance_refresh + redirect: amazon.aws.autoscaling_instance_refresh ec2_asg_instance_refresh_info: # Deprecation for this alias should not *start* prior to 2024-09-01 - redirect: community.aws.autoscaling_instance_refresh_info + redirect: amazon.aws.autoscaling_instance_refresh_info ec2_asg_lifecycle_hook: # Deprecation for this alias should not *start* prior to 2024-09-01 redirect: community.aws.autoscaling_lifecycle_hook @@ -537,6 +533,10 @@ plugin_routing: redirect: amazon.aws.ec2_vpc_vpn ec2_vpc_vpn_info: redirect: amazon.aws.ec2_vpc_vpn_info + autoscaling_instance_refresh: + redirect: amazon.aws.autoscaling_instance_refresh + autoscaling_instance_refresh_info: + redirect: amazon.aws.autoscaling_instance_refresh_info module_utils: route53: redirect: amazon.aws.route53 diff --git a/plugins/modules/autoscaling_instance_refresh.py b/plugins/modules/autoscaling_instance_refresh.py deleted file mode 100644 index b337b5b1f52..00000000000 --- a/plugins/modules/autoscaling_instance_refresh.py +++ /dev/null @@ -1,298 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -DOCUMENTATION = r""" ---- -module: autoscaling_instance_refresh -version_added: 3.2.0 -short_description: Start or cancel an EC2 Auto Scaling Group (ASG) instance refresh in AWS -description: - - Start or cancel an EC2 Auto Scaling Group instance refresh in AWS. - - Can be used with M(community.aws.autoscaling_instance_refresh_info) to track the subsequent progress. - - Prior to release 5.0.0 this module was called M(community.aws.ec2_asg_instance_refresh). - The usage did not change. -author: - - "Dan Khersonsky (@danquixote)" -options: - state: - description: - - Desired state of the ASG. - type: str - required: true - choices: [ 'started', 'cancelled' ] - name: - description: - - The name of the auto scaling group you are searching for. - type: str - required: true - strategy: - description: - - The strategy to use for the instance refresh. The only valid value is V(Rolling). - - A rolling update is an update that is applied to all instances in an Auto Scaling group until all instances have been updated. - - A rolling update can fail due to failed health checks or if instances are on standby or are protected from scale in. - - If the rolling update process fails, any instances that were already replaced are not rolled back to their previous configuration. - type: str - default: 'Rolling' - preferences: - description: - - Set of preferences associated with the instance refresh request. - - If not provided, the default values are used. - - For O(preferences.min_healthy_percentage), the default value is V(90). - - For O(preferences.instance_warmup), the default is to use the value specified for the health check grace period for the Auto Scaling group. - - Can not be specified when O(state=cancelled). - required: false - suboptions: - min_healthy_percentage: - description: - - Total percent of capacity in ASG that must remain healthy during instance refresh to allow operation to continue. - - It is rounded up to the nearest integer. - - Value range is V(0) to V(100). - type: int - default: 90 - instance_warmup: - description: - - The number of seconds until a newly launched instance is configured and ready to use. - - During this time, Amazon EC2 Auto Scaling does not immediately move on to the next replacement. - - The default is to use the value for the health check grace period defined for the group. - type: int - skip_matching: - description: - - Indicates whether skip matching is enabled. - - If enabled V(true), then Amazon EC2 Auto Scaling skips replacing instances that match the desired configuration. - type: bool - version_added: 9.0.0 - max_healthy_percentage: - description: - - Specifies the maximum percentage of the group that can be in service and healthy, or pending, - to support your workload when replacing instances. - - The value is expressed as a percentage of the desired capacity of the Auto Scaling group. - - Value range is V(100) to V(200). - - When specified, you must also specify O(preferences.min_healthy_percentage), and the difference between them cannot be greater than V(100). - type: int - version_added: 9.0.0 - type: dict -extends_documentation_fragment: - - amazon.aws.common.modules - - amazon.aws.region.modules - - amazon.aws.boto3 -""" - -EXAMPLES = r""" -# Note: These examples do not set authentication details, see the AWS Guide for details. - -- name: Start a refresh - community.aws.autoscaling_instance_refresh: - name: some-asg - state: started - -- name: Cancel a refresh - community.aws.autoscaling_instance_refresh: - name: some-asg - state: cancelled - -- name: Start a refresh and pass preferences - community.aws.autoscaling_instance_refresh: - name: some-asg - state: started - preferences: - min_healthy_percentage: 91 - instance_warmup: 60 - skip_matching: true -""" - -RETURN = r""" -instance_refreshes: - description: Details of the instance refreshes for the Auto Scaling group. - returned: always - type: complex - contains: - instance_refresh_id: - description: Instance refresh id. - returned: success - type: str - sample: "08b91cf7-8fa6-48af-b6a6-d227f40f1b9b" - auto_scaling_group_name: - description: Name of autoscaling group. - returned: success - type: str - sample: "public-webapp-production-1" - status: - description: - - The current state of the group when DeleteAutoScalingGroup is in progress. - - The following are the possible statuses - - Pending - The request was created, but the operation has not started. - - InProgress - The operation is in progress. - - Successful - The operation completed successfully. - - Failed - The operation failed to complete. - You can troubleshoot using the status reason and the scaling activities. - - Cancelling - An ongoing operation is being cancelled. - Cancellation does not roll back any replacements that have already been - completed, but it prevents new replacements from being started. - - Cancelled - The operation is cancelled. - returned: success - type: str - sample: "Pending" - preferences: - description: The preferences for an instance refresh. - returned: always - type: dict - sample: { - 'AlarmSpecification': { - 'Alarms': [ - 'my-alarm', - ], - }, - 'AutoRollback': True, - 'InstanceWarmup': 200, - 'MinHealthyPercentage': 90, - 'ScaleInProtectedInstances': 'Ignore', - 'SkipMatching': False, - 'StandbyInstances': 'Ignore', - } - start_time: - description: The date and time this ASG was created, in ISO 8601 format. - returned: success - type: str - sample: "2015-11-25T00:05:36.309Z" - end_time: - description: The date and time this ASG was created, in ISO 8601 format. - returned: success - type: str - sample: "2015-11-25T00:05:36.309Z" - percentage_complete: - description: the % of completeness. - returned: success - type: int - sample: 100 - instances_to_update: - description: number of instances to update. - returned: success - type: int - sample: 5 -""" - -from typing import Dict -from typing import Optional -from typing import Union - -from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict -from ansible.module_utils.common.dict_transformations import snake_dict_to_camel_dict - -from ansible_collections.amazon.aws.plugins.module_utils.autoscaling import AnsibleAutoScalingError -from ansible_collections.amazon.aws.plugins.module_utils.autoscaling import cancel_instance_refresh -from ansible_collections.amazon.aws.plugins.module_utils.autoscaling import describe_instance_refreshes -from ansible_collections.amazon.aws.plugins.module_utils.autoscaling import start_instance_refresh -from ansible_collections.amazon.aws.plugins.module_utils.transformation import scrub_none_parameters - -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule - - -def validate_healthy_percentage(preferences: Dict[str, Union[bool, int]]) -> Optional[str]: - min_healthy_percentage = preferences.get("min_healthy_percentage") - max_healthy_percentage = preferences.get("max_healthy_percentage") - - if min_healthy_percentage is not None and (min_healthy_percentage < 0 or min_healthy_percentage > 100): - return "The value range for the min_healthy_percentage is 0 to 100." - if max_healthy_percentage is not None: - if max_healthy_percentage < 100 or max_healthy_percentage > 200: - return "The value range for the max_healthy_percentage is 100 to 200." - if min_healthy_percentage is None: - return "You must also specify min_healthy_percentage when max_healthy_percentage is specified." - if (max_healthy_percentage - min_healthy_percentage) > 100: - return "The difference between the max_healthy_percentage and min_healthy_percentage cannot be greater than 100." - return None - - -def start_or_cancel_instance_refresh(conn, module: AnsibleAWSModule) -> None: - """ - Args: - conn (boto3.AutoScaling.Client): Valid Boto3 ASG client. - module: AnsibleAWSModule object - """ - - asg_state = module.params.get("state") - asg_name = module.params.get("name") - preferences = module.params.get("preferences") - - args = {} - if asg_state == "started": - args["Strategy"] = module.params.get("strategy") - if preferences: - if asg_state == "cancelled": - module.fail_json(msg="can not pass preferences dict when canceling a refresh") - error = validate_healthy_percentage(preferences) - if error: - module.fail_json(msg=error) - args["Preferences"] = snake_dict_to_camel_dict(scrub_none_parameters(preferences), capitalize_first=True) - cmd_invocations = { - "cancelled": cancel_instance_refresh, - "started": start_instance_refresh, - } - try: - if module.check_mode: - ongoing_refresh = describe_instance_refreshes(conn, auto_scaling_group_name=asg_name).get( - "InstanceRefreshes", [] - ) - if asg_state == "started": - if ongoing_refresh: - module.exit_json( - changed=False, - msg="In check_mode - Instance Refresh is already in progress, can not start new instance refresh.", - ) - else: - module.exit_json(changed=True, msg="Would have started instance refresh if not in check mode.") - elif asg_state == "cancelled": - if ongoing_refresh and ongoing_refresh[0].get("Status", "") in ["Cancelling", "Cancelled"]: - module.exit_json( - changed=False, - msg="In check_mode - Instance Refresh already cancelled or is pending cancellation.", - ) - elif not ongoing_refresh: - module.exit_json(changed=False, msg="In check_mode - No active referesh found, nothing to cancel.") - else: - module.exit_json(changed=True, msg="Would have cancelled instance refresh if not in check mode.") - instance_refresh_id = cmd_invocations[asg_state](conn, auto_scaling_group_name=asg_name, **args) - response = describe_instance_refreshes( - conn, auto_scaling_group_name=asg_name, instance_refresh_ids=[instance_refresh_id] - ) - result = dict(instance_refreshes=camel_dict_to_snake_dict(response["InstanceRefreshes"][0])) - module.exit_json(**result) - except AnsibleAutoScalingError as e: - module.fail_json_aws(e, msg=f"Failed to {asg_state.replace('ed', '')} InstanceRefresh: {e}") - - -def main(): - argument_spec = dict( - state=dict( - type="str", - required=True, - choices=["started", "cancelled"], - ), - name=dict(required=True), - strategy=dict(type="str", default="Rolling", required=False), - preferences=dict( - type="dict", - required=False, - options=dict( - min_healthy_percentage=dict(type="int", default=90), - instance_warmup=dict(type="int"), - skip_matching=dict(type="bool"), - max_healthy_percentage=dict(type="int"), - ), - ), - ) - - module = AnsibleAWSModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - autoscaling = module.client("autoscaling") - - start_or_cancel_instance_refresh(autoscaling, module) - - -if __name__ == "__main__": - main() diff --git a/plugins/modules/autoscaling_instance_refresh_info.py b/plugins/modules/autoscaling_instance_refresh_info.py deleted file mode 100644 index 1d3bf8fe90c..00000000000 --- a/plugins/modules/autoscaling_instance_refresh_info.py +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Copyright: Ansible Project -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -DOCUMENTATION = r""" ---- -module: autoscaling_instance_refresh_info -version_added: 3.2.0 -short_description: Gather information about EC2 Auto Scaling Group (ASG) Instance Refreshes in AWS -description: - - Describes one or more instance refreshes. - - You can determine the status of a request by looking at the RV(instance_refreshes.status) return value. - - Prior to release 5.0.0 this module was called M(community.aws.ec2_asg_instance_refresh_info). - The usage did not change. -author: - - "Dan Khersonsky (@danquixote)" -options: - name: - description: - - The name of the Auto Scaling group. - type: str - required: true - ids: - description: - - One or more instance refresh IDs. - type: list - elements: str - default: [] - next_token: - description: - - The token for the next set of items to return. (You received this token from a previous call.) - type: str - max_records: - description: - - The maximum number of items to return with this call. The default value is V(50) and the maximum value is V(100). - type: int - required: false -extends_documentation_fragment: - - amazon.aws.common.modules - - amazon.aws.region.modules - - amazon.aws.boto3 -""" - -EXAMPLES = r""" -# Note: These examples do not set authentication details, see the AWS Guide for details. - -- name: Find an refresh by ASG name - community.aws.autoscaling_instance_refresh_info: - name: somename-asg - -- name: Find an refresh by ASG name and one or more refresh-IDs - community.aws.autoscaling_instance_refresh_info: - name: somename-asg - ids: ['some-id-123'] - register: asgs - -- name: Find an refresh by ASG name and set max_records - community.aws.autoscaling_instance_refresh_info: - name: somename-asg - max_records: 4 - register: asgs - -- name: Find an refresh by ASG name and NextToken, if received from a previous call - community.aws.autoscaling_instance_refresh_info: - name: somename-asg - next_token: 'some-token-123' - register: asgs -""" - -RETURN = r""" -next_token: - description: A string that indicates that the response contains more items than can be returned in a single response. - returned: always - type: str -instance_refreshes: - description: A list of instance refreshes. - returned: always - type: complex - contains: - instance_refresh_id: - description: instance refresh id. - returned: success - type: str - sample: "08b91cf7-8fa6-48af-b6a6-d227f40f1b9b" - auto_scaling_group_name: - description: Name of autoscaling group. - returned: success - type: str - sample: "public-webapp-production-1" - status: - description: - - The current state of the group when DeleteAutoScalingGroup is in progress. - - The following are the possible statuses - - Pending - The request was created, but the operation has not started. - - InProgress - The operation is in progress. - - Successful - The operation completed successfully. - - Failed - The operation failed to complete. - You can troubleshoot using the status reason and the scaling activities. - - Cancelling - An ongoing operation is being cancelled. - Cancellation does not roll back any replacements that have already been - completed, but it prevents new replacements from being started. - - Cancelled - The operation is cancelled. - returned: success - type: str - sample: "Pending" - preferences: - description: The preferences for an instance refresh. - returned: always - type: dict - sample: { - 'AlarmSpecification': { - 'Alarms': [ - 'my-alarm', - ], - }, - 'AutoRollback': True, - 'InstanceWarmup': 200, - 'MinHealthyPercentage': 90, - 'ScaleInProtectedInstances': 'Ignore', - 'SkipMatching': False, - 'StandbyInstances': 'Ignore', - } - start_time: - description: The date and time this ASG was created, in ISO 8601 format. - returned: success - type: str - sample: "2015-11-25T00:05:36.309Z" - end_time: - description: The date and time this ASG was created, in ISO 8601 format. - returned: success - type: str - sample: "2015-11-25T00:05:36.309Z" - percentage_complete: - description: the % of completeness - returned: success - type: int - sample: 100 - instances_to_update: - description: number of instances to update. - returned: success - type: int - sample: 5 -""" - -from typing import Any -from typing import Dict - -from ansible.module_utils.common.dict_transformations import camel_dict_to_snake_dict - -from ansible_collections.amazon.aws.plugins.module_utils.autoscaling import AnsibleAutoScalingError -from ansible_collections.amazon.aws.plugins.module_utils.autoscaling import describe_instance_refreshes - -from ansible_collections.community.aws.plugins.module_utils.modules import AnsibleCommunityAWSModule as AnsibleAWSModule - - -def format_response(response: Dict[str, Any]) -> Dict[str, Any]: - result = {} - if "InstanceRefreshes" in response: - instance_refreshes_dict = { - "instance_refreshes": response["InstanceRefreshes"], - "next_token": response.get("NextToken", ""), - } - result = camel_dict_to_snake_dict(instance_refreshes_dict) - return result - - -def find_asg_instance_refreshes(client, module: AnsibleAWSModule) -> None: - """ - Args: - client (boto3.AutoScaling.Client): Valid Boto3 ASG client. - module: AnsibleAWSModule object - """ - - try: - max_records = module.params.get("max_records") - response = describe_instance_refreshes( - client, - auto_scaling_group_name=module.params.get("name"), - instance_refresh_ids=module.params.get("ids"), - next_token=module.params.get("next_token"), - max_records=max_records, - ) - instance_refreshes_result = format_response(response) - - if max_records is None: - while "NextToken" in response: - response = describe_instance_refreshes( - client, - auto_scaling_group_name=module.params.get("name"), - instance_refresh_ids=module.params.get("ids"), - next_token=response["NextToken"], - max_records=max_records, - ) - f_response = format_response(response) - if "instance_refreshes" in f_response: - instance_refreshes_result["instance_refreshes"].extend(f_response["instance_refreshes"]) - instance_refreshes_result["next_token"] = f_response["next_token"] - - module.exit_json(changed=False, **instance_refreshes_result) - except AnsibleAutoScalingError as e: - module.fail_json_aws(e, msg=f"Failed to describe InstanceRefreshes: {e}") - - -def main(): - argument_spec = dict( - name=dict(required=True, type="str"), - ids=dict(required=False, default=[], elements="str", type="list"), - next_token=dict(required=False, default=None, type="str", no_log=True), - max_records=dict(required=False, type="int"), - ) - - module = AnsibleAWSModule( - argument_spec=argument_spec, - supports_check_mode=True, - ) - - autoscaling = module.client("autoscaling") - find_asg_instance_refreshes(autoscaling, module) - - -if __name__ == "__main__": - main() diff --git a/tests/integration/targets/autoscaling_instance_refresh/aliases b/tests/integration/targets/autoscaling_instance_refresh/aliases deleted file mode 100644 index 6ce549da4bb..00000000000 --- a/tests/integration/targets/autoscaling_instance_refresh/aliases +++ /dev/null @@ -1,3 +0,0 @@ -time=14m -cloud/aws -autoscaling_instance_refresh_info diff --git a/tests/integration/targets/autoscaling_instance_refresh/defaults/main.yml b/tests/integration/targets/autoscaling_instance_refresh/defaults/main.yml deleted file mode 100644 index 08e57d2558e..00000000000 --- a/tests/integration/targets/autoscaling_instance_refresh/defaults/main.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- -# defaults file for ec2_asg -vpc_seed: '{{ tiny_prefix }}' -subnet_a_cidr: '10.{{ 256 | random(seed=vpc_seed) }}.32.0/24' - -default_resource_name: '{{ resource_prefix }}-asg-refresh' -short_resource_name: '{{ tiny_prefix }}-asg-refresh' - -vpc_name: '{{ default_resource_name }}' -subnet_name: '{{ default_resource_name }}' -route_name: '{{ default_resource_name }}' -sg_name: '{{ default_resource_name }}' -asg_name: '{{ default_resource_name }}' -lc_name_1: '{{ default_resource_name }}-1' -lc_name_2: '{{ default_resource_name }}-2' -load_balancer_name: '{{ short_resource_name }}' diff --git a/tests/integration/targets/autoscaling_instance_refresh/meta/main.yml b/tests/integration/targets/autoscaling_instance_refresh/meta/main.yml deleted file mode 100644 index 1471b11f658..00000000000 --- a/tests/integration/targets/autoscaling_instance_refresh/meta/main.yml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - setup_ec2_facts diff --git a/tests/integration/targets/autoscaling_instance_refresh/tasks/instance_refresh_info.yml b/tests/integration/targets/autoscaling_instance_refresh/tasks/instance_refresh_info.yml deleted file mode 100644 index bf95b1668db..00000000000 --- a/tests/integration/targets/autoscaling_instance_refresh/tasks/instance_refresh_info.yml +++ /dev/null @@ -1,99 +0,0 @@ ---- -- name: Test getting info for an ASG name - autoscaling_instance_refresh_info: - name: "{{ asg_name }}" - register: output - -- name: Assert that the correct number of records are returned - assert: - that: - - output.instance_refreshes | map(attribute='instance_refresh_id') | unique | length == 7 - -- name: Test using fake refresh ID - autoscaling_instance_refresh_info: - name: "{{ asg_name }}" - ids: ['0e367f58-blabla-bla-bla-ca870dc5dbfe'] - register: output - -- name: Assert that no record is returned - assert: - that: - - output.instance_refreshes | length == 0 - -- name: Test using a real refresh ID - autoscaling_instance_refresh_info: - name: "{{ asg_name }}" - ids: [ '{{ refreshout.instance_refreshes.instance_refresh_id }}' ] - register: output - -- name: Assert that the correct record is returned - assert: - that: - - output.instance_refreshes | length == 1 - -- name: Test getting info for an ASG name which doesn't exist - autoscaling_instance_refresh_info: - name: n0n3x1stentname27b - ignore_errors: true - register: output - -- name: Assert that module failed to return record - assert: - that: - - "'Failed to describe InstanceRefreshes: An error occurred (ValidationError) when calling the DescribeInstanceRefreshes operation: AutoScalingGroup name not found - AutoScalingGroup n0n3x1stentname27b not found' in output.msg" - -- name: Retrieve instance refresh info - autoscaling_instance_refresh_info: - name: "{{ asg_name }}" - register: output - -- name: Assert that the correct number of records are returned - assert: - that: - - output.instance_refreshes | length == 7 - -- name: Retrieve instance refresh info using next_token - autoscaling_instance_refresh_info: - name: "{{ asg_name }}" - next_token: "fake-token-123" - ignore_errors: true - register: output - -- name: Assert that valid message with fake-token is returned - assert: - that: - - '"Failed to describe InstanceRefreshes: An error occurred (InvalidNextToken) when calling the DescribeInstanceRefreshes operation: The token ''********'' is invalid." in output.msg' - -- name: Retrieve instance refresh info using max_records - autoscaling_instance_refresh_info: - name: "{{ asg_name }}" - max_records: 1 - register: output_with_token - -- name: Assert that max records=1 returns no more than one record - assert: - that: - - output_with_token.instance_refreshes | length == 1 - -- name: Retrieve instance refresh using valid token - autoscaling_instance_refresh_info: - name: "{{ asg_name }}" - next_token: "{{ output_with_token.next_token }}" - register: output - -- name: Assert that valid message with real-token is returned - assert: - that: - - output.instance_refreshes | length == 6 - -- name: Test using both real nextToken and max_records=1 - autoscaling_instance_refresh_info: - name: "{{ asg_name }}" - max_records: 1 - next_token: "{{ output_with_token.next_token }}" - register: output - -- name: Assert that only one instance refresh is returned - assert: - that: - - output.instance_refreshes | length == 1 diff --git a/tests/integration/targets/autoscaling_instance_refresh/tasks/main.yml b/tests/integration/targets/autoscaling_instance_refresh/tasks/main.yml deleted file mode 100644 index cdfa2e00106..00000000000 --- a/tests/integration/targets/autoscaling_instance_refresh/tasks/main.yml +++ /dev/null @@ -1,226 +0,0 @@ ---- -- name: setup credentials and region - module_defaults: - group/aws: - access_key: "{{ aws_access_key }}" - secret_key: "{{ aws_secret_key }}" - session_token: "{{ security_token | default(omit) }}" - region: "{{ aws_region }}" - - collections: - - amazon.aws - - block: - # Set up the testing dependencies: VPC, subnet, security group, and two launch configurations - - name: Create VPC for use in testing - ec2_vpc_net: - name: "{{ vpc_name }}" - cidr_block: '{{ subnet_a_cidr }}' - 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 subnet for use in testing - ec2_vpc_subnet: - state: present - vpc_id: "{{ testing_vpc.vpc.id }}" - cidr: '{{ subnet_a_cidr }}' - az: "{{ aws_region }}a" - resource_tags: - Name: "{{ subnet_name }}" - register: testing_subnet - - - name: Create routing rules - ec2_vpc_route_table: - vpc_id: "{{ testing_vpc.vpc.id }}" - tags: - created: "{{ route_name }}" - routes: - - dest: 0.0.0.0/0 - gateway_id: "{{ igw.gateway_id }}" - subnets: - - "{{ testing_subnet.subnet.id }}" - - - name: Create a security group with the vpc created in the ec2_setup - ec2_security_group: - name: "{{ sg_name }}" - 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 - - - name: Ensure launch configs exist - autoscaling_launch_config: - name: "{{ item }}" - assign_public_ip: true - image_id: "{{ ec2_ami_id }}" - user_data: | - package_upgrade: true - package_update: true - packages: - - httpd - runcmd: - - "service httpd start" - security_groups: "{{ sg.group_id }}" - instance_type: t3.micro - loop: - - "{{ lc_name_1 }}" - - "{{ lc_name_2 }}" - - - name: Launch asg and do not wait for instances to be deemed healthy (no ELB) - autoscaling_group: - name: "{{ asg_name }}" - launch_config_name: "{{ lc_name_1 }}" - desired_capacity: 1 - min_size: 1 - max_size: 1 - vpc_zone_identifier: "{{ testing_subnet.subnet.id }}" - wait_for_instances: no - state: present - register: output - - - name: Assert that there is no viable instance - assert: - that: - - "output.viable_instances == 0" - - # ============================================================ - - name: Run test with start_cancel_instance_refresh.yml - include_tasks: start_cancel_instance_refresh.yml - - # ============================================================ - - - name: Run test with refresh_and_cancel_three_times.yml - include_tasks: refresh_and_cancel_three_times.yml - loop: "{{ query('sequence', 'start=1 end=3') }}" - - - name: Run test with instance_refresh_info.yml - include_tasks: instance_refresh_info.yml - - always: - - - name: Kill asg - autoscaling_group: - name: "{{ asg_name }}" - state: absent - register: removed - until: removed is not failed - ignore_errors: true - retries: 10 - # Remove the testing dependencies - - - name: Remove the load balancer - elb_classic_lb: - name: "{{ load_balancer_name }}" - state: absent - security_group_ids: - - "{{ sg.group_id }}" - subnets: "{{ testing_subnet.subnet.id }}" - wait: true - connection_draining_timeout: 60 - listeners: - - protocol: http - load_balancer_port: 80 - instance_port: 80 - health_check: - ping_protocol: tcp - ping_port: 80 - ping_path: "/" - response_timeout: 5 - interval: 10 - unhealthy_threshold: 4 - healthy_threshold: 2 - register: removed - until: removed is not failed - ignore_errors: true - retries: 10 - - - name: Remove launch configs - autoscaling_launch_config: - name: "{{ item }}" - state: absent - register: removed - until: removed is not failed - ignore_errors: true - retries: 10 - loop: - - "{{ lc_name_1 }}" - - "{{ lc_name_2 }}" - - - name: Delete launch template - ec2_launch_template: - name: "{{ resource_prefix }}-lt" - state: absent - register: del_lt - retries: 10 - until: del_lt is not failed - ignore_errors: true - - - name: Remove the security group - ec2_security_group: - name: "{{ sg_name }}" - description: a security group for ansible tests - vpc_id: "{{ testing_vpc.vpc.id }}" - state: absent - register: removed - until: removed is not failed - ignore_errors: true - retries: 10 - - - name: Remove routing rules - ec2_vpc_route_table: - state: absent - vpc_id: "{{ testing_vpc.vpc.id }}" - tags: - created: "{{ route_name }}" - routes: - - dest: 0.0.0.0/0 - gateway_id: "{{ igw.gateway_id }}" - subnets: - - "{{ testing_subnet.subnet.id }}" - register: removed - until: removed is not failed - ignore_errors: true - 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: true - retries: 10 - - - name: Remove the subnet - ec2_vpc_subnet: - state: absent - vpc_id: "{{ testing_vpc.vpc.id }}" - cidr: '{{ subnet_a_cidr }}' - register: removed - until: removed is not failed - ignore_errors: true - retries: 10 - - - name: Remove the VPC - ec2_vpc_net: - name: "{{ vpc_name }}" - cidr_block: '{{ subnet_a_cidr }}' - state: absent - register: removed - until: removed is not failed - ignore_errors: true - retries: 10 diff --git a/tests/integration/targets/autoscaling_instance_refresh/tasks/refresh_and_cancel_three_times.yml b/tests/integration/targets/autoscaling_instance_refresh/tasks/refresh_and_cancel_three_times.yml deleted file mode 100644 index e2cebe924a9..00000000000 --- a/tests/integration/targets/autoscaling_instance_refresh/tasks/refresh_and_cancel_three_times.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- -- name: Test starting a refresh with an ASG name - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "started" - retries: 10 - delay: 5 - register: refreshout - until: refreshout is not failed - -- name: Test cancelling a refresh with an ASG name - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" diff --git a/tests/integration/targets/autoscaling_instance_refresh/tasks/start_cancel_instance_refresh.yml b/tests/integration/targets/autoscaling_instance_refresh/tasks/start_cancel_instance_refresh.yml deleted file mode 100644 index a15e71cc3d3..00000000000 --- a/tests/integration/targets/autoscaling_instance_refresh/tasks/start_cancel_instance_refresh.yml +++ /dev/null @@ -1,206 +0,0 @@ ---- -- name: test invalid cancelation - V1 - (pre-refresh) - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" - ignore_errors: true - register: result - -- name: Assert that module failed with proper message - assert: - that: - - "'An error occurred (ActiveInstanceRefreshNotFound) when calling the CancelInstanceRefresh operation: No in progress or pending Instance Refresh found for Auto Scaling group ' ~ resource_prefix ~ '-asg' in result.msg" - -- name: Test starting a refresh with a valid ASG name - check_mode - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "started" - check_mode: true - register: output - -- name: Validate starting in check_mode - assert: - that: - - output is changed - - '"autoscaling:StartInstanceRefresh" not in output.resource_actions' - -- name: Test starting a refresh with a valid ASG name - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "started" - register: output - -- name: Validate start - assert: - that: - - "'instance_refresh_id' in output.instance_refreshes" - -- name: Test starting a refresh with a valid ASG name - Idempotent - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "started" - ignore_errors: true - register: output - -- name: Validate starting Idempotency - assert: - that: - - output is not changed - - '"Failed to start InstanceRefresh: An error occurred (InstanceRefreshInProgress) when calling the StartInstanceRefresh operation: An Instance Refresh is already in progress and blocks the execution of this Instance Refresh." in output.msg' - -- name: Test starting a refresh with a valid ASG name - Idempotent (check_mode) - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "started" - check_mode: true - register: output - -- name: Validate starting Idempotency in check_mode - assert: - that: - - output is not changed - - '"In check_mode - Instance Refresh is already in progress, can not start new instance refresh." in output.msg' - -- name: Test starting a refresh with a nonexistent ASG name - autoscaling_instance_refresh: - name: "nonexistentname-asg" - state: "started" - ignore_errors: true - register: result - -- name: Assert that module failed with proper message - assert: - that: - - "'Failed to start InstanceRefresh: An error occurred (ValidationError) when calling the StartInstanceRefresh operation: AutoScalingGroup name not found' in result.msg" - -- name: Test canceling a refresh with an ASG name - check_mode - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" - check_mode: true - register: output - -- name: Validate cancelation - assert: - that: - - output is not failed - - output is changed - - '"autoscaling:CancelInstanceRefresh" not in output.resource_actions' - -- name: Test canceling a refresh with an ASG name - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" - register: output - -- name: Validate cancelation - assert: - that: - - "'instance_refresh_id' in output.instance_refreshes" - -- name: Test canceling a refresh with a ASG name - Idempotent - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" - register: output - ignore_errors: true - -- name: Validate cancelling Idempotency - assert: - that: - - output is not changed - -- name: Test cancelling a refresh with a valid ASG name - Idempotent (check_mode) - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" - check_mode: true - register: output - -- name: Validate cancelling Idempotency in check_mode - assert: - that: - - output is not changed - -- name: Test starting a refresh with an ASG name and preferences dict - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "started" - preferences: - min_healthy_percentage: 10 - instance_warmup: 10 - retries: 5 - register: output - until: output is not failed - -- name: Assert that module succeed with preferences - assert: - that: - - "'instance_refresh_id' in output.instance_refreshes" - -- name: Re-test canceling a refresh with an ASG name - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" - register: output - -- name: Assert that module returned instance refresh id - assert: - that: - - "'instance_refresh_id' in output.instance_refreshes" - -- name: Test valid start - V1 - (with preferences missing instance_warmup) - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "started" - preferences: - min_healthy_percentage: 10 - retries: 5 - register: output - until: output is not failed - -- name: Validate start with preferences missing instance warmup - assert: - that: - - "'instance_refresh_id' in output.instance_refreshes" - -- name: Re-test canceling a refresh with an ASG name - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" - register: output - -- name: Validate canceling Idempotency - assert: - that: - - "'instance_refresh_id' in output.instance_refreshes" - -- name: Test valid start - V2 - (with preferences missing min_healthy_percentage) - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "started" - preferences: - instance_warmup: 10 - retries: 5 - register: output - until: output is not failed - -- name: Assert that module did not returned and instance refresh id - assert: - that: - - "'instance_refresh_id' in output.instance_refreshes" - -- name: Test invalid cancelation - V2 - (with preferences) - autoscaling_instance_refresh: - name: "{{ asg_name }}" - state: "cancelled" - preferences: - min_healthy_percentage: 10 - instance_warmup: 10 - ignore_errors: true - register: result - -- name: Assert that module failed with proper message - assert: - that: - - "'can not pass preferences dict when canceling a refresh' in result.msg" diff --git a/tests/unit/plugins/modules/test_autoscaling_instance_refresh.py b/tests/unit/plugins/modules/test_autoscaling_instance_refresh.py deleted file mode 100644 index 590074367a2..00000000000 --- a/tests/unit/plugins/modules/test_autoscaling_instance_refresh.py +++ /dev/null @@ -1,28 +0,0 @@ -# (c) 2024 Red Hat Inc. -# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) - -import pytest - -from ansible_collections.community.aws.plugins.modules.autoscaling_instance_refresh import validate_healthy_percentage - - -@pytest.mark.parametrize( - "min_healthy, max_healthy, expected_error", - [ - (90, None, None), - (-1, None, "The value range for the min_healthy_percentage is 0 to 100."), - (101, None, "The value range for the min_healthy_percentage is 0 to 100."), - (None, 90, "The value range for the max_healthy_percentage is 100 to 200."), - (None, 201, "The value range for the max_healthy_percentage is 100 to 200."), - (None, 100, "You must also specify min_healthy_percentage when max_healthy_percentage is specified."), - (10, 100, None), - ( - 10, - 150, - "The difference between the max_healthy_percentage and min_healthy_percentage cannot be greater than 100.", - ), - ], -) -def test_validate_healthy_percentage(min_healthy, max_healthy, expected_error): - preferences = dict(min_healthy_percentage=min_healthy, max_healthy_percentage=max_healthy) - assert expected_error == validate_healthy_percentage(preferences)