Repository: ansible-collections/community.vmware

Issue:
Custom Attributes set fail if the attribute name is defined twice (for VM and host)
##### SUMMARY
Using the  community.vmware.vmware_guest_custom_attributes function to set some attributes for a VM, I get a failure in a specific case.
We have some custom attributes with the same namebut on two king of object : vm and esxi.
Say we have an custom attribute named 'MainUser' of type 'VirtualMachine', and another custom attribute also named 'MainUser' but of type 'Host'.
In that case, troyint to set a value for this specific custom attribute for a VirtualMachine fails. 

##### ISSUE TYPE
- Bug Report

##### COMPONENT NAME
The error is located in the file nsible_collections/community/vmware/plugins/modules/vmware_guest_custom_attributes.py, line 196, message is    invalidProperty = 'entity'
The version of collection 'community.vmware' is 3.6.0 (I believe it is the latest version ?)
reverting to the version 2.10.2 that I use on a much older system resolve this bug for me.

##### ANSIBLE VERSION
ansible [core 2.15.0]
  config file = /root/viebs/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.16 (main, Dec  8 2022, 00:00:00) [GCC 11.3.1 20221121 (Red Hat 11.3.1-4)] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True


##### COLLECTION VERSION
# /root/.ansible/collections/ansible_collections
Collection       Version
---------------- -------
community.vmware 3.7.0

##### CONFIGURATION
CONFIG_FILE() = /root/viebs/ansible.cfg
INVENTORY_ENABLED(/root/viebs/ansible.cfg) = ['vmware_vm_inventory']

##### OS / ENVIRONMENT
OS : RockyLinux 9.2

##### STEPS TO REPRODUCE
In your VCenter, create two CustomAttributes of the same name: 

Name               Type
MainUser         VirtualMachine
MainUser         Host
```
# test-CA.yaml : demonstrate a trouble in setting a value for an Custom Attribute
#                defined twice in the VCenter with community.vmware.vmware_guest_custom_attributes version 3.7.0
#                Prerequisite:
#                Create two general Custom Attributes with the same name, but for two categories (not a global one)
#                Name                    Type
#                MainUser                Virtual Machine
#                MainUser                Host
---
- name: test Custom Attributes
  hosts: localhost
  gather_facts: yes
  # Variables communes

  # This file contains secrets for our VCenter
  tasks:
  - name: include vault
    ansible.builtin.include_vars:
      file: vcenter.vmware.yaml

  - name: Add some Custom Attributes to the VM
    community.vmware.vmware_guest_custom_attributes:
      hostname: "{{ hostname[vcenter] }}"
      username: "{{ username[vcenter] }}"
      password: "{{ password[vcenter] }}"
      validate_certs: "{{ validate_certs[vcenter] }}"
      datacenter: "{{ datacenter }}"
      name: "{{ source_vm }}-clone"
      folder: "{{ source_folder }}"
      attributes:
      - name: MainUser
        value: "John Doe"
    register: attributes
```

Result in version 2.10.2:

[root@kub09 viebs]# ansible-playbook --vault-password-file ~/.secret.pass --extra-vars "@vm/IACOP56.yaml" test-CA.yaml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [test Custom Attributes] *********************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [localhost]

TASK [include vault] ******************************************************************************************************************************************************
ok: [localhost]

TASK [Add some Custom Attributes to the VM] *******************************************************************************************************************************
changed: [localhost]

PLAY RECAP ****************************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[root@kub09 viebs]# ansible-galaxy collection list community.vmware

# /root/.ansible/collections/ansible_collections
Collection       Version
---------------- -------
community.vmware 2.10.2


Result in version 3.7.0:
[root@kub09 viebs]# ansible-galaxy collection install --upgrade community.vmware
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/download/community-vmware-3.7.0.tar.gz to /root/.ansible/tmp/ansible-local-9913yax99p5s/tmp0q8zwhed/community-vmware-3.7.0-vlrh096o
Installing 'community.vmware:3.7.0' to '/root/.ansible/collections/ansible_collections/community/vmware'
community.vmware:3.7.0 was installed successfully
[root@kub09 viebs]# ansible-playbook --vault-password-file ~/.secret.pass --extra-vars "@vm/IACOP56.yaml" test-CA.yaml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [test Custom Attributes] *********************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [localhost]

TASK [include vault] ******************************************************************************************************************************************************
ok: [localhost]

TASK [Add some Custom Attributes to the VM] *******************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: }
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/root/.ansible/tmp/ansible-tmp-1686818021.0248926-9978-167505637494988/AnsiballZ_vmware_guest_custom_attributes.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/root/.ansible/tmp/ansible-tmp-1686818021.0248926-9978-167505637494988/AnsiballZ_vmware_guest_custom_attributes.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/root/.ansible/tmp/ansible-tmp-1686818021.0248926-9978-167505637494988/AnsiballZ_vmware_guest_custom_attributes.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.vmware.plugins.modules.vmware_guest_custom_attributes', init_globals=dict(_module_fqn='ansible_collections.community.vmware.plugins.modules.vmware_guest_custom_attributes', _modlib_path=modlib_path),\n  File \"/usr/lib64/python3.9/runpy.py\", line 225, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib64/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib64/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_community.vmware.vmware_guest_custom_attributes_payload_h1kwodz8/ansible_community.vmware.vmware_guest_custom_attributes_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_custom_attributes.py\", line 358, in <module>\n  File \"/tmp/ansible_community.vmware.vmware_guest_custom_attributes_payload_h1kwodz8/ansible_community.vmware.vmware_guest_custom_attributes_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_custom_attributes.py\", line 346, in main\n  File \"/tmp/ansible_community.vmware.vmware_guest_custom_attributes_payload_h1kwodz8/ansible_community.vmware.vmware_guest_custom_attributes_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_custom_attributes.py\", line 196, in set_custom_field\n  File \"/usr/local/lib/python3.9/site-packages/pyVmomi/VmomiSupport.py\", line 598, in <lambda>\n    self.f(*(self.args + (obj,) + args), **kwargs)\n  File \"/usr/local/lib/python3.9/site-packages/pyVmomi/VmomiSupport.py\", line 388, in _InvokeMethod\n    return self._stub.InvokeMethod(self, info, args)\n  File \"/usr/local/lib/python3.9/site-packages/pyVmomi/SoapAdapter.py\", line 1577, in InvokeMethod\n    raise obj  # pylint: disable-msg=E0702\npyVmomi.VmomiSupport.vmodl.fault.InvalidArgument: (vmodl.fault.InvalidArgument) {\n   dynamicType = <unset>,\n   dynamicProperty = (vmodl.DynamicProperty) [],\n   msg = 'A specified parameter was not correct: entity',\n   faultCause = <unset>,\n   faultMessage = (vmodl.LocalizableMessage) [],\n   invalidProperty = 'entity'\n}\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

PLAY RECAP ****************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

##### EXPECTED RESULTS
Note that, even in version 3.7.0, the attribute is set, but the error rise just after.
I expect no error, like in older versions :) 


##### ACTUAL RESULTS
Attibute value is set, but the ansible playbook stops in error

<!--- Paste verbatim command output between quotes -->
```
# ansible-playbook --vault-password-file ~/.secret.pass --extra-vars "@vm/IACOP56.yaml" test-CA.yaml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [test Custom Attributes] *********************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [localhost]

TASK [include vault] ******************************************************************************************************************************************************
ok: [localhost]

TASK [Add some Custom Attributes to the VM] *******************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: }
fatal: [localhost]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"/root/.ansible/tmp/ansible-tmp-1686818021.0248926-9978-167505637494988/AnsiballZ_vmware_guest_custom_attributes.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/root/.ansible/tmp/ansible-tmp-1686818021.0248926-9978-167505637494988/AnsiballZ_vmware_guest_custom_attributes.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/root/.ansible/tmp/ansible-tmp-1686818021.0248926-9978-167505637494988/AnsiballZ_vmware_guest_custom_attributes.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.vmware.plugins.modules.vmware_guest_custom_attributes', init_globals=dict(_module_fqn='ansible_collections.community.vmware.plugins.modules.vmware_guest_custom_attributes', _modlib_path=modlib_path),\n  File \"/usr/lib64/python3.9/runpy.py\", line 225, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib64/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib64/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_community.vmware.vmware_guest_custom_attributes_payload_h1kwodz8/ansible_community.vmware.vmware_guest_custom_attributes_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_custom_attributes.py\", line 358, in <module>\n  File \"/tmp/ansible_community.vmware.vmware_guest_custom_attributes_payload_h1kwodz8/ansible_community.vmware.vmware_guest_custom_attributes_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_custom_attributes.py\", line 346, in main\n  File \"/tmp/ansible_community.vmware.vmware_guest_custom_attributes_payload_h1kwodz8/ansible_community.vmware.vmware_guest_custom_attributes_payload.zip/ansible_collections/community/vmware/plugins/modules/vmware_guest_custom_attributes.py\", line 196, in set_custom_field\n  File \"/usr/local/lib/python3.9/site-packages/pyVmomi/VmomiSupport.py\", line 598, in <lambda>\n    self.f(*(self.args + (obj,) + args), **kwargs)\n  File \"/usr/local/lib/python3.9/site-packages/pyVmomi/VmomiSupport.py\", line 388, in _InvokeMethod\n    return self._stub.InvokeMethod(self, info, args)\n  File \"/usr/local/lib/python3.9/site-packages/pyVmomi/SoapAdapter.py\", line 1577, in InvokeMethod\n    raise obj  # pylint: disable-msg=E0702\npyVmomi.VmomiSupport.vmodl.fault.InvalidArgument: (vmodl.fault.InvalidArgument) {\n   dynamicType = <unset>,\n   dynamicProperty = (vmodl.DynamicProperty) [],\n   msg = 'A specified parameter was not correct: entity',\n   faultCause = <unset>,\n   faultMessage = (vmodl.LocalizableMessage) [],\n   invalidProperty = 'entity'\n}\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

PLAY RECAP ****************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

```



Discussion:
I have the same problem. Try to upgrade to community.vmware 3.9.0 but the problem remains
@Schirrms @df-cgdm The problem is the lack of checking for the type of the custom attribute object. I'll release a fix after a while, but I don't know exactly when it will be added to the next minor version of the collection.

Resolving patch:
diff --git a/plugins/modules/vmware_guest_custom_attributes.py b/plugins/modules/vmware_guest_custom_attributes.py
--- a/plugins/modules/vmware_guest_custom_attributes.py
+++ b/plugins/modules/vmware_guest_custom_attributes.py
@@ -247,7 +247,11 @@ def check_exists(self, vm, user_fields):
         """
         # Gather the available existing custom attributes based on user_fields
         existing_custom_attributes = []
-        for k, n in [(x.key, x.name) for x in self.custom_field_mgr for v in user_fields if x.name == v['name']]:
+        for k, n in [(x.key, x.name) for x in self.custom_field_mgr
+                     # vmware_guest_custome_attributes must work with self moref type of custom attributes or with global custom attributes
+                     if x.managedObjectType == vim.VirtualMachine or x.managedObjectType is None
+                     for v in user_fields
+                     if x.name == v['name']]:
             existing_custom_attributes.append({
                 "key": k,
                 "name": n


Test patch: