Skip to content

Support glob patterns for targetDisk deviceName and model hints #29

Description

@tjjh89017

Today

Every TargetDiskHints field is an exact comparison (internal/diskmatch/diskmatch.go's hintsMatch):

  • deviceName, serialNumber, wwn, pciePath, hctl compare byte-for-byte.
  • model and vendor compare after trimming whitespace.
  • minSizeGigabytes, maxSizeGigabytes, rotational, slotNumber compare numerically.

Set fields are ANDed; unset fields do not constrain. Match then requires exactly one disk to satisfy the hints - zero and 2+ are both errors.

The only non-exact selection available today is a size range plus rotational, e.g. "the one SSD of 200 GiB or more".

The gap

Two hints are naturally patterned, and both are awkward to write exactly:

  • deviceName. A fleet where the target is "the first NVMe namespace" needs /dev/nvme0n1 spelled out per machine, even though /dev/nvme*n1 is the real intent. Writing a hint per machine is exactly what the field is meant to avoid.
  • model. Firmware model strings carry revision suffixes and padding that vary within one purchase batch (SAMSUNG MZQL2960HCJR-00A07 vs -00B07), so a hint that is right for one machine misses its neighbour.

Proposal

Add glob support for those two hints, as new, separate fields rather than changing what the existing ones mean:

targetDisk:
  deviceNamePattern: "/dev/nvme*n1"
  modelPattern: "SAMSUNG MZQL2960HCJR-*"
  • Matching uses Go's path.Match semantics (*, ?, [...]), case-sensitive, consistent with the exact fields.
  • A pattern field ANDs with every other set hint, the same as any exact field.
  • modelPattern trims whitespace on the disk side before matching, matching model's existing behaviour.
  • The "exactly one disk" rule does not change. A pattern that matches several disks is the same error an over-broad exact hint already produces, with the same "refine them" message listing the matching devices. A glob is a way to write one hint for a fleet, not a way to select a set.
  • Setting both deviceName and deviceNamePattern (or model and modelPattern) is rejected by the webhook rather than silently ANDed - two spellings of one constraint in one object is a configuration mistake.

Why glob, not regex

The pattern comes from a user-writable CR and is evaluated in the controller on every resolve. path.Match has no catastrophic-backtracking class of input, so it needs no complexity or length budget of its own. Regex would need one, and would buy expressiveness nothing in the cases above wants. If a real case later needs alternation or anchoring that glob cannot express, that is the point to revisit it - not before.

Scope

  • api/v1alpha1/machine_types.go: two fields on TargetDiskHints, plus hasAnyHint.
  • internal/diskmatch/diskmatch.go: the two hintsMatch arms, and unit tests for match, no-match, ambiguous-match, and a malformed pattern.
  • internal/webhook/v1alpha1/machine_webhook.go: reject a malformed pattern (path.Match returns ErrBadPattern) and reject the exact/pattern pair at admission, so a bad pattern fails at apply time rather than mid-deploy.
  • CRD regeneration, and the hint documentation.
  • Machine.spec.targetDisk and every dataImages[].targetDisk share TargetDiskHints, so both get this at once.

Out of scope

serialNumber, wwn, pciePath, hctl, and vendor stay exact. A serial or WWN identifies one physical device, so a pattern over it has no meaning worth supporting; pciePath and hctl are structured addresses where a size or slot hint expresses the same intent more clearly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions