Skip to content

feat: manage VM tags (create, list, edit) - #256

Closed
wesleip wants to merge 3 commits into
virtfoundry:mainfrom
wesleip:feat/vm-tags
Closed

wesleip wants to merge 3 commits into
virtfoundry:mainfrom
wesleip:feat/vm-tags

Conversation

@wesleip

@wesleip wesleip commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

End-to-end support for user-defined VM tags.

  • Backend: add DeployVMInput.Tags and UpdateVMInput.Tags. UpdateVMInput.Tags is *[]string — nil means "leave unchanged", while a non-nil slice (including empty) replaces the tags, so removing all tags persists. Tags are stored in Instance.spec.tags through the store mapping, the legacy hypervisor deploy path forwards them, and MergePlatformVM no longer resurrects cleared tags.
  • UI: the VM list shows API tags; the edit form seeds the current tags (including those set at creation) and renders them as removable pills — Enter/comma to add, Backspace removes the last, × removes a pill. A reusable TagsInput component is shared by the edit form and the deploy wizard.
  • Fix: the deploy wizard could only ever accept a single tag. Its input derived the value from form.tags.join(', ') and split on comma, so the separator was stripped on every keystroke and Enter did nothing. It now uses TagsInput.
  • Fix: editing a VM that the store cannot resolve by Instance name (legacy / KubeVirt-only VM without an Instance CR) dereferenced a nil pointer and returned HTTP 500. UpdateVM now uses the GetVM fallback result with a nil guard, covered by a regression test.

Cross-repo

Tags are persisted in Instance.spec.tags, so the operator CRD must include the tags field (otherwise the API server prunes it). No typed Kubernetes API calls were added, so the RBAC contract is unchanged.

Test plan

  • go test ./...
  • cd ui && npm run build (also npm test — vitest, 32 passing)
  • Validated on a Kubernetes cluster: create with multiple tags, list, edit (add/remove), clear all tags
  • Wiki updated (if behavior or ops changed)

Add a Tags field to DeployVMInput and UpdateVMInput (nil means untouched,
a non-nil slice including an empty one replaces the tags), carry the tags
through DeployVM and UpdateVM, and persist them to Instance.spec.tags via
the store mapping. MergePlatformVM no longer resurrects cleared tags and
the legacy hypervisor deploy path forwards them too.
UpdateVM discarded the GetVM fallback result and re-queried the store,
which could return nil for legacy/KubeVirt-only VMs without an Instance
CR, panicking on the field access below. Use the GetVM result and add a
nil guard, with a regression test.
Show API tags in the VM list, seed the edit form with existing tags and
render them as removable pills (Enter/comma to add, Backspace to drop the
last). Extract a reusable TagsInput and reuse it in the deploy wizard,
fixing creation so more than one tag can be entered (the old input
stripped the comma on every keystroke). Add pt/en strings and a unit test
for mergeTags.

@Matheus-Thurler Matheus-Thurler left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tag UX and the UpdateVM nil-guard fix look good. Two things to address:

  1. Every save writes spec.tags, even when empty. InstanceToUnstructured always sets spec["tags"] = [] (see TestInstanceToUnstructuredWritesEmptyTags). On a cluster still running the old CRD, strict decoding rejects unknown field "spec.tags", which breaks create/update of every VM, not only tagged ones. Please write the field only when there are tags, or when clearing previously set tags, so this is safe to deploy before the CRD is applied.
  2. No validation of tags. Nothing limits count, length or charset in the handler or service. Suggest trimming plus a cap (for example 50 tags, 63 chars each) with an HTTP 400, matching the CRD limits requested in operator#74.

Deploy order: operator#74, CRD sync in helm-charts and apply, then this PR.

@wesleip

wesleip commented Oct 11, 2026

Copy link
Copy Markdown
Collaborator Author

Owner re-request: feedback from PR #256 addressed

Issue 1 - Write spec.tags only when tags exist

  • InstanceToUnstructured now only writes spec["tags"] when vm.Tags has at least one non-empty trimmed tag
  • Avoids strict CRD decode errors on older clusters
  • Updated TestInstanceToUnstructuredWritesEmptyTags test to expect field omitted when VM has nil/empty tags

Issue 2 - Tag validation

  • New validateTags() function with limits: max 50 tags (maxTags), max 63 chars each (maxTagLength)
  • Trims each tag, returns HTTP 400 error for invalid input
  • Called in both DeployVM and UpdateVM

Issue 3 - Deploy order

  • Note preserved: operator#74, CRD sync in helm-charts and apply, then this PR

All tests pass (go test ./...) and project builds (go build ./...).

Matheus-Thurler added a commit that referenced this pull request Oct 16, 2026
* feat(compute): support VM tags on create and update

Add a Tags field to DeployVMInput and UpdateVMInput (nil means untouched,
a non-nil slice including an empty one replaces the tags), carry the tags
through DeployVM and UpdateVM, and persist them to Instance.spec.tags via
the store mapping. MergePlatformVM no longer resurrects cleared tags and
the legacy hypervisor deploy path forwards them too.

* fix(compute): avoid nil deref when editing a VM missing from store

UpdateVM discarded the GetVM fallback result and re-queried the store,
which could return nil for legacy/KubeVirt-only VMs without an Instance
CR, panicking on the field access below. Use the GetVM result and add a
nil guard, with a regression test.

* feat(ui): manage VM tags in list, edit and creation

Show API tags in the VM list, seed the edit form with existing tags and
render them as removable pills (Enter/comma to add, Backspace to drop the
last). Extract a reusable TagsInput and reuse it in the deploy wizard,
fixing creation so more than one tag can be entered (the old input
stripped the comma on every keystroke). Add pt/en strings and a unit test
for mergeTags.

---------

Co-authored-by: Weslei Paulo Pereira <[email protected]>
@Matheus-Thurler

Copy link
Copy Markdown
Contributor

Superseded by #261 (rebased on the new UI).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants