If you still use VMware, as I have been, lately, you absolutely must download the govmomi-based “govc” client:

https://github.com/vmware/govmomi/tree/master/govc

First, there’s the ‘govc find’ command, which is like UNIX’s filesystem ‘find.

govc find -h:

The '-type' flag value can be a managed entity type or one of the following aliases:a    VirtualApp
c ClusterComputeResource
d Datacenter
f Folder
g DistributedVirtualPortgroup
h HostSystem
m VirtualMachine
n Network
o OpaqueNetwork
p ResourcePool
r ComputeResource
s Datastore
w DistributedVirtualSwitch

You can find templates in a folder:

govc find /Datacenter/vm/template_folder -type m 

Next, there’s ‘object.collect’, which displays “Managed Object Properties” for each VMWare object (VM, folder, etc.). Couple this with the ‘-json’ flag and jq for an amazing view of all of the VM’s properties:

govc object.collect -json /Datacenter/vm/template/template_folder/my_template 

Obviously, you can use JMESpath queries with jq:

govc object.collect -json /Datacenter/vm/template/template_folder/my_template tag | jq '.[].Annotation'

(A friendlier version of this is the ‘vm.info’ command.)

These commands can be put together to automate management of your VMware items:

#!/bin/bashTEMPLATE_FOLDER=${TEMPLATE_FOLDER:-/templates}
PRUNE_PATTERN=${PRUNE_PATTERN:-XXXXXXX}
KEEP=${KEEP:-3}
templates=($(govc find "${TEMPLATE_FOLDER}" -name "${PRUNE_PATTERN}*" -type m -disabledMethod PowerOnVM_Task | sort))limit=$[${#templates[@]} - $KEEP]for template in "${templates[@]:0:$limit}"; do
if [[ "$(govc vm.info -json "$template" | jq '.VirtualMachines[].Config.Annotation')" =~ keep ]]; then
echo "keeping $template since it has been held"
else
echo "pruning $template"
govc vm.destroy -vm.ipath="$template"
fidone

Do you hate the VMware web console as much as I do? Probably! Flash. Sheesh.

Let’s upload an ISO to a datastore:

export GOVC_DATASTORE=templates
govc datastore.upload rhel-server-7.6-x86_64-dvd.iso ISOs/rhel-server-7.6-x86_64-dvd.iso

Best thing is, it’s a Go binary so you can build it into a lightweight Docker image (Alpine, anyone?). Add jq and *boom*. Instant portable toolkit.