When NetBox inventory moves from DCIM devices to virtualization VMs, tags need their own audit.

A tag can exist and still be wrong for the new object model. If a cluster tag is scoped only to DCIM devices or IP addresses, migrated virtualization VMs may not be taggable or discoverable through normal cluster filters.

Audit Cluster Tag Scopes

Set API variables:

NETBOX_URL="${NETBOX_URL:-https://netbox.example.com}"
TOKEN="${NETBOX_TOKEN:-}"

case "$TOKEN" in
  nbt_*) AUTH="Authorization: Bearer $TOKEN" ;;
  *)     AUTH="Authorization: Token $TOKEN" ;;
esac

List cluster-* tags missing virtualization VM scope:

curl -fsS -H "$AUTH" "$NETBOX_URL/api/extras/tags/?limit=1000" \
  | jq -r '.results[]
      | select(.slug | startswith("cluster-"))
      | [.slug, (.object_types | join(","))] | @tsv' \
  | awk -F '\t' '$2 !~ /virtualization\.virtualmachine/ {print}'

Expected output after cleanup:

<no output>

Why It Matters

Cluster tags are often used for:

  • filtering nodes in the NetBox UI.
  • scoping scripts to one cluster.
  • selecting inventory for CSV export.
  • validating migrated VM counts.
  • grouping Terraform import targets.

If the tag does not support virtualization.virtualmachine, those workflows silently become incomplete.

Repair Pattern

Use a script or API patch that preserves existing object types and appends the VM type.

Target state:

dcim.device
ipam.ipaddress
virtualization.virtualmachine

Do not replace the whole object type list unless the script first reads the current tag and merges existing values.

Verify Tagged VM Counts

After scope repair and tag sync, verify VM counts by cluster tag:

for slug in cluster-site-a-prod-rke2 cluster-site-a-uat-rke2; do
  printf '%s\t' "$slug"
  curl -fsS -H "$AUTH" \
    "$NETBOX_URL/api/virtualization/virtual-machines/?tag=$slug&limit=1" \
    | jq -r '.count'
done

Example output:

cluster-site-a-prod-rke2    18
cluster-site-a-uat-rke2     14

The exact counts are less important than matching the expected cluster inventory.

Final Check

Run both checks:

missing VM tag scope: none
tagged VM counts: match expected inventory

Only then treat tag migration as complete.