Repository: ansible-collections/community.vmware

Issue:
vmware_tag_manager: Changing the value of a single cardinal tag category fails with 'Tagging cardinality violation'
<!--- 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
Changing the value of a single cardinal tag category fails with `Tagging cardinality violation`.

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
vmware_tag_manager

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```
ansible [core 2.13.4]
  config file = None
  configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ansible/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/ansible/.local/bin/ansible
  python version = 3.10.6 (main, Aug 10 2022, 11:40:04) [GCC 11.3.0]
  jinja version = 3.0.3
  libyaml = True
```

##### COLLECTION VERSION
<!--- Paste verbatim output from "ansible-galaxy collection list <namespace>.<collection>"  between the quotes
for example: ansible-galaxy collection list community.general
-->
```
download_url: https://galaxy.ansible.com/download/community-vmware-3.0.0.tar.gz
format_version: 1.0.0
name: vmware
namespace: community
server: https://galaxy.ansible.com/api/
signatures: []
version: 3.0.0
version_url: https://galaxy.ansible.com/api/v2/collections/community/vmware/versions/3.0.0/
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```
INVENTORY_ENABLED(/home/ansible/automation/ansible.cfg) = ['host_list', 'script', 'auto', 'yaml', 'ini', 'toml']
TRANSFORM_INVALID_GROUP_CHARS(/home/ansible/automation/ansible.cfg) = ignore
```

##### OS / ENVIRONMENT
vSphere 7.0.3
The issue is not dependent of the underlying OS

##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```
- name: Set and modify a single cardinal tag category
  community.vmware.vmware_tag_manager:
    hostname: "{{ vcenter_hostname }}"
    username: "{{ vcenter_username }}"
    password: "{{ vcenter_password }}"
    validate_certs: false
    state: set
    object_name: "{{ vm_name }}"
    object_type: VirtualMachine
    tag_names:
      - category: Environment
        tag: "{{ env }}"
  loop:
    - Prod
    - Lab
  loop_control:
    loop_var: env
```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
The tag tag category `Prodtype` has the value `Lab`.


##### ACTUAL RESULTS
The task fails:
```
TASK [vsphere : Set and modify a single cardinal tag category] **********************
fatal: [molecule-ubuntu-jammy.local -> localhost]: FAILED! => {"changed": false, "msg": "Tagging cardinality violation"}
```

vmware_tag_manager: Changing the value of a single cardinal tag category fails with 'Tagging cardinality violation'
<!--- 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
Changing the value of a single cardinal tag category fails with `Tagging cardinality violation`.

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
vmware_tag_manager

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes -->
```
ansible [core 2.13.4]
  config file = None
  configured module search path = ['/home/ansible/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ansible/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/ansible/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/ansible/.local/bin/ansible
  python version = 3.10.6 (main, Aug 10 2022, 11:40:04) [GCC 11.3.0]
  jinja version = 3.0.3
  libyaml = True
```

##### COLLECTION VERSION
<!--- Paste verbatim output from "ansible-galaxy collection list <namespace>.<collection>"  between the quotes
for example: ansible-galaxy collection list community.general
-->
```
download_url: https://galaxy.ansible.com/download/community-vmware-3.0.0.tar.gz
format_version: 1.0.0
name: vmware
namespace: community
server: https://galaxy.ansible.com/api/
signatures: []
version: 3.0.0
version_url: https://galaxy.ansible.com/api/v2/collections/community/vmware/versions/3.0.0/
```

##### CONFIGURATION
<!--- Paste verbatim output from "ansible-config dump --only-changed" between quotes -->
```
INVENTORY_ENABLED(/home/ansible/automation/ansible.cfg) = ['host_list', 'script', 'auto', 'yaml', 'ini', 'toml']
TRANSFORM_INVALID_GROUP_CHARS(/home/ansible/automation/ansible.cfg) = ignore
```

##### OS / ENVIRONMENT
vSphere 7.0.3
The issue is not dependent of the underlying OS

##### STEPS TO REPRODUCE
<!--- Describe exactly how to reproduce the problem, using a minimal test-case -->

<!--- Paste example playbooks or commands between quotes below -->
```
- name: Set and modify a single cardinal tag category
  community.vmware.vmware_tag_manager:
    hostname: "{{ vcenter_hostname }}"
    username: "{{ vcenter_username }}"
    password: "{{ vcenter_password }}"
    validate_certs: false
    state: set
    object_name: "{{ vm_name }}"
    object_type: VirtualMachine
    tag_names:
      - category: Environment
        tag: "{{ env }}"
  loop:
    - Prod
    - Lab
  loop_control:
    loop_var: env
```

<!--- HINT: You can paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
The tag tag category `Prodtype` has the value `Lab`.


##### ACTUAL RESULTS
The task fails:
```
TASK [vsphere : Set and modify a single cardinal tag category] **********************
fatal: [molecule-ubuntu-jammy.local -> localhost]: FAILED! => {"changed": false, "msg": "Tagging cardinality violation"}
```



Discussion:

Resolving patch:
diff --git a/plugins/modules/vmware_tag_manager.py b/plugins/modules/vmware_tag_manager.py
--- a/plugins/modules/vmware_tag_manager.py
+++ b/plugins/modules/vmware_tag_manager.py
@@ -339,20 +339,20 @@ def ensure_state(self):
                         self.module.fail_json(msg="%s" % self.get_error_message(error))
 
         elif action == 'set':
-            for tag_obj in tag_objs:
-                if tag_obj not in available_tag_obj:
-                    # Tag is not already applied
+            for av_tag in available_tag_obj:
+                if av_tag not in tag_objs:
+                    # Tag not in the defined list
                     try:
-                        self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
+                        self.tag_association_svc.detach(tag_id=av_tag.id, object_id=self.dynamic_managed_object)
                         changed = True
                     except Error as error:
                         self.module.fail_json(msg="%s" % self.get_error_message(error))
 
-            for av_tag in available_tag_obj:
-                if av_tag not in tag_objs:
-                    # Tag not in the defined list
+            for tag_obj in tag_objs:
+                if tag_obj not in available_tag_obj:
+                    # Tag is not already applied
                     try:
-                        self.tag_association_svc.detach(tag_id=av_tag.id, object_id=self.dynamic_managed_object)
+                        self.tag_association_svc.attach(tag_id=tag_obj.id, object_id=self.dynamic_managed_object)
                         changed = True
                     except Error as error:
                         self.module.fail_json(msg="%s" % self.get_error_message(error))


Test patch: