Repository: ansible-collections/community.aws

Issue:
route53_health_check resource_path uniqueness ignored
<!--- Verify first that your issue is not already reported on GitHub -->
<!--- Also test if the latest release and devel branch are affected too -->
<!--- Complete *all* sections as described, this form is processed automatically -->

##### SUMMARY
<!--- Explain the problem briefly below -->
Moving [issue](https://github.com/ansible/ansible/issues/23110) from ansible repository to community.aws collections.
Tried to create multiple route53 healthchecks to the same server but different resource paths using with_items . Instead of creating one health check for each resource path, only the first is created.
##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below, use your best guess if unsure -->

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```paste below
ansible 2.2.2.0
```


##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: set up route53 health checks
  connection: local
  become: false
  route53_health_check:
    failure_threshold: 3
    ip_address: '{{ ip_address }}'
    port: 80
    request_interval: 30
    resource_path: '{{ item }}'
    state: present
    type: HTTP
  register: result
  with_items:
    - /some_status1
    - /other_status2
```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- Describe what you expected to happen when running the steps above -->
2 health checks created
result contains health_check.ids for each health check

##### ACTUAL RESULTS
<!--- Describe what actually happened. If possible run with extra verbosity (-vvvv) -->

1 health check created
result contains two items, both having the same health_check.id

<!--- Paste verbatim command output between quotes -->
```paste below

```



Discussion:
Files identified in the description:
None

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->

Resolving patch:
diff --git a/plugins/modules/route53_health_check.py b/plugins/modules/route53_health_check.py
--- a/plugins/modules/route53_health_check.py
+++ b/plugins/modules/route53_health_check.py
@@ -44,7 +44,7 @@
     description:
       - The type of health check that you want to create, which indicates how
         Amazon Route 53 determines whether an endpoint is healthy.
-    required: true
+      - Once health_check is created, type can not be changed.
     choices: [ 'HTTP', 'HTTPS', 'HTTP_STR_MATCH', 'HTTPS_STR_MATCH', 'TCP' ]
     type: str
   resource_path:
@@ -86,6 +86,28 @@
       - Will default to C(3) if not specified on creation.
     choices: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
     type: int
+  health_check_name:
+    description:
+      - Name of the Health Check.
+      - Used together with I(use_unique_names) to set/make use of I(health_check_name) as a unique identifier.
+    type: str
+    required: False
+    aliases: ['name']
+    version_added: 4.1.0
+  use_unique_names:
+    description:
+      - Used together with I(health_check_name) to set/make use of I(health_check_name) as a unique identifier.
+    type: bool
+    required: False
+    version_added: 4.1.0
+  health_check_id:
+    description:
+      - ID of the health check to be update or deleted.
+      - If provided, a health check can be updated or deleted based on the ID as unique identifier.
+    type: str
+    required: False
+    aliases: ['id']
+    version_added: 4.1.0
 author:
   - "zimbatm (@zimbatm)"
 notes:
@@ -120,10 +142,35 @@
     weight: 100
     health_check: "{{ my_health_check.health_check.id }}"
 
+- name: create a simple health check with health_check_name as unique identifier
+  community.aws.route53_health_check:
+    state: present
+    health_check_name: ansible
+    fqdn: ansible.com
+    port: 443
+    type: HTTPS
+    use_unique_names: true
+
 - name: Delete health-check
   community.aws.route53_health_check:
     state: absent
     fqdn: host1.example.com
+
+- name: Update Health check by ID - update ip_address
+  community.aws.route53_health_check:
+    id: 12345678-abcd-abcd-abcd-0fxxxxxxxxxx
+    ip_address: 1.2.3.4
+
+- name: Update Health check by ID - update port
+  community.aws.route53_health_check:
+    id: 12345678-abcd-abcd-abcd-0fxxxxxxxxxx
+    ip_address: 8080
+
+- name: Delete Health check by ID
+  community.aws.route53_health_check:
+    state: absent
+    id: 12345678-abcd-abcd-abcd-0fxxxxxxxxxx
+
 '''
 
 RETURN = r'''
@@ -249,7 +296,6 @@ def find_health_check(ip_addr, fqdn, hc_type, request_interval, port):
     # Additionally, we can't properly wrap the paginator, so retrying means
     # starting from scratch with a paginator
     results = _list_health_checks()
-
     while True:
         for check in results.get('HealthChecks'):
             config = check.get('HealthCheckConfig')
@@ -268,6 +314,20 @@ def find_health_check(ip_addr, fqdn, hc_type, request_interval, port):
             return None
 
 
+def get_existing_checks_with_name():
+    results = _list_health_checks()
+    health_checks_with_name = {}
+    while True:
+        for check in results.get('HealthChecks'):
+            if 'Name' in describe_health_check(check['Id'])['tags']:
+                check_name = describe_health_check(check['Id'])['tags']['Name']
+                health_checks_with_name[check_name] = check
+        if results.get('IsTruncated', False):
+            results = _list_health_checks(Marker=results.get('NextMarker'))
+        else:
+            return health_checks_with_name
+
+
 def delete_health_check(check_id):
     if not check_id:
         return False, None
@@ -348,10 +408,14 @@ def create_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_
 
 
 def update_health_check(existing_check):
-    # In theory it's also possible to update the IPAddress, Port and
-    # FullyQualifiedDomainName, however, because we use these in lieu of a
-    # 'Name' to uniquely identify the health check this isn't currently
-    # supported.  If we accepted an ID it would be possible to modify them.
+    # It's possible to update following parameters
+    # - ResourcePath
+    # - SearchString
+    # - FailureThreshold
+    # - Disabled
+    # - IPAddress
+    # - Port
+    # - FullyQualifiedDomainName
 
     changes = dict()
     existing_config = existing_check.get('HealthCheckConfig')
@@ -372,10 +436,23 @@ def update_health_check(existing_check):
     if disabled is not None and disabled != existing_config.get('Disabled'):
         changes['Disabled'] = module.params.get('disabled')
 
+    # If updating based on Health Check ID or health_check_name, we can update
+    if module.params.get('health_check_id') or module.params.get('use_unique_names'):
+        ip_address = module.params.get('ip_address', None)
+        if ip_address is not None and ip_address != existing_config.get('IPAddress'):
+            changes['IPAddress'] = module.params.get('ip_address')
+
+        port = module.params.get('port', None)
+        if port is not None and port != existing_config.get('Port'):
+            changes['Port'] = module.params.get('port')
+
+        fqdn = module.params.get('fqdn', None)
+        if fqdn is not None and fqdn != existing_config.get('FullyQualifiedDomainName'):
+            changes['FullyQualifiedDomainName'] = module.params.get('fqdn')
+
     # No changes...
     if not changes:
         return False, None
-
     if module.check_mode:
         return True, 'update'
 
@@ -419,7 +496,7 @@ def main():
         disabled=dict(type='bool'),
         ip_address=dict(),
         port=dict(type='int'),
-        type=dict(required=True, choices=['HTTP', 'HTTPS', 'HTTP_STR_MATCH', 'HTTPS_STR_MATCH', 'TCP']),
+        type=dict(choices=['HTTP', 'HTTPS', 'HTTP_STR_MATCH', 'HTTPS_STR_MATCH', 'TCP']),
         resource_path=dict(),
         fqdn=dict(),
         string_match=dict(),
@@ -427,16 +504,27 @@ def main():
         failure_threshold=dict(type='int', choices=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
         tags=dict(type='dict', aliases=['resource_tags']),
         purge_tags=dict(type='bool'),
+        health_check_id=dict(type='str', aliases=['id'], required=False),
+        health_check_name=dict(type='str', aliases=['name'], required=False),
+        use_unique_names=dict(type='bool', required=False),
     )
 
     args_one_of = [
-        ['ip_address', 'fqdn'],
+        ['ip_address', 'fqdn', 'health_check_id'],
     ]
 
     args_if = [
         ['type', 'TCP', ('port',)],
     ]
 
+    args_required_together = [
+        ['use_unique_names', 'health_check_name'],
+    ]
+
+    args_mutually_exclusive = [
+        ['health_check_id', 'health_check_name']
+    ]
+
     global module
     global client
 
@@ -444,6 +532,8 @@ def main():
         argument_spec=argument_spec,
         required_one_of=args_one_of,
         required_if=args_if,
+        required_together=args_required_together,
+        mutually_exclusive=args_mutually_exclusive,
         supports_check_mode=True,
     )
 
@@ -455,6 +545,9 @@ def main():
             version='5.0.0', collection_name='community.aws')
         module.params['purge_tags'] = False
 
+    if not module.params.get('health_check_id') and not module.params.get('type'):
+        module.fail_json(msg="parameter 'type' is required if not updating or deleting health check by ID.")
+
     state_in = module.params.get('state')
     ip_addr_in = module.params.get('ip_address')
     port_in = module.params.get('port')
@@ -464,6 +557,8 @@ def main():
     string_match_in = module.params.get('string_match')
     request_interval_in = module.params.get('request_interval')
     failure_threshold_in = module.params.get('failure_threshold')
+    health_check_name = module.params.get('health_check_name')
+    tags = module.params.get('tags')
 
     # Default port
     if port_in is None:
@@ -484,22 +579,66 @@ def main():
     action = None
     check_id = None
 
-    existing_check = find_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_in)
-
-    if existing_check:
-        check_id = existing_check.get('Id')
-
+    if module.params.get('use_unique_names') or module.params.get('health_check_id'):
+        module.deprecate(
+            'The health_check_name is currently non required parameter.'
+            ' This behavior will change and health_check_name '
+            ' will change to required=True and use_unique_names will change to default=True in release 6.0.0.',
+            version='6.0.0', collection_name='community.aws')
+
+    # If update or delete Health Check based on ID
+    update_delete_by_id = False
+    if module.params.get('health_check_id'):
+        update_delete_by_id = True
+        id_to_update_delete = module.params.get('health_check_id')
+        try:
+            existing_check = client.get_health_check(HealthCheckId=id_to_update_delete)['HealthCheck']
+        except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
+            module.exit_json(changed=False, msg='The specified health check with ID: {0} does not exist'.format(id_to_update_delete))
+    else:
+        existing_check = find_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_in)
+        if existing_check:
+            check_id = existing_check.get('Id')
+
+    # Delete Health Check
     if state_in == 'absent':
-        changed, action = delete_health_check(check_id)
+        if update_delete_by_id:
+            changed, action = delete_health_check(id_to_update_delete)
+        else:
+            changed, action = delete_health_check(check_id)
         check_id = None
+
+    # Create Health Check
     elif state_in == 'present':
-        if existing_check is None:
+        if existing_check is None and not module.params.get('use_unique_names') and not update_delete_by_id:
             changed, action, check_id = create_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_in)
+
+        # Update Health Check
         else:
-            changed, action = update_health_check(existing_check)
+            # If health_check_name is a unique identifier
+            if module.params.get('use_unique_names'):
+                existing_checks_with_name = get_existing_checks_with_name()
+                # update the health_check if another health check with same name exists
+                if health_check_name in existing_checks_with_name:
+                    changed, action = update_health_check(existing_checks_with_name[health_check_name])
+                else:
+                    # create a new health_check if another health check with same name does not exists
+                    changed, action, check_id = create_health_check(ip_addr_in, fqdn_in, type_in, request_interval_in, port_in)
+                    # Add tag to add name to health check
+                    if check_id:
+                        if not tags:
+                            tags = {}
+                        tags['Name'] = health_check_name
+
+            else:
+                if update_delete_by_id:
+                    changed, action = update_health_check(existing_check)
+                else:
+                    changed, action = update_health_check(existing_check)
+
         if check_id:
             changed |= manage_tags(module, client, 'healthcheck', check_id,
-                                   module.params.get('tags'), module.params.get('purge_tags'))
+                                   tags, module.params.get('purge_tags'))
 
     health_check = describe_health_check(id=check_id)
     health_check['action'] = action


Test patch:
diff --git a/tests/integration/targets/route53_health_check/defaults/main.yml b/tests/integration/targets/route53_health_check/defaults/main.yml
--- a/tests/integration/targets/route53_health_check/defaults/main.yml
+++ b/tests/integration/targets/route53_health_check/defaults/main.yml
@@ -11,6 +11,7 @@
 
 #ip_address: We allocate an EIP due to route53 restrictions
 fqdn: '{{ tiny_prefix }}.route53-health.ansible.test'
+fqdn_1: '{{ tiny_prefix }}-1.route53-health.ansible.test'
 port: 8080
 type: 'TCP'
 request_interval: 30
@@ -27,7 +28,9 @@ failure_threshold_updated: 1
 # for string_match we need an _STR_MATCH type
 type_https_match: 'HTTPS_STR_MATCH'
 type_http_match: 'HTTP_STR_MATCH'
+type_http: 'HTTP'
 resource_path: '/health.php'
+resource_path_1: '/new-health.php'
 resource_path_updated: '/healthz'
 string_match: 'Hello'
 string_match_updated: 'Hello World'
diff --git a/tests/integration/targets/route53_health_check/tasks/create_multiple_health_checks.yml b/tests/integration/targets/route53_health_check/tasks/create_multiple_health_checks.yml
new file mode 100644
--- /dev/null
+++ b/tests/integration/targets/route53_health_check/tasks/create_multiple_health_checks.yml
@@ -0,0 +1,134 @@
+---
+- block:
+    - name: 'Create multiple HTTP health checks with different resource_path - check_mode'
+      route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ item }}-test-hc-delete-if-found'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ item }}'
+        use_unique_names: true
+      register: create_check
+      check_mode: true
+      with_items:
+        - '{{ resource_path }}'
+        - '{{ resource_path_1 }}'
+
+    - name: 'Check result - Create a HTTP health check - check_mode'
+      assert:
+        that:
+        - create_check is not failed
+        - create_check is changed
+        - '"route53:CreateHealthCheck" not in create_check.results[0].resource_actions'
+        - '"route53:CreateHealthCheck" not in create_check.results[1].resource_actions'
+
+    - name: 'Create multiple HTTP health checks with different resource_path'
+      route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ item }}-test-hc-delete-if-found'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ item }}'
+        use_unique_names: true
+      register: create_result
+      with_items:
+        - '{{ resource_path }}'
+        - '{{ resource_path_1 }}'
+
+    - name: Get ID's for health_checks created in above task
+      set_fact:
+        health_check_1_id: "{{ create_result.results[0].health_check.id }}"
+        health_check_2_id: "{{ create_result.results[1].health_check.id }}"
+
+    - name: Get health_check 1 info
+      community.aws.route53_info:
+        query: health_check
+        health_check_id: "{{ health_check_1_id }}"
+        health_check_method: details
+      register: health_check_1_info
+
+    - name: Get health_check 2 info
+      community.aws.route53_info:
+        query: health_check
+        health_check_id: "{{ health_check_2_id }}"
+        health_check_method: details
+      register: health_check_2_info
+
+    - name: 'Check result - Create multiple HTTP health check'
+      assert:
+        that:
+        - create_result is not failed
+        - create_result is changed
+        - '"route53:UpdateHealthCheck" not in create_result.results[0].resource_actions'
+        - '"route53:UpdateHealthCheck" not in create_result.results[1].resource_actions'
+        - health_check_1_id != health_check_2_id
+        - health_check_1_info.HealthCheck.HealthCheckConfig.ResourcePath == '{{ resource_path }}'
+        - health_check_2_info.HealthCheck.HealthCheckConfig.ResourcePath == '{{ resource_path_1 }}'
+
+    - name: 'Create multiple HTTP health checks with different resource_path - idempotency - check_mode'
+      route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ item }}-test-hc-delete-if-found'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ item }}'
+        use_unique_names: true
+      register: create_idem_check
+      check_mode: true
+      with_items:
+        - '{{ resource_path }}'
+        - '{{ resource_path_1 }}'
+
+    - name: 'Check result - Create multiple HTTP health check - idempotency - check_mode'
+      assert:
+        that:
+        - create_idem_check is not failed
+        - create_idem_check is not changed
+        - '"route53:CreateHealthCheck" not in create_idem_check.results[0].resource_actions'
+        - '"route53:CreateHealthCheck" not in create_idem_check.results[1].resource_actions'
+        - '"route53:UpdateHealthCheck" not in create_idem_check.results[0].resource_actions'
+        - '"route53:UpdateHealthCheck" not in create_idem_check.results[1].resource_actions'
+
+    - name: 'Create multiple HTTP health checks with different resource_path - idempotency'
+      route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ item }}-test-hc-delete-if-found'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ item }}'
+        use_unique_names: true
+      register: create_idem
+      check_mode: true
+      with_items:
+        - '{{ resource_path }}'
+        - '{{ resource_path_1 }}'
+
+    - name: 'Check result - Create multiple HTTP health check - idempotency - check_mode'
+      assert:
+        that:
+        - create_idem is not failed
+        - create_idem is not changed
+        - '"route53:CreateHealthCheck" not in create_idem.results[0].resource_actions'
+        - '"route53:CreateHealthCheck" not in create_idem.results[1].resource_actions'
+        - '"route53:UpdateHealthCheck" not in create_idem.results[0].resource_actions'
+        - '"route53:UpdateHealthCheck" not in create_idem.results[1].resource_actions'
+
+  always:
+    # Cleanup starts here
+      - name: 'Delete multiple HTTP health checks with different resource_path'
+        route53_health_check:
+          state: absent
+          name: '{{ tiny_prefix }}-{{ item }}-test-hc-delete-if-found'
+          ip_address: '{{ ip_address }}'
+          port: '{{ port }}'
+          type: '{{ type_http }}'
+          resource_path: '{{ item }}'
+          use_unique_names: true
+        register: delete_result
+        with_items:
+          - '{{ resource_path }}'
+          - '{{ resource_path_1 }}'
diff --git a/tests/integration/targets/route53_health_check/tasks/main.yml b/tests/integration/targets/route53_health_check/tasks/main.yml
--- a/tests/integration/targets/route53_health_check/tasks/main.yml
+++ b/tests/integration/targets/route53_health_check/tasks/main.yml
@@ -32,6 +32,12 @@
   - set_fact:
       ip_address: '{{ eip.public_ip }}'
 
+  - name: Run tests for creating multiple health checks with name as unique identifier
+    include_tasks: create_multiple_health_checks.yml
+
+  - name: Run tests for update and delete health check by ID
+    include_tasks: update_delete_by_id.yml
+
   # Minimum possible definition
   - name: 'Create a TCP health check - check_mode'
     route53_health_check:
diff --git a/tests/integration/targets/route53_health_check/tasks/update_delete_by_id.yml b/tests/integration/targets/route53_health_check/tasks/update_delete_by_id.yml
new file mode 100644
--- /dev/null
+++ b/tests/integration/targets/route53_health_check/tasks/update_delete_by_id.yml
@@ -0,0 +1,303 @@
+---
+- block:
+    - name: 'Create HTTP health check for use in this test'
+      route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-test-update-delete-by-id'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ resource_path }}'
+        fqdn: '{{ fqdn }}'
+        use_unique_names: true
+      register: create_result
+
+    - name: 'Check result - Create HTTP health check'
+      assert:
+        that:
+        - create_result is not failed
+        - create_result is changed
+        - '"route53:CreateHealthCheck" in create_result.resource_actions'
+
+    - name: Get ID for health_checks created in above task
+      set_fact:
+        health_check_id: "{{ create_result.health_check.id }}"
+
+    - name: Get health_check info
+      community.aws.route53_info:
+        query: health_check
+        health_check_id: "{{ health_check_id }}"
+        health_check_method: details
+      register: health_check_info
+
+    # Update Health Check by ID Tests
+    - name: 'Update Health Check by ID - Update Port - check_mode'
+      route53_health_check:
+        id: "{{ health_check_id }}"
+        port: 8888
+      register: update_result
+      check_mode: true
+    
+    - name: 'Check result - Update Health Check Port - check_mode'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+    
+    - name: 'Update Health Check by ID - Update Port'
+      route53_health_check:
+        id: "{{ health_check_id }}"
+        port: 8888
+      register: update_result
+
+    - name: Get health_check info
+      community.aws.route53_info:
+        query: health_check
+        health_check_id: "{{ health_check_id }}"
+        health_check_method: details
+      register: health_check_info
+
+    - name: 'Check result - Update Health Check Port'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is changed
+          - health_check_info.HealthCheck.HealthCheckConfig.Port == 8888
+
+
+    - name: 'Update Health Check by ID - Update Port - idempotency - check_mode'
+      route53_health_check:
+        id: "{{ health_check_id }}"
+        port: 8888
+      register: update_result
+      check_mode: true
+
+    - name: 'Check result - Update Health Check Port - idempotency - check_mode'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is not changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+
+    - name: 'Update Health Check by ID - Update Port - idempotency'
+      route53_health_check:
+        id: "{{ health_check_id }}"
+        port: 8888
+      register: update_result
+    
+    - name: 'Check result - Update Health Check Port - idempotency'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is not changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+
+    ##
+    - name: 'Update Health Check by ID - Update IP address and FQDN - check_mode'
+      route53_health_check:
+        id: "{{ health_check_id }}"
+        ip_address: 1.2.3.4
+        fqdn: '{{ fqdn_1 }}'
+      register: update_result
+      check_mode: true
+    
+    - name: 'Check result - Update Health Check IP address and FQDN - check_mode'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+    
+    - name: 'Update Health Check by ID - Update IP address and FQDN'
+      route53_health_check:
+        id: "{{ health_check_id }}"
+        ip_address: 1.2.3.4
+        fqdn: '{{ fqdn_1 }}'
+      register: update_result
+
+    - name: Get health_check info
+      community.aws.route53_info:
+        query: health_check
+        health_check_id: "{{ health_check_id }}"
+        health_check_method: details
+      register: health_check_info
+
+    - name: 'Check result - Update Health Check IP address and FQDN'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is changed
+          - health_check_info.HealthCheck.HealthCheckConfig.IPAddress == '1.2.3.4'
+          - health_check_info.HealthCheck.HealthCheckConfig.FullyQualifiedDomainName == "{{ fqdn_1 }}"
+
+
+    - name: 'Update Health Check by ID - Update IP address and FQDN - idempotency - check_mode'
+      route53_health_check:
+        id: "{{ health_check_id }}"
+        ip_address: 1.2.3.4
+        fqdn: '{{ fqdn_1 }}'
+      register: update_result
+      check_mode: true
+
+    - name: 'Check result - Update Health Check IP address and FQDN - idempotency - check_mode'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is not changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+
+    - name: 'Update Health Check by ID - Update IP address and FQDN - idempotency'
+      route53_health_check:
+        id: "{{ health_check_id }}"
+        ip_address: 1.2.3.4
+        fqdn: '{{ fqdn_1 }}'
+      register: update_result
+    
+    - name: 'Check result - Update Health Check IP address and FQDN - idempotency'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is not changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+
+    # Update Health Check (Port) by name
+
+    - name: 'Update Health Check by name - Update Port - check_mode'
+      route53_health_check:
+        state: present
+        port: 8080
+        type: '{{ type_http }}'
+        fqdn: '{{ fqdn }}'
+        health_check_name: '{{ tiny_prefix }}-test-update-delete-by-id'
+        use_unique_names: true
+      register: update_result
+      check_mode: true
+
+    - name: 'Check result - Update Health Check Port - check_mode'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+
+    - name: 'Update Health Check by name - Update Port'
+      route53_health_check:
+        state: present
+        port: 8080
+        type: '{{ type_http }}'
+        fqdn: '{{ fqdn }}'
+        health_check_name: '{{ tiny_prefix }}-test-update-delete-by-id'
+        use_unique_names: true
+      register: update_result
+
+    - name: Get health_check info
+      community.aws.route53_info:
+        query: health_check
+        health_check_id: "{{ health_check_id }}"
+        health_check_method: details
+      register: health_check_info
+
+    - name: 'Check result - Update Health Check Port'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is changed
+          - health_check_info.HealthCheck.HealthCheckConfig.Port == 8080
+
+    - name: 'Update Health Check by name - Update Port - idempotency - check_mode'
+      route53_health_check:
+        state: present
+        port: 8080
+        type: '{{ type_http }}'
+        fqdn: '{{ fqdn }}'
+        health_check_name: '{{ tiny_prefix }}-test-update-delete-by-id'
+        use_unique_names: true
+      register: update_result
+      check_mode: true
+
+    - name: 'Check result - Update Health Check Port - idempotency - check_mode'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is not changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+
+    - name: 'Update Health Check by name - Update Port - idempotency'
+      route53_health_check:
+        state: present
+        port: 8080
+        type: '{{ type_http }}'
+        fqdn: '{{ fqdn }}'
+        health_check_name: '{{ tiny_prefix }}-test-update-delete-by-id'
+        use_unique_names: true
+      register: update_result
+
+    - name: 'Check result - Update Health Check Port - idempotency'
+      assert:
+        that:
+          - update_result is not failed
+          - update_result is not changed
+          - '"route53:UpdateHealthCheck" not in update_result.resource_actions'
+
+    # Delete Health Check by ID Tests
+    - name: Delete Health check by ID - check_mode
+      route53_health_check:
+        state: absent
+        id: "{{ health_check_id }}"
+      register: delete_result
+      check_mode: true
+
+    - name: 'Check result - Delete Health Check by ID -check_mode'
+      assert:
+        that:
+          - delete_result is not failed
+          - delete_result is changed
+          - '"route53:DeleteHealthCheck" not in delete_result.resource_actions'
+
+    - name: Delete Health check by ID
+      route53_health_check:
+        state: absent
+        id: "{{ health_check_id }}"
+      register: delete_result
+
+    - name: 'Check result - Delete Health Check by ID'
+      assert:
+        that:
+          - delete_result is not failed
+          - delete_result is changed
+          - '"route53:DeleteHealthCheck" in delete_result.resource_actions'
+
+    - name: Delete Health check by ID - idempotency - check_mode
+      route53_health_check:
+        state: absent
+        id: "{{ health_check_id }}"
+      register: delete_result
+      check_mode: true
+
+    - name: 'Check result - Delete Health Check by ID -idempotency -check_mode'
+      assert:
+        that:
+          - delete_result is not failed
+          - delete_result is not changed
+          - '"route53:DeleteHealthCheck" not in delete_result.resource_actions'
+
+    - name: Delete Health check by ID - idempotency
+      route53_health_check:
+        state: absent
+        id: "{{ health_check_id }}"
+      register: delete_result
+
+    - name: 'Check result - Delete Health Check by ID -idempotency'
+      assert:
+        that:
+          - delete_result is not failed
+          - delete_result is not changed
+          - '"route53:DeleteHealthCheck" not in delete_result.resource_actions'
+
+  # cleanup
+  always:
+    - name: Delete Health check by ID
+      route53_health_check:
+        state: absent
+        id: "{{ health_check_id }}"