Skip to content

feat(snapshot): kind-based DataImport targetRef, snapshot CRUD commands, and full-tree aggregator import#391

Merged
kkozoriz merged 7 commits into
feat/d8-snapshot-new-endpointsfrom
feat/dataimport-kind-targetref
Jun 29, 2026
Merged

feat(snapshot): kind-based DataImport targetRef, snapshot CRUD commands, and full-tree aggregator import#391
kkozoriz merged 7 commits into
feat/d8-snapshot-new-endpointsfrom
feat/dataimport-kind-targetref

Conversation

@AleksZimin

Copy link
Copy Markdown
Member

Summary

This branch builds on feat/d8-snapshot-new-endpoints and bundles several related improvements to the data and snapshot CLI surfaces:

  • Switch DataExport/DataImport targetRef from a resource to a kind, and add a dual-mode (Mode A / Mode B) DataImport flow with an import marker and volume metadata persisted in the archive.
  • Add d8 snapshot list (cluster + local-archive modes).
  • Add d8 snapshot create and d8 snapshot delete.
  • Allow d8 snapshot import to import full snapshot trees, including domain aggregators (e.g. DemoVirtualMachineSnapshot).

What's included

data: kind-based targetRef + dual-mode DataImport

  • targetRef now identifies the target by kind instead of resource (group/kind/name), so leaves are matched by GroupKind without RESTMapper resolution.
  • DataImport gains a second mode (Mode B) alongside the existing one; the import marker (spec.source.import: {}) and captured volume metadata are persisted in the archive.
  • Docs/READMEs updated accordingly.

snapshot: list

  • d8 snapshot list lists top-level Snapshot objects in a namespace (with child counts) and supports a local-archive mode that walks a downloaded archive tree and prints each node's KIND/PATH.

snapshot: create / delete

  • d8 snapshot create creates a Snapshot object (built via unstructured to preserve all CRD fields).
  • d8 snapshot delete removes Snapshot objects, with explicit flag/argument validation.

snapshot: full-tree import including domain aggregators

  • d8 snapshot import previously rejected any archive containing a domain aggregator (a domain snapshot that references children but carries no own volume data) as "not client-drivable".
  • Aggregators are in fact reconstructed server-side by the genericbinder from the same inputs the CLI already uploads for structural nodes: the unified spec.source.import marker plus the node's manifests and child refs (no DataImport, since the aggregator has no own data) — the exact flow the e2e suite client-drives.
  • Preflight and importMarkerCR no longer reject aggregators, so a full archive imports as-is with the aggregator materialised as a non-root node.
  • The only remaining restriction: an aggregator (or a manifest-only domain node) cannot be selected as a standalone --node root (no parent SnapshotContent to attach to); import the full archive or select an ancestor Snapshot instead.

Behavior changes / compatibility

  • targetRef shape changes from resource to kind — any consumer reading/writing DataExport/DataImport targetRef must use kind.
  • d8 snapshot import now succeeds on archives that previously errored out due to a domain aggregator; the --node <aggregator> case still errors by design.

… archive + Mode B

Mode A (d8 snapshot import):
- EnsureDataImport now emits targetRef{group,kind,name} and echoes the leaf's
  storageClassName/size/volumeMode instead of the removed dataArtifactType; the
  controller infers the artifact and matches the leaf by GroupKind reverse-lookup.
- leafTargetRef returns the leaf kind directly (no RESTMapper resolution).
- Every import marker is the unified spec.source.import: {} (drop dataImportName,
  dataSource.name and sourceRef); isImportModeMarker keys solely off it.
- snapshot.yaml VolumeInfo carries storageClassName/size/volumeMode (from
  SnapshotContent.status.dataRef); PlannedNode reads it back for the DataImport spec.

Mode B (d8 data import): align the typed API with the unified CRD (KindPersistentVolumeClaim
constant, doc comments) and validate the PVC template carries metadata.name before create.

Signed-off-by: Aleksandr Zimin <alexandr.zimin@flant.com>
Align the d8 DataExport consumer with the storage-volume-data-manager CRD
that now keys targetRef on Kind instead of the resource plural:

- typed TargetRefSpec.Resource -> Kind (Group stays); the controller resolves
  the served version via its RESTMapper, so only group needs deriving.
- KindToGroupResource -> KindToGroup (drop the plural); CreateDataExport,
  CreateDataExporterIfNeeded and the recreate-on-expiry path now pass kind.
- getExportStatus allowlist checks targetRef.Kind against the Kind constants.
- cmd/create resolves group via KindToGroup and forwards the kind verbatim.
- snapshot path: aggapi.LeafDataExportTarget returns {group, kind} (no
  RESTMapping), exporter.EnsureDataExport/OpenExport take kind, pipeline wires
  it through.
- tests assert Kind instead of the resource plural.

Signed-off-by: Aleksandr Zimin <alexandr.zimin@flant.com>
- dataimport README: document that create drives standalone PVC import
  (targetRef.kind: PersistentVolumeClaim) and that the PVC template must carry
  metadata.name (rejected client-side otherwise).
- dataexport README: note targets are referenced by kind and list supported
  target kinds with their CLI aliases; fix stale snapshot/ alias example to vs/.
- CHEATSHEET_E2E: describe the unified spec.source.import: {} marker and the
  per-leaf DataImport with kind-based targetRef plus volume params in spec.

Signed-off-by: Aleksandr Zimin <alexandr.zimin@flant.com>
Add `d8 snapshot list` (alias `ls`) to list storage.deckhouse.io/v1alpha1
Snapshot resources in kubectl style:

- `-n/--namespace` for a single namespace, `-A/--all-namespaces` for all,
  otherwise the kubeconfig context namespace (`-A` and `-n` are mutually
  exclusive).
- `-o table|json|yaml` (default table); table columns NAME, READY,
  SNAPSHOTCONTENT, CHILDREN, AGE (plus NAMESPACE under `-A`); json/yaml emit
  the raw Snapshot objects.

Add `utilk8s.KubeconfigNamespace` to resolve the context namespace, factoring
the shared kubeconfig loading-rules logic out of `SetupK8sClientSet`.

Signed-off-by: Aleksandr Zimin <alexandr.zimin@flant.com>
Extend 'd8 snapshot list' with an optional positional [DIR] argument that
lists snapshot nodes from a downloaded archive on disk instead of querying
the cluster.

- Recursively walk DIR for snapshot.yaml nodes and print a table with
  columns NAME/KIND/NAMESPACE/CHILDREN/VOLUMES/AGE/PATH; -o json|yaml
  emit the same rows.
- Surface filesystem I/O errors (stat/ReadDir) instead of silently
  skipping nodes or under-reporting children; only ErrNotExist is benign.
- Keep Namespace raw in rows so cluster-scoped nodes omit it in
  json/yaml; the "-" placeholder is applied only when rendering the table.
- Reject -A/--all-namespaces and -n with a local DIR argument.

Signed-off-by: Aleksandr Zimin <alexandr.zimin@flant.com>
Add 'd8 snapshot create' to create a Snapshot object and 'd8 snapshot
delete' to remove Snapshot objects, and wire both into the snapshot
command group.

Signed-off-by: Aleksandr Zimin <alexandr.zimin@flant.com>
Domain aggregators (e.g. an intermediate DemoVirtualMachineSnapshot that
references child snapshots) were rejected by 'd8 snapshot import' as
"not client-drivable", which blocked importing any archive that contained
them. They are in fact reconstructed server-side by the genericbinder from
the same inputs the CLI already uploads for structural nodes: the unified
spec.source.import marker plus the node's manifests and child refs (no
DataImport, since the aggregator carries no own volume data). This is the
exact flow the e2e suite client-drives.

Stop rejecting aggregators in preflight and in importMarkerCR so a full
archive imports as-is, with the aggregator materialised as a non-root node.
The only remaining restriction is that an aggregator (or a manifest-only
domain node) cannot be selected as a standalone --node root, since it has
no parent SnapshotContent to attach to; import the full archive or select
an ancestor Snapshot instead.

Update the command help and unit tests accordingly, and add coverage for a
full aggregator-tree import.

Signed-off-by: Aleksandr Zimin <alexandr.zimin@flant.com>
@AleksZimin AleksZimin self-assigned this Jun 29, 2026
@AleksZimin AleksZimin requested a review from ldmonster as a code owner June 29, 2026 11:57
@kkozoriz kkozoriz self-requested a review June 29, 2026 13:58
@kkozoriz kkozoriz merged commit 37cf302 into feat/d8-snapshot-new-endpoints Jun 29, 2026
5 checks passed
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