Repository: ansible-collections/amazon.aws

Issue:
route53_health_check - Name tag lost on 2nd deploy
### Summary

When updating a Route53 health check the `Name` tag is removed when using `health_check_name: my-health-check`

Tag is initially added by
https://github.com/ansible-collections/amazon.aws/blob/f9751fab28c55d793df7996f599839a3ace5414b/plugins/modules/route53_health_check.py#L624

### Issue Type

Bug Report

### Component Name

route53_health_check

### Ansible Version

```console (paste below)
$ ansible --version

ansible [core 2.12.2]
  config file = /Users/<USER>/Source/dataintelligence-ansible/ansible.cfg
  configured module search path = ['/Users/<USER>/Source/dataintelligence-ansible/library']
  ansible python module location = /Users/<USER>/Source/dataintelligence-ansible/.runtime/.pyvenv/lib/python3.9/site-packages/ansible
  ansible collection location = /Users/<USER>/.ansible/collections:/usr/share/ansible/collections
  executable location = /Users/<USER>/Source/dataintelligence-ansible/.runtime/.pyvenv/bin/ansible
  python version = 3.9.8 (main, Nov 18 2021, 16:08:04) [Clang 12.0.5 (clang-1205.0.22.9)]
  jinja version = 2.11.3
  libyaml = True
```


### Collection Versions

Manually added https://github.com/ansible-collections/amazon.aws/blob/5.0.2/plugins/modules/route53_health_check.py to my local Ansible

### AWS SDK versions

```console (paste below)
$ pip show boto boto3 botocore

Name: boto
Version: 2.49.0
Summary: Amazon Web Services Library
Home-page: https://github.com/boto/boto/
Author: Mitch Garnaat
Author-email: mitch@garnaat.com
License: MIT
Location: /Users/<USER>/Source/dataintelligence-ansible/.runtime/.pyvenv/lib/python3.9/site-packages
Requires:
Required-by:
---
Name: boto3
Version: 1.20.48
Summary: The AWS SDK for Python
Home-page: https://github.com/boto/boto3
Author: Amazon Web Services
Author-email:
License: Apache License 2.0
Location: /Users/<USER>/Source/dataintelligence-ansible/.runtime/.pyvenv/lib/python3.9/site-packages
Requires: botocore, jmespath, s3transfer
Required-by: aws-sam-cli, aws-sam-translator, serverlessrepo
---
Name: botocore
Version: 1.23.48
Summary: Low-level, data-driven core of boto 3.
Home-page: https://github.com/boto/botocore
Author: Amazon Web Services
Author-email:
License: Apache License 2.0
Location: /Users/<USER>/Source/dataintelligence-ansible/.runtime/.pyvenv/lib/python3.9/site-packages
Requires: jmespath, python-dateutil, urllib3
Required-by: awscli, boto3, s3transfer
```


### Configuration

```console (paste below)
$ ansible-config dump --only-changed

```


### OS / Environment

macOS 11.6

### Steps to Reproduce

Run the following playbook twice

```yaml (paste below)
---
- hosts: localhost
  tasks:
    - name: Create a health-check
      route53_health_check:
        health_check_name: my-health-check
        use_unique_names: true
        fqdn: ***
        type: HTTPS
        resource_path: /
        request_interval: 30
        failure_threshold: 3
        tags:
          Service: my-service
          Owner: some-owner
          Lifecycle: dev
      register: my_health_check
```

### Expected Results

`Name` tag added during first run and never removed

### Actual Results

First run: Health check created, `Name` tag added

```yaml (paste below)
changed: [localhost] => changed=true
  health_check:
    action: create
    caller_reference: ***
    health_check_config:
      disabled: false
      enable_sni: true
      failure_threshold: 3
      fully_qualified_domain_name: ***
      inverted: false
      measure_latency: false
      port: 443
      request_interval: 30
      resource_path: /
      type: HTTPS
    health_check_version: 1
    id: ***
    tags:
      Lifecycle: dev
      Name: my-health-check
      Owner: some-owner
      Service: my-service
```

Second run: Health check marked as changed (expected noop [ok]), `Name` tag removed (not expected)

```yaml (paste below)
changed: [localhost] => changed=true
  health_check:
    action: null
    caller_reference: ***
    health_check_config:
      disabled: false
      enable_sni: true
      failure_threshold: 3
      fully_qualified_domain_name: ***
      inverted: false
      measure_latency: false
      port: 443
      request_interval: 30
      resource_path: /
      type: HTTPS
    health_check_version: 1
    id: ***
    tags:
      Lifecycle: dev
      Owner: some-owner
      Service: my-service
```


### Code of Conduct

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


Discussion:
Files identified in the description:
* [`plugins/modules/route53_health_check.py`](https://github.com/['ansible-collections/amazon.aws', 'ansible-collections/community.aws', 'ansible-collections/community.vmware']/blob/main/plugins/modules/route53_health_check.py)

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 --->
cc @jillr @s-hertel @tremble @zimbatm
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

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
@@ -573,6 +573,7 @@ def main():
     request_interval_in = module.params.get('request_interval')
     health_check_name = module.params.get('health_check_name')
     tags = module.params.get('tags')
+    purge_tags = module.params.get('purge_tags')
 
     # Default port
     if port_in is None:
@@ -632,24 +633,24 @@ def main():
             # If health_check_name is a unique identifier
             if module.params.get('use_unique_names'):
                 existing_checks_with_name = get_existing_checks_with_name()
+                if tags is None:
+                    purge_tags = False
+                    tags = {}
+                tags['Name'] = health_check_name
+
                 # update the health_check if another health check with same name exists
                 if health_check_name in existing_checks_with_name:
                     changed, action, check_id = 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:
                 changed, action, check_id = update_health_check(existing_check)
 
         if check_id:
             changed |= manage_tags(module, client, 'healthcheck', check_id,
-                                   tags, module.params.get('purge_tags'))
+                                   tags, 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/tasks/create_multiple_health_checks.yml b/tests/integration/targets/route53_health_check/tasks/create_multiple_health_checks.yml
--- 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
@@ -102,12 +102,11 @@
         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'
+    - name: 'Check result - Create multiple HTTP health check - idempotency'
       assert:
         that:
         - create_idem is not failed
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,9 @@
   - set_fact:
       ip_address: '{{ eip.public_ip }}'
 
+  - name: Run tests for create and delete health check with tags and name as unique identifier
+    include_tasks: named_health_check_tag_operations.yml
+
   - name: Run tests for creating multiple health checks with name as unique identifier
     include_tasks: create_multiple_health_checks.yml
 
diff --git a/tests/integration/targets/route53_health_check/tasks/named_health_check_tag_operations.yml b/tests/integration/targets/route53_health_check/tasks/named_health_check_tag_operations.yml
new file mode 100644
--- /dev/null
+++ b/tests/integration/targets/route53_health_check/tasks/named_health_check_tag_operations.yml
@@ -0,0 +1,271 @@
+---
+- block:
+    # Create Health Check =================================================================
+    - name: 'Create Health Check with name and tags'
+      amazon.aws.route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ resource_path }}'
+        use_unique_names: true
+        fqdn: '{{ fqdn }}'
+        tags:
+          Service: my-service
+          Owner: my-test-xyz
+          Lifecycle: dev
+      register: create_result
+
+    - name: Get Health Check tags
+      amazon.aws.route53_info:
+        query: health_check
+        resource_id:  "{{ create_result.health_check.id }}"
+        health_check_method: tags
+      register: health_check_tags
+    - set_fact:
+        tags_keys_list: "{{ health_check_tags.ResourceTagSets[0].Tags | map(attribute='Key') | list }}"
+
+    - name: 'Check result - Create HTTP health check'
+      assert:
+        that:
+        - create_result is not failed
+        - create_result is changed
+        - tags_keys_list | length == 4
+        - '"Service" in tags_keys_list'
+        - '"Owner" in tags_keys_list'
+        - '"Lifecycle" in tags_keys_list'
+        - '"Name" in tags_keys_list'
+
+    # Create Health Check - check Idempotenty =================================================================
+    - name: 'Create Health Check with name and tags - idempotency'
+      amazon.aws.route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ resource_path }}'
+        use_unique_names: true
+        tags:
+          Service: my-service
+          Owner: my-test-xyz
+          Lifecycle: dev
+        fqdn: '{{ fqdn }}'
+      register: create_idem
+
+    - name: Get Health Check tags
+      amazon.aws.route53_info:
+        query: health_check
+        resource_id:  "{{ create_idem.health_check.id }}"
+        health_check_method: tags
+      register: health_check_tags
+    - set_fact:
+        tags_keys_list: "{{ health_check_tags.ResourceTagSets[0].Tags | map(attribute='Key') | list }}"
+
+    - name: 'Check result - Create HTTP health check - idempotency'
+      assert:
+        that:
+        - create_idem is not failed
+        - create_idem is not changed
+        - tags_keys_list | length == 4
+        - '"Service" in tags_keys_list'
+        - '"Owner" in tags_keys_list'
+        - '"Lifecycle" in tags_keys_list'
+        - '"Name" in tags_keys_list'
+
+    # Create Health Check - Update Tags =================================================================
+    - name: 'Create Health Check with name and tags'
+      amazon.aws.route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ resource_path }}'
+        use_unique_names: true
+        tags:
+          Service: my-service
+          NewOwner: my-test-abcd
+        fqdn: '{{ fqdn }}'
+      register: create_hc_update_tags
+
+    - name: Get Health Check tags
+      amazon.aws.route53_info:
+        query: health_check
+        resource_id:  "{{ create_hc_update_tags.health_check.id }}"
+        health_check_method: tags
+      register: health_check_tags
+    - set_fact:
+        tags_keys_list: "{{ health_check_tags.ResourceTagSets[0].Tags | map(attribute='Key') | list }}"
+
+    - name: 'Check result - Create HTTP health check'
+      assert:
+        that:
+        - create_hc_update_tags is not failed
+        - create_hc_update_tags is changed
+        - tags_keys_list | length == 3
+        - '"Service" in tags_keys_list'
+        - '"NewOwner" in tags_keys_list'
+        - '"Owner" not in tags_keys_list'
+        - '"Lifecycle" not in tags_keys_list'
+        - '"Name" in tags_keys_list'
+
+    # Create Health Check - Update Tags - Idempotency =================================================================
+    - name: 'Create Health Check with name and tags - Idempotency'
+      amazon.aws.route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ resource_path }}'
+        use_unique_names: true
+        tags:
+          Service: my-service
+          NewOwner: my-test-abcd
+        fqdn: '{{ fqdn }}'
+      register: create_hc_update_tags_idem
+
+    - name: Get Health Check tags
+      amazon.aws.route53_info:
+        query: health_check
+        resource_id:  "{{ create_hc_update_tags_idem.health_check.id }}"
+        health_check_method: tags
+      register: health_check_tags
+    - set_fact:
+        tags_keys_list: "{{ health_check_tags.ResourceTagSets[0].Tags | map(attribute='Key') | list }}"
+
+    - name: 'Check result - Create HTTP health check'
+      assert:
+        that:
+        - create_hc_update_tags_idem is not failed
+        - create_hc_update_tags_idem is not changed
+        - tags_keys_list | length == 3
+        - '"Service" in tags_keys_list'
+        - '"NewOwner" in tags_keys_list'
+        - '"Owner" not in tags_keys_list'
+        - '"Lifecycle" not in tags_keys_list'
+        - '"Name" in tags_keys_list'
+
+    # Create Health Check - test purge_tags behavior =================================================================
+
+    - name: 'Create Health Check with name with tags={} and purge_tags=false (should not remove existing tags)'
+      amazon.aws.route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ resource_path }}'
+        use_unique_names: true
+        fqdn: '{{ fqdn }}'
+        tags: {}
+        purge_tags: false
+      register: create_hc_update_tags
+
+    - name: Get Health Check tags
+      amazon.aws.route53_info:
+        query: health_check
+        resource_id:  "{{ create_hc_update_tags.health_check.id }}"
+        health_check_method: tags
+      register: health_check_tags
+    - set_fact:
+        tags_keys_list: "{{ health_check_tags.ResourceTagSets[0].Tags | map(attribute='Key') | list }}"
+
+    - name: 'Check result - Create HTTP health check'
+      assert:
+        that:
+        - create_hc_update_tags is not failed
+        - create_hc_update_tags is not changed
+        - tags_keys_list | length == 3
+        - '"Service" in tags_keys_list'
+        - '"NewOwner" in tags_keys_list'
+        - '"Name" in tags_keys_list'
+
+    - name: 'Create Health Check with name with tags=None with purge_tags=true (should not remove existing tags)'
+      amazon.aws.route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ resource_path }}'
+        use_unique_names: true
+        fqdn: '{{ fqdn }}'
+        purge_tags: true
+      register: create_hc_update_tags
+
+    - name: Get Health Check tags
+      amazon.aws.route53_info:
+        query: health_check
+        resource_id:  "{{ create_hc_update_tags.health_check.id }}"
+        health_check_method: tags
+      register: health_check_tags
+    - set_fact:
+        tags_keys_list: "{{ health_check_tags.ResourceTagSets[0].Tags | map(attribute='Key') | list }}"
+
+    - name: 'Check result - Create HTTP health check'
+      assert:
+        that:
+        - create_hc_update_tags is not failed
+        - create_hc_update_tags is not changed
+        - tags_keys_list | length == 3
+        - '"Service" in tags_keys_list'
+        - '"NewOwner" in tags_keys_list'
+        - '"Name" in tags_keys_list'
+
+    - name: 'Create Health Check with name with tags={} with purge_tags=true (should remove existing tags except Name)'
+      amazon.aws.route53_health_check:
+        state: present
+        name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations'
+        ip_address: '{{ ip_address }}'
+        port: '{{ port }}'
+        type: '{{ type_http }}'
+        resource_path: '{{ resource_path }}'
+        use_unique_names: true
+        fqdn: '{{ fqdn }}'
+        tags: {}
+        purge_tags: true
+      register: create_hc_update_tags
+
+    - name: Get Health Check tags
+      amazon.aws.route53_info:
+        query: health_check
+        resource_id:  "{{ create_hc_update_tags.health_check.id }}"
+        health_check_method: tags
+      register: health_check_tags
+    - set_fact:
+        tags_keys_list: "{{ health_check_tags.ResourceTagSets[0].Tags | map(attribute='Key') | list }}"
+
+    - name: 'Check result - Create HTTP health check'
+      assert:
+        that:
+        - create_hc_update_tags is not failed
+        - create_hc_update_tags is changed
+        - tags_keys_list | length == 1
+        - '"Service" not in tags_keys_list'
+        - '"NewOwner" not in tags_keys_list'
+        - '"Name" in tags_keys_list'
+
+  # Cleanup starts here =================================================================
+  always:
+      - name: 'Delete HTTP health check with use_unique_names'
+        amazon.aws.route53_health_check:
+          state: absent
+          name: '{{ tiny_prefix }}-{{ resource_path }}-test-hc-tag-operations'
+          ip_address: '{{ ip_address }}'
+          port: '{{ port }}'
+          type: '{{ type_http }}'
+          resource_path: '{{ resource_path }}'
+          use_unique_names: true
+          fqdn: '{{ fqdn }}'
+          tags: {}
+        register: delete_result
+        with_items:
+          - '{{ resource_path }}'
+
+      - assert:
+          that:
+            - delete_result is changed
+            - delete_result is not failed