How to match exactly a tags name?

Hi, I am trying to create an inventory from vmware

This is my partial code on ansible playbook

- name: vm read on VMWARE
  hosts: localhost
  become: false
  gather_facts: true
  vars_files:
    - secrets.yml
    - vars.yml
  collections:
    - community.vmware
  tasks:
    - name: Gather all registered virtual machines
      vmware_vm_info:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        show_tag: true
        validate_certs: no
      delegate_to: localhost
      register: vm_info

    - name: Filter VMs with tag 'tagtoprocess'
      set_fact:
        filtered_vms: >-
          {{
            vm_info.virtual_machines
            | selectattr('tags', 'defined')
            | selectattr('tags', 'search', 'tagtoprocess')
            | list
          }}

This is the structure of my vm machines extractions:

    "ansible_facts": {
        "filtered_vms": [
            {
				.
				.
				.				
                "resource_pool": null,
                "tags": [
                    {
                        "category_id": "urn:vmomi:InventoryServiceCategory:dfjfjdfjd",
                        "category_name": "Ansible",
                        "description": "",
                        "id": "urn:vmomi:InventoryServiceTag:3ecce703-3dkfkkkfk:GLOBAL",
                        "name": "tagtoprocess-nosnmp"
                    },
                    {
                        "category_id": "urn:vmomi:InventoryServiceCategory:fc34d73f-4182-432f-b042-1e5f47fc4421:GLOBAL",
                        "category_name": "Backupp",
                        "description": "VmSecon",
                        "id": "urn:vmomi:InventoryServiceTag:6820fb9e-46b1-4eb9-8e6f-e6009ea61f3f:GLOBAL",
                        "name": "differenttag"
                    }
                ],
				.
				.
				.

As you can see, it matches with the tags tagtoprocess-nosnmp but I donā€™t like this.
How could I change my code matching exactly the machines with tags.name=tagtoprocess?

I think tags.name isnā€™t right

How could I solve?
Thanks a lot for your help

selectattr('tags', '==', 'tagtoprocess')
1 Like

Next to building your own inventory, have you consider using the existing dynamic inventory plugin community.vmware.vmware_vm_inventory?

You can use there also filter and apply tags to groups

plugin: community.vmware.vmware_vm_inventory
...
filters:
  - runtime.powerState == "poweredOn"
  - "tag_category.AD_ZONE is defined"
...
keyed_groups:
  - key: tag_category.AD_ZONE

https://docs.ansible.com/ansible/latest/collections/community/vmware/vmware_vm_inventory_inventory.html

1 Like

Thanks for your answer.

With this I obtain an empty list:

ok: [localhost] => {
    "ansible_facts": {
        "filtered_vms": []
    },
    "changed": false
}

so an empty list because the tag I am looking for is on the key = name with value ā€˜tagtoprocessā€™

About here community.vmware.vmware_vm_inventory inventory ā€“ VMware Guest inventory source ā€” Ansible Community Documentation

how to filter the machines where tags name=tagtoprocess

thanks a lot

Weā€™re about to deprecate this inventory plugin in favor of vmware.vmware.vms :shushing_face:

1 Like

Oh, didnā€™t use vmware for more than 4 years now :smiley:

how to filter the machines where tags name=tagtoprocess

You must turn on the gather_tags parameter. I have no access to a vmware host anymore, so I cannot try it myself.

1 Like

Oh, I didnā€™t know
Soā€¦how could I solve my issue with the supported plugin.

I would like to change this:

    - name: Filter VMs with tag 'tagtoprocess'
      set_fact:
        filtered_vms: >-
          {{
            vm_info.virtual_machines
            | selectattr('tags', 'defined')
            | selectattr('tags', 'search', 'tagtoprocess')
            | list
          }}

to match exactly the tag name tagtoprocess.
I didnā€™t find any examples for this.
:frowning:
Thanks a lot
Mario

Start with the very basic inventory vmware.vmware.vms inventory ā€“ Create an inventory containing VMware VMs ā€” Ansible Community Documentation

---
plugin: vmware.vmware.vms
hostname: 10.65.223.31
username: administrator@vsphere.local
password: Esxi@123$%
validate_certs: false
gather_tags: true

And do

ansible-inventory -i basic.vmware_vms.yml --list

Once this works and you see your vmware hosts, try e.g. to group your vms by tags

---
plugin: vmware.vmware.vms
hostname: 10.65.223.31
username: administrator@vsphere.local
password: Esxi@123$%
validate_certs: false
gather_tags: true
keyed_groups:
  - key: tags_by_category.tagtoprocess
    separator: ""

tags_by_category.tagtoprocess depends on the structure that is returned by ansible-inventory with the --list option.
So itā€™s bit blind boiler templating here ā€¦

In general, hosts with the related tag should be grouped in the tagtoprocess group.
--graph should nicely display that.

ansible-inventory -i basic.vmware_vms.yml --graph

Once that works, your playbook can look like that

---
- hosts: tagtoprocess

  tasks:
    ....

with ansible-playbook -i basic.vmware_vms.yml your_play.yml

Another option is, to target hosts: all and use --limit tagstoprocess in your ansible-playbook account.


Our proxmox dynamic inventory looks like the

---
plugin: community.general.proxmox
url: .......
validate_certs: false
user: "{{ lookup('onepassword', 'proxmox', vault='Employee', field='username') }}"
token_id: "{{ lookup('onepassword', 'proxmox', vault='Employee', field='token_id') }}"
token_secret: "{{ lookup('onepassword', 'proxmox', vault='Employee', field='password') }}"
want_facts: true
keyed_groups:
  - key: proxmox_tags_parsed
    separator: ""
# use IP address to connect, when DNS is not set yet
want_proxmox_nodes_ansible_host: false
compose:
  ansible_host: proxmox_agent_interfaces[1]["ip-addresses"][0] | ansible.utils.ipaddr('address')

So our proxmox tags results here also in ansible groups

While our aws dynamic inventory looks like that

---
plugin: aws_ec2
cache: true
groups:
  linux: true
regions:
  - eu-central-1
hostnames:
  - tag:Name
filters:
  instance-state-name:
    - running
  tag:ansible_group:
    - ubuntu
    - oraclelinux
    - opnsense
keyed_groups:
  - key: tags['ansible_group']
    separator: ''
  - key: tags['infra_system']
    separator: ''
  - key: placement.availability_zone
    separator: ''
exclude_filters:
  - key-name:
    - 'windowsserver'
compose:
  ansible_ssh_extra_args: '-o StrictHostKeyChecking=accept-new'

Our self managed dns servers got the tags infra_system: dns.
And we can address them with ansible-playbook -i hosts.aws_ec2.yml some_play.yml --limit dns

1 Like

Sorryā€¦but I have some troubles to understand

Forst script with basic.vmware_vms.yml

---
plugin: vmware.vmware.vms
hostname: 10.65.223.31
username: administrator@vsphere.local
password: Esxi@123$%
validate_certs: false
gather_tags: true

worked and produce a big list.

This is the structure, and I put an example of one of the vms listed:

{
    "_meta": {
        "hostvars": {
            "namehost1": {
                "ansible_host": "172.17.1.12",
                "config": {
                    "cpuHotAddEnabled": true,
                    "cpuHotRemoveEnabled": false,
                    "guestId": "windows9Server64Guest",
                    "hardware": {
                        "numCPU": 2
                    },
                    "instanceUuid": "501xhshsdh-b1cc-6bf9-5c85-f16ddefd74b",
                    "name": "namehost1",
                    "template": false,
                    "uuid": "421c2f5e-0a4d-4d0c-ab65-403727ad0849"
                },
                "customValue": {
                    "Backup Status": "Backup Job ID [422928]  Client: [vcentername.mydomain.loc], Backup Set: [defaultBackupSet], Subclient: [VMMain_MA] Parent >
                    "Last Backup": "11/02/2025 21:48:26"
                },
                "guest": {
                    "guestId": "windows2019srvNext_64Guest",
                    "guestState": "running",
                    "hostName": "namehost1.mydomain.loc",
                    "ipAddress": "172.16.1.152"
                },
                "name": "namehost1",
                "path": "/MycityVX/vm/PABX",
                "runtime": {
                    "maxMemoryUsage": 8192
                },
                "summary": {
                    "runtime": {
                        "powerState": "poweredOn"
                    }
                },
                "tags": {
                    "urn:vmomi:InventoryServiceTag:04ec94c1-ff30-42b8-855d-10ce5a065303:GLOBAL": "othertagpippo",
                    "urn:vmomi:InventoryServiceTag:92b445a9-a413-416d-9cc2-c3b0ad3e1bf8:GLOBAL": "tagtoprocess"
                },
                "tags_by_category": {
                    "Ansible": [
                        {
                            "urn:vmomi:InventoryServiceTag:92b445a9-a413-416d-9cc2-c3b0ad3e1bf8:GLOBAL": "tagtoprocess"
                        }
                    ],
                    "OtherCategory": [
                        {
                            "urn:vmomi:InventoryServiceTag:04ec94c1-ff30-42b8-855d-10ce5a065303:GLOBAL": "othertagpippo"
                        }
                    ]
                }
            },
             "namehost2": {
                       "ansible_host": ...
.
.

so, how could I group for tag tagtoprocess, and filter only for the hosts containing that tag as the example you gave me?
I stucked on the next step you suggested meā€¦

Thanks a lot
Mario

Iā€™m not sure if I understand the returned tag structure correctly. But when the Key of the tag is Ansible and its value is tagtoprocess, than

---
plugin: vmware.vmware.vms
hostname: 10.65.223.31
username: administrator@vsphere.local
password: Esxi@123$%
validate_certs: false
gather_tags: true
keyed_groups:
  - key: tags_by_category.Ansible
    separator: ""

might work.
And case-sensitive might also be matter.

1 Like

Super, it helps a lot, I am at a step further.

I obtain:

{
    "__urn_vmomi_InventoryServiceTag_3ecce703_3dc7_44b1_91fe_e66593973000_GLOBAL____tagtoprocess__": {
        "hosts": [
            "namehost1"
        ]
    },
    "__urn_vmomi_InventoryServiceTag_92b445a9_a413_416d_9cc2_c3b0ad3e1bf8_GLOBAL____anothertagtodontprocess__": {
        "hosts": [
            "namehost2"
        ]
    },
    "_meta": {
        "hostvars": {

So, if I want to obtain only the host namehost1 because it has the tag ā€œtagtoprocessā€ is there a way?
Because I donā€™t want namehost2 in the list because it has the tag ā€œanothertagtodontprocessā€ in the same tags_by_category.Ansible

thanks thanks

This is totally okey when it lists all available hosts.

give ansible-inventory with --graph a shot.

It should display something like that

  |--@tagtoprocess:
  |  |--namehost1
  |--@anothertagtodontprocess_:
  |  |--namehost2

In your playbook you address just the group

---
- hosts: tagtoprocess

....

with ansible-playbook -i yours..vmware_vms.yml yourplay.ym

You should also try to add prefix: "" to the keyed_groups: dict to cleanup the tag value.

---
plugin: vmware.vmware.vms
hostname: 10.65.223.31
username: administrator@vsphere.local
password: Esxi@123$%
validate_certs: false
gather_tags: true
keyed_groups:
  - key: tags_by_category.tagtoprocess
    separator: ""
    prefix: ""
1 Like

I think you meant tags_by_category.Ansible here:

---
plugin: vmware.vmware.vms
hostname: 10.65.223.31
username: administrator@vsphere.local
password: Esxi@123$%
validate_certs: false
gather_tags: true
keyed_groups:
  - key: tags_by_category.Ansible
    separator: ""
    prefix: ""

With the --graph I obtain:


  | 
  |--@__urn_vmomi_InventoryServiceTag_3ecce703_3dc7_44b1_91fe_e66593973000_GLOBAL____tagtoprocess__:
  |  |--namehost1
  |--@__urn_vmomi_InventoryServiceTag_92b445a9_a413_416d_9cc2_c3b0ad3e1bf8_GLOBAL____anothertagtodontprocess__:
  |  |--namehost2

so it doesnā€™t produce a clean inventory only with tagtoprocess namehost1 I suppose

try to add some filters to key:

---
plugin: vmware.vmware.vms
hostname: 10.65.223.31
username: administrator@vsphere.local
password: Esxi@123$%
validate_certs: false
gather_tags: true
keyed_groups:
  - key: tags_by_category.Ansible | regex_search("___(.*)__") | replace("_","")
    separator: ""
    prefix: ""

it might be worth it to open an issue in GitHub - ansible-collections/vmware.vmware: Ansible VMWare Collection and ask how to get clean tags ā€¦

1 Like

For future readers, they did open an issue here How to create an inventory grouped by tag name? Ā· Issue #117 Ā· ansible-collections/vmware.vmware Ā· GitHub
And i believe I answered their question but still waiting to hear back

1 Like