aggapi

package
v0.33.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package aggapi is a thin client for the state-snapshotter aggregated subresource API exposed through the kube-apiserver aggregation layer.

After C9 there is no whole-subtree server-side aggregation: each snapshot node exposes three per-CR subresources, addressed by the node's resource plural:

  • manifests-download: the node's own captured manifests (status preserved, namespace made relative). Served by the node's OWN subresource group (core group for the core Snapshot, the domain-prefixed group for domain snapshot CRs — the domain apiserver proxies to the core content layer); CSI VolumeSnapshot leaves use the dedicated VS-connector group instead.
  • manifests-with-data-restoration: a ready-to-apply manifest array for the node's whole subtree (the server delegates domain subtrees internally). Served by the node's OWN subresource group (core group for the core Snapshot, the domain-prefixed group for domain snapshot CRs).
  • manifests-and-children-refs-upload: import one node's manifests plus its direct child refs. Served by the node's OWN subresource group (core group for the core Snapshot, the domain-prefixed group for domain snapshot CRs — the domain apiserver's upload facade records the node's own childrenSnapshotRefs and forwards the manifests to the core content layer); CSI VolumeSnapshot leaves use the dedicated VS-connector group instead. The upload is bind-first: it returns 409 ImportContentNotBound until the node's SnapshotContent is bound.

All three subresources now route the same way — by the node's own group — so there is no longer any download/upload group asymmetry. Every subresource is addressed by the node's own namespaced CR (Snapshot, domain snapshot CR, or CSI VolumeSnapshot leaf). The client never reads cluster-scoped SnapshotContent objects.

Index

Constants

View Source
const (
	// CoreSubresourcesGroup is the core controller's aggregated subresources API group.
	// It serves manifests-download for every node kind and the core Snapshot's
	// restore/upload subresources.
	CoreSubresourcesGroup = "subresources.state-snapshotter.deckhouse.io"
	// CoreSubresourcesVersion is the version served under CoreSubresourcesGroup.
	CoreSubresourcesVersion = "v1alpha1"

	// DomainSubresourcesGroupPrefix is prepended to a domain snapshot's API group to
	// address its aggregated subresources group (e.g. "sds-unified-snapshots-poc.deckhouse.io"
	// -> "subresources.sds-unified-snapshots-poc.deckhouse.io").
	DomainSubresourcesGroupPrefix = "subresources."

	// VSConnectorGroup is the generic-PVC extended VolumeSnapshot connector subresource group.
	VSConnectorGroup = "subresources.snapshot.storage.k8s.io"
	// VSConnectorVersion is the version served under VSConnectorGroup.
	VSConnectorVersion = "v1"

	// StorageGroup is the API group of the core Snapshot / SnapshotContent CRDs.
	StorageGroup = "state-snapshotter.deckhouse.io"
	// VolumeSnapshotGroup is the CSI external-snapshotter API group of VolumeSnapshot leaves.
	VolumeSnapshotGroup = "snapshot.storage.k8s.io"
	// VolumeSnapshotResource is the resource plural of CSI VolumeSnapshot objects.
	VolumeSnapshotResource = "volumesnapshots"
	// VolumeSnapshotKind is the kind of CSI VolumeSnapshot leaf nodes.
	VolumeSnapshotKind = "VolumeSnapshot"
)

Aggregated subresource API groups and versions.

View Source
const (
	// SubManifestsDownload reads one node's own captured manifests.
	SubManifestsDownload = "manifests-download"
	// SubManifestsRestore reads a ready-to-apply manifest array for a node's subtree.
	SubManifestsRestore = "manifests-with-data-restoration"
	// SubManifestsUpload imports one node's manifests plus its direct child refs.
	SubManifestsUpload = "manifests-and-children-refs-upload"
)

Subresource names.

View Source
const (
	// DefaultMaxResponseBytes caps one aggregated-API response at 64 MiB. Manifest
	// bundles may be large, but must not grow client memory without a finite bound.
	DefaultMaxResponseBytes int64 = 64 << 20
)
View Source
const ReasonImportContentNotBound = "ImportContentNotBound"

ReasonImportContentNotBound is the canonical status.reason of the bind-first 409 the namespaced (core / domain / VS-connector) manifests-and-children-refs-upload returns while a node's status.boundSnapshotContentName is still empty. It mirrors state-snapshotter usecase.ReasonImportContentNotBound verbatim — the wire contract d8 retries on until the binder binds the node's SnapshotContent.

Variables

View Source
var ErrResponseTooLarge = errors.New("aggregated API response exceeds byte limit")

ErrResponseTooLarge reports that an aggregated-API response exceeded its byte budget.

View Source
var ErrRestoreBadRequest = errors.New("restore request rejected as invalid")

ErrRestoreBadRequest is returned by RestoreManifestsScoped when the server rejects the request as invalid (state-snapshotter restore.ErrBadRequest wire equivalent: an unknown scope value, an object filter missing kind or name, or an object filter used with a scope other than RestoreScopeNode). Distinguish it from other failures with errors.Is.

View Source
var ErrRestoreNotFound = errors.New("restore target not found")

ErrRestoreNotFound is returned by RestoreManifestsScoped when the addressed node, or — with an object filter — the requested object within it, does not exist. Distinguish it from other failures with errors.Is.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client performs aggregated-apiserver calls over an absolute-path REST interface (typically a discovery REST client) and resolves a node's GVK to its resource plural via a RESTMapper.

func NewClient

func NewClient(restClient rest.Interface, mapper meta.RESTMapper) *Client

NewClient builds a Client from a raw REST interface (e.g. the discovery REST client) and a RESTMapper used to resolve GVK -> resource plural.

func NewClientForConfig

func NewClientForConfig(cfg *rest.Config, mapper meta.RESTMapper) (*Client, error)

NewClientForConfig builds a Client from a rest.Config, constructing the discovery REST client internally. mapper resolves GVK -> resource plural.

func (*Client) LeafDataExportTarget

func (c *Client) LeafDataExportTarget(ref NodeRef) (string, string, string, error)

LeafDataExportTarget resolves the DataExport targetRef {group, resource, kind} for a snapshot leaf node. CSI VolumeSnapshot leaves use the fixed constants VolumeSnapshotGroup / VolumeSnapshotResource / VolumeSnapshotKind; all other kinds derive group from the leaf's apiVersion, use its own kind directly, and resolve the resource plural via the RESTMapper.

This is used to build a DataExport that the storage-volume-data-manager controller can route through its kind-agnostic snapshot export path (categorySnapshot): group/kind must identify a namespaced snapshot CR so the controller can read its status.boundSnapshotContentName → SnapshotContent → status.dataRef.

TEMP REVERTME: resource (plural) is populated in addition to kind so the DataExport satisfies the deployed storage-volume-data-manager (mr135) GVR-based CRD, which requires spec.targetRef.resource. The kind-based contract is not yet in SVDM main. Sending both resource and kind is safe because each CRD prunes the field it doesn't know.

func (*Client) NodeManifestsDownload

func (c *Client) NodeManifestsDownload(ctx context.Context, ref NodeRef) ([]byte, error)

NodeManifestsDownload performs GET <node>/manifests-download and returns the raw JSON array body (the node's own captured manifests).

The call is retried with bounded exponential backoff on a transient aggregated-API error (see isTransientManifestsDownloadError) — observed in practice as the aggregated APIService backend briefly restarting/overloading and returning "the server is currently unable to handle the request" (HTTP 503).

func (*Client) RestoreManifests

func (c *Client) RestoreManifests(ctx context.Context, ref NodeRef, targetNamespace string) ([]byte, error)

RestoreManifests performs GET <node>/manifests-with-data-restoration?targetNamespace=<ns> and returns the raw apply-ready JSON array body for the node's whole subtree.

It is a thin wrapper over RestoreManifestsScoped with a zero-value RestoreScopeOptions; callers that need scope=node or an object filter call RestoreManifestsScoped directly.

func (*Client) RestoreManifestsScoped

func (c *Client) RestoreManifestsScoped(ctx context.Context, ref NodeRef, targetNamespace string, opts RestoreScopeOptions) ([]byte, error)

RestoreManifestsScoped performs GET <node>/manifests-with-data-restoration with targetNamespace and, when set, the server's scope/kind/name/apiVersion query params (restore_handler.go parseRestoreQueryOptions). Each of opts.Scope/FilterKind/FilterName/FilterAPIVersion is sent ONLY when non-empty — an empty Scope omits the scope param entirely rather than sending scope=subtree explicitly, reproducing the server's own default byte-for-byte.

func (*Client) UploadManifests

func (c *Client) UploadManifests(ctx context.Context, ref NodeRef, body []byte) ([]byte, error)

UploadManifests performs POST <node>/manifests-and-children-refs-upload with the given JSON body ({"manifests": <array>, "childRefs": [...]}) and returns the raw body.

The upload is bind-first: the aggregated apiserver refuses it with 409 ImportContentNotBound until the addressed node's status.boundSnapshotContentName is set. The import orchestrator (see snapimport.Run) already gates the whole upload pass behind a collective wait-for-bind, so this per-request retry is only a safety net for the narrow read-after-write race where the CLI observed a node bound but this upload endpoint has not yet — see postManifestsUpload.

type NodeRef

type NodeRef struct {
	APIVersion string
	Kind       string
	Name       string
	Namespace  string
}

NodeRef uniquely identifies a snapshot node for aggregated subresource calls. It is intentionally string-based (no typed objects) so that domain-specific kinds can be addressed without registering their Go types.

func (NodeRef) IsVolumeSnapshotLeaf

func (r NodeRef) IsVolumeSnapshotLeaf() bool

IsVolumeSnapshotLeaf reports whether the ref addresses a CSI VolumeSnapshot leaf, which is served by the VS-connector subresource group instead of the core group.

type RestoreScope

type RestoreScope string

RestoreScope selects the compilation depth of a RestoreManifestsScoped call, mirroring state-snapshotter's usecase/restore.Scope wire values verbatim (restore_handler.go parseRestoreQueryOptions) — these literals go on the wire as the "scope" query param, so they must match the server exactly, not just read similarly.

const (
	// RestoreScopeSubtree compiles the addressed node and its whole subtree, recursively. It is
	// the server's default when the scope query param is omitted entirely.
	RestoreScopeSubtree RestoreScope = "subtree"
	// RestoreScopeNode compiles ONLY the addressed node, with no descendants. Required before an
	// object filter (FilterKind/FilterName/FilterAPIVersion) is accepted.
	RestoreScopeNode RestoreScope = "node"
)

type RestoreScopeOptions

type RestoreScopeOptions struct {
	Scope            RestoreScope
	FilterKind       string
	FilterName       string
	FilterAPIVersion string
}

RestoreScopeOptions narrows a RestoreManifestsScoped call to one node (Scope == RestoreScopeNode) and, optionally, a single captured object within that node (FilterKind + FilterName, with FilterAPIVersion further disambiguating). The server accepts the object filter ONLY together with Scope == RestoreScopeNode and rejects any other combination with a 400 (restore_handler.go parseRestoreQueryOptions) — RestoreManifestsScoped does not pre-validate this client-side, it lets the server enforce its own contract and surfaces the resulting ErrRestoreBadRequest. A zero-value RestoreScopeOptions reproduces today's default (full subtree, no filter) byte-for-byte: no scope/kind/name/apiVersion query params are sent at all.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL