kubernetes

package
v0.0.0-...-b13fc33 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	ElasticClusterConditionReady            = "Ready"
	ElasticClusterConditionStorageReady     = "StorageReady"
	ElasticClusterConditionCephClusterReady = "CephClusterReady"
	ElasticClusterConditionCredentialsReady = "CredentialsReady"
	ElasticClusterConditionCsiCephReady     = "CsiCephReady"
)

Well-known ElasticCluster status condition types. Mirrored from sds-elastic/api/v1alpha1 (ECCondition*) and kept here as plain strings so storage-e2e does not take a build dependency on the sds-elastic module. Keep in sync with the api package.

View Source
const (
	ElasticClusterReasonStorageClassesExist = "StorageClassesExist"
	ElasticClusterReasonVolumesExist        = "VolumesExist"
	ElasticClusterReasonTerminating         = "Terminating"
)

Well-known ElasticCluster teardown reasons set on the aggregate Ready condition while the CR is being deleted. Domain-level on purpose (they never name the underlying Rook/csi-ceph resources). Mirrored from sds-elastic/api/v1alpha1 (ECReason*).

View Source
const (
	// ElasticRookGroup is the renamed Rook API group used by sds-elastic.
	ElasticRookGroup = "internal.sdselastic.deckhouse.io"
	// ElasticRookVersion is the renamed Rook API version.
	ElasticRookVersion = "v1"
	// UpstreamRookGroup is the upstream Rook API group that MUST NOT appear
	// on a cluster running sds-elastic.
	UpstreamRookGroup = "ceph.rook.io"
)

The sds-elastic module ships a vendored Rook operator whose API group is renamed from the upstream ceph.rook.io to internal.sdselastic.deckhouse.io (see sds-elastic images/operator/patches). The verifiers below address the renamed group so the e2e suite can assert that the Rook resources the sds-elastic controller created are healthy AND that no upstream ceph.rook.io objects leaked onto the cluster (handled at the suite level via discovery).

View Source
const (
	ElasticStorageClassTypeRBD    = "RBD"
	ElasticStorageClassTypeCephFS = "CephFS"

	ElasticReplicationAvailabilityWithoutConsistency = "AvailabilityWithoutConsistency"
	ElasticReplicationConsistencyAndAvailability     = "ConsistencyAndAvailability"
	ElasticReplicationHighRedundancy                 = "HighRedundancy"
	ElasticReplicationErasureCodedCompact            = "ErasureCodedCompact"
)

ElasticStorageClass spec enums (mirrored from sds-elastic/api/v1alpha1 so storage-e2e stays free of a build dependency on the module). Keep in sync.

View Source
const (
	ElasticStorageClassConditionReady                = "Ready"
	ElasticStorageClassConditionPoolReady            = "PoolReady"
	ElasticStorageClassConditionCsiStorageClassReady = "CsiStorageClassReady"
)

Well-known ElasticStorageClass status condition types (mirror of ESCCondition* in the api package).

View Source
const (
	ElasticStorageClassReasonBoundVolumesExist  = "BoundVolumesExist"
	ElasticStorageClassReasonDataPresentInPool  = "DataPresentInPool"
	ElasticStorageClassReasonFilesystemNotEmpty = "FilesystemNotEmpty"
	ElasticStorageClassReasonTerminating        = "Terminating"
)

Well-known ElasticStorageClass teardown reasons set on the aggregate Ready condition while the CR is being deleted (mirror of ESCReason* in the api package).

View Source
const CephFilesystemGoneTimeout = 5 * time.Minute

CephFilesystemGoneTimeout is the default budget for WaitForCephFilesystemGone. MDS shutdown + pool removal usually settles in 1-2 minutes; we allow more to absorb operator restarts and slow Ceph mons.

View Source
const DefaultDistrolessSessionTTL = 30 * time.Minute

DefaultDistrolessSessionTTL is the lifetime of the `sleep` process inside the injected ephemeral container when used as a long-lived reader session (OpenDistrolessReader / DistrolessReader.ReadFile). 30 minutes comfortably outlasts any single test cell while still guaranteeing eventual self-cleanup if the caller crashes.

View Source
const DefaultEphemeralStartupTimeout = 60 * time.Second

DefaultEphemeralStartupTimeout caps the wait for the injected ephemeral container to transition into Running. Image pull from a warm registry usually takes a couple of seconds; 60 s is a generous upper bound that still surfaces ImagePullBackOff/ErrImagePull early.

View Source
const DefaultRookNamespace = "d8-sds-elastic"

DefaultRookNamespace is the namespace the sds-elastic module deploys its vendored Rook operator (and the rook-config-override ConfigMap) into. It is the default scope for the Rook-daemon helpers that survive the removal of the raw-Rook cluster builders.

View Source
const ElasticClusterGoneTimeout = 15 * time.Minute

ElasticClusterGoneTimeout is the default budget for WaitForElasticClusterGone. The controller tears down the whole Rook CephCluster (mon/mgr/osd drain, CRUSH map removal) before releasing the finalizer — easily 10+ minutes.

View Source
const ElasticStorageClassForceDeleteAnnotation = "sds-elastic.deckhouse.io/force-deletion"

ElasticStorageClassForceDeleteAnnotation, set to "true" on an ElasticStorageClass, authorizes the destructive purge of a non-empty RBD pool (the controller propagates it to the underlying CephBlockPool as the Rook force-deletion annotation). It NEVER bypasses the bound-PV guard. Mirror of v1alpha1 ESCForceDeleteAnnotation.

View Source
const ElasticStorageClassGoneTimeout = 10 * time.Minute

ElasticStorageClassGoneTimeout is the default budget for WaitForElasticStorageClassGone. Pool/filesystem teardown plus the csi-ceph SC removal take a few minutes; a force-deletion purge of a populated pool can take longer.

View Source
const PollGetTimeout = 30 * time.Second

PollGetTimeout caps a single Get call inside readiness pollers. Without this cap a hung TCP connect (e.g. SSH tunnel that died after a Wi-Fi flap on the developer's laptop) eats the entire parent timeout silently — the poller appears to "hang" until the per-resource ReadyTimeout fires 15-20 minutes later. With a 30s cap each Get fails fast, so we surface the network problem early via the WARN log emitted by pollResourceUntilReady.

View Source
const PollGoneProgressEvery = 30 * time.Second

PollGoneProgressEvery controls how often pollResourceUntilGone emits a progress INFO line while the resource is still alive. We don't want a log per tick (chatty) but we also don't want long stretches of silence when a finalizer is stuck for minutes — every ~30s strikes a balance.

View Source
const PollTickInterval = 5 * time.Second

PollTickInterval is the default tick interval between Get attempts when waiting for a Kubernetes resource to reach a ready state.

View Source
const RookConfigOverrideName = "rook-config-override"

RookConfigOverrideName is the well-known ConfigMap name Rook reads Ceph config overrides from (see Rook docs: "Advanced Configuration – Custom ceph.conf Settings"). Rook watches this ConfigMap in its operator namespace and injects the `config` key into `/etc/ceph/ceph.conf` of every Ceph daemon.

Variables

View Source
var (
	// ElasticRookCephClusterGVR is the renamed-group CephCluster GVR.
	ElasticRookCephClusterGVR = schema.GroupVersionResource{
		Group:    ElasticRookGroup,
		Version:  ElasticRookVersion,
		Resource: "cephclusters",
	}
	// ElasticRookCephBlockPoolGVR is the renamed-group CephBlockPool GVR.
	ElasticRookCephBlockPoolGVR = schema.GroupVersionResource{
		Group:    ElasticRookGroup,
		Version:  ElasticRookVersion,
		Resource: "cephblockpools",
	}
	// ElasticRookCephFilesystemGVR is the renamed-group CephFilesystem GVR.
	ElasticRookCephFilesystemGVR = schema.GroupVersionResource{
		Group:    ElasticRookGroup,
		Version:  ElasticRookVersion,
		Resource: "cephfilesystems",
	}
)
View Source
var BlockDeviceGVR = schema.GroupVersionResource{
	Group:    "storage.deckhouse.io",
	Version:  "v1alpha1",
	Resource: "blockdevices",
}

BlockDeviceGVR is the GroupVersionResource of the sds-node-configurator BlockDevice CR (cluster-scoped). Used to label individual BlockDevices so a selector (e.g. ElasticCluster.spec.storage.blockDeviceSelector) can adopt them for OSDs.

View Source
var CephFilesystemGVR = schema.GroupVersionResource{
	Group:    "ceph.rook.io",
	Version:  "v1",
	Resource: "cephfilesystems",
}

CephFilesystemGVR is the GroupVersionResource of Rook's CephFilesystem.

View Source
var ElasticClusterGVR = schema.GroupVersionResource{
	Group:    "storage.deckhouse.io",
	Version:  "v1alpha1",
	Resource: "elasticclusters",
}

ElasticClusterGVR is the GroupVersionResource of the sds-elastic ElasticCluster CR. It is cluster-scoped (no namespace), so all dynamic calls below omit .Namespace(). The CR is the high-level entry point of the sds-elastic module: the controller turns it into a Rook CephCluster (renamed group internal.sdselastic.deckhouse.io) backed by LVM-local OSDs.

View Source
var ElasticStorageClassGVR = schema.GroupVersionResource{
	Group:    "storage.deckhouse.io",
	Version:  "v1alpha1",
	Resource: "elasticstorageclasses",
}

ElasticStorageClassGVR is the GroupVersionResource of the sds-elastic ElasticStorageClass CR (cluster-scoped). The controller maps it to a Ceph pool/filesystem plus a 1:1-named csi-ceph CephStorageClass and a core storage.k8s.io/v1 StorageClass of the same name.

View Source
var LocalStorageClassGVR = schema.GroupVersionResource{
	Group:    "storage.deckhouse.io",
	Version:  "v1alpha1",
	Resource: "localstorageclasses",
}
View Source
var VolumeSnapshotClassGVR = schema.GroupVersionResource{
	Group:    "snapshot.storage.k8s.io",
	Version:  "v1",
	Resource: "volumesnapshotclasses",
}

Functions

func AnnotateElasticStorageClassForceDeletion

func AnnotateElasticStorageClassForceDeletion(ctx context.Context, kubeconfig *rest.Config, name string) error

AnnotateElasticStorageClassForceDeletion sets the force-deletion annotation on the named ESC, authorizing the destructive purge of a non-empty RBD pool. It never bypasses the bound-PV guard. Idempotent; retries on optimistic-concurrency conflicts.

func CephFSDataPoolFullName

func CephFSDataPoolFullName(fsName, dataPoolName string) string

CephFSDataPoolFullName returns the full Ceph pool name that ends up referenced from CephStorageClass.spec.cephFS.pool. Rook composes the per-filesystem pool name as "<filesystem>-<dataPool.name>".

func CreateCephFilesystem

func CreateCephFilesystem(ctx context.Context, kubeconfig *rest.Config, cfg CephFilesystemConfig) error

CreateCephFilesystem creates (or updates, if already present) a CephFilesystem in the given namespace from the provided configuration. It is idempotent and safe to call on every test run.

func CreateElasticCluster

func CreateElasticCluster(ctx context.Context, kubeconfig *rest.Config, params ElasticClusterParams) error

CreateElasticCluster creates (or updates the spec of) an ElasticCluster. Idempotent: re-running overwrites spec so callers can tweak ElasticClusterParams and re-apply. Fails fast if the existing CR is Terminating (its spec update would be a no-op while the finalizer unwinds, and a follow-up wait-Ready would hang on a never-Ready object).

func CreateElasticStorageClass

func CreateElasticStorageClass(ctx context.Context, kubeconfig *rest.Config, params ElasticStorageClassParams) error

CreateElasticStorageClass creates (or updates the spec of) an ElasticStorageClass. Idempotent; fails fast on a Terminating existing CR.

func CreateLVMVolumeGroup

func CreateLVMVolumeGroup(ctx context.Context, kubeconfig *rest.Config, name, nodeName string, blockDeviceNames []string, actualVGName string) error

CreateLVMVolumeGroup creates an LVMVolumeGroup resource for a specific node

func CreateLVMVolumeGroupWithThinPool

func CreateLVMVolumeGroupWithThinPool(ctx context.Context, kubeconfig *rest.Config, name, nodeName string, blockDeviceNames []string, actualVGName string, thinPools []ThinPoolSpec) error

CreateLVMVolumeGroupWithThinPool creates an LVMVolumeGroup resource with thin pools for a specific node

func CreateLocalStorageClass

func CreateLocalStorageClass(ctx context.Context, kubeconfig *rest.Config, cfg LocalStorageClassConfig) error

func CreateNamespaceIfNotExists

func CreateNamespaceIfNotExists(ctx context.Context, config *rest.Config, name string) (*corev1.Namespace, error)

CreateNamespaceIfNotExists creates a namespace if it doesn't exist, or returns the existing one.

func CreateStaticNodeGroup

func CreateStaticNodeGroup(ctx context.Context, config *rest.Config, name string) error

CreateStaticNodeGroup creates a NodeGroup resource with Static nodeType.

Right after bootstrap the node-manager validating webhook (node-controller-webhook in d8-cloud-instance-manager) is frequently not reachable yet, so the apiserver rejects the create with a transient InternalError ("failed calling webhook ... connect: operation not permitted"). We retry with backoff until the webhook converges; retry.IsRetryable already classifies both InternalError and "failed calling webhook" as transient. The loop is bounded by the caller's context (config.NodeGroupTimeout).

func CreateStorageClass

func CreateStorageClass(ctx context.Context, kubeconfig *rest.Config, cfg StorageClassCreateConfig) error

CreateStorageClass creates a StorageClass from cfg, or no-ops if it already exists.

func CreateVolumeSnapshotClass

func CreateVolumeSnapshotClass(ctx context.Context, kubeconfig *rest.Config, cfg VolumeSnapshotClassConfig) error

func DeleteCephFilesystem

func DeleteCephFilesystem(ctx context.Context, kubeconfig *rest.Config, namespace, name string) error

DeleteCephFilesystem deletes a CephFilesystem. Safe to call if the filesystem does not exist. NOTE: fire-and-forget — Rook's `cephfilesystem.ceph.rook.io` finalizer takes time to detach the MDS daemons and remove the metadata/data pools. Pair with WaitForCephFilesystemGone if you need to know the CR has actually been GC'd before doing something else (e.g. deleting the parent CephCluster).

func DeleteElasticCluster

func DeleteElasticCluster(ctx context.Context, kubeconfig *rest.Config, name string) error

DeleteElasticCluster removes an ElasticCluster. Idempotent (NotFound is swallowed). Fire-and-forget: the controller then runs its ordered teardown finalizer (delete CephCluster + csi-ceph wiring the operator cannot delete by hand). Follow with WaitForElasticClusterGone to be sure it is GC'd.

func DeleteElasticStorageClass

func DeleteElasticStorageClass(ctx context.Context, kubeconfig *rest.Config, name string) error

DeleteElasticStorageClass removes an ElasticStorageClass. Idempotent. Fire-and-forget: the controller runs the destructive pool/filesystem teardown (and the bound-PV guard) under its finalizer. Follow with WaitForElasticStorageClassGone.

func DeleteLVMVolumeGroup

func DeleteLVMVolumeGroup(ctx context.Context, kubeconfig *rest.Config, name string) error

DeleteLVMVolumeGroup deletes an LVMVolumeGroup resource by name

func DeleteNamespace

func DeleteNamespace(ctx context.Context, config *rest.Config, name string) error

func DeleteRookConfigOverride

func DeleteRookConfigOverride(ctx context.Context, kubeconfig *rest.Config, namespace string) error

DeleteRookConfigOverride removes the `rook-config-override` ConfigMap. It is safe to call when the ConfigMap does not exist.

func DetachAndDeleteVirtualDisk

func DetachAndDeleteVirtualDisk(ctx context.Context, kubeconfig *rest.Config, namespace, attachmentName, diskName string) error

DetachAndDeleteVirtualDisk deletes the VirtualMachineBlockDeviceAttachment and then the VirtualDisk. Use this for cleanup after a test. Errors are logged but not returned for "not found" (idempotent).

func EnableAndConfigureModules

func EnableAndConfigureModules(ctx context.Context, kubeconfig *rest.Config, clusterDef *config.ClusterDefinition, sshClient ssh.SSHClient) error

EnableAndConfigureModules enables and configures modules based on cluster definition It builds a dependency graph and processes modules level by level using topological sort After configuring each level, it waits for all modules in that level to become Ready before proceeding to the next level

func EnableModulesAndWait

func EnableModulesAndWait(ctx context.Context, kubeconfig *rest.Config, sshClient ssh.SSHClient, clusterDef *config.ClusterDefinition, modules []ModuleSpec, timeout time.Duration) error

EnableModulesAndWait is a convenience function that enables modules and waits for them to become ready in one call.

Parameters:

  • ctx: context for cancellation
  • kubeconfig: kubernetes client config
  • sshClient: SSH client for cluster access
  • clusterDef: cluster definition (can be nil for existing clusters)
  • modules: list of module specifications to enable
  • timeout: maximum time to wait for all modules to become ready

func EnableModulesWithSpecs

func EnableModulesWithSpecs(ctx context.Context, kubeconfig *rest.Config, sshClient ssh.SSHClient, clusterDef *config.ClusterDefinition, modules []ModuleSpec) error

EnableModulesWithSpecs enables and configures the specified modules in the test cluster. It handles dependencies automatically through topological sort and waits for each level of modules to become Ready before proceeding to the next level.

func ExecInPod

func ExecInPod(
	ctx context.Context,
	kubeconfig *rest.Config,
	namespace, pod, container string,
	cmd []string,
) (stdout, stderr string, err error)

ExecInPod runs cmd inside container of pod namespace/pod via the apiserver's pods/exec subresource and returns stdout and stderr separately, plus any transport- or exec-level error.

The container must ship every binary referenced by cmd; ExecInPod does NOT inject any helper. For distroless containers without cat / sh, see ReadFileFromDistrolessPod.

func FindSecretByName

func FindSecretByName(ctx context.Context, kubeconfig *rest.Config, namespace, name string) (string, error)

FindSecretByName finds a secret by name, trying multiple matching strategies This helps with issues where secret names might have hidden Unicode characters 1. Exact match 2. Case-insensitive match 3. Fuzzy match (ignoring common Unicode issues like non-breaking spaces) Returns the actual secret name found (which may differ from the requested name due to Unicode issues)

func FindUnsetEnvVars

func FindUnsetEnvVars(content string) []string

FindUnsetEnvVars finds all ${VAR} patterns in content and returns those that are not set

func GetDefaultStorageClassName

func GetDefaultStorageClassName(ctx context.Context, kubeconfig *rest.Config) (string, error)

GetDefaultStorageClassName returns the name of the current default StorageClass (annotated with storageclass.kubernetes.io/is-default-class=true), or "" if none exists.

func GetElasticClusterCondition

func GetElasticClusterCondition(ctx context.Context, kubeconfig *rest.Config, name, condType string) (status, reason, message string, found bool, err error)

GetElasticClusterCondition returns the (status, reason, message) of the named condition on the ElasticCluster, plus whether the condition exists. Single GET, no waiting — meant to be wrapped in a Gomega Eventually / Consistently when asserting teardown-guard reasons on a Terminating CR.

func GetElasticStorageClassCondition

func GetElasticStorageClassCondition(ctx context.Context, kubeconfig *rest.Config, name, condType string) (status, reason, message string, found bool, err error)

GetElasticStorageClassCondition returns the (status, reason, message) of the named condition on the ESC, plus whether it exists. Single GET; wrap in a Gomega Eventually/Consistently to assert teardown-guard reasons.

func GetNodeTaints

func GetNodeTaints(ctx context.Context, kubeconfig *rest.Config, nodeName string) ([]corev1.Taint, error)

GetNodeTaints returns the taints of the named node.

func GetNodes

func GetNodes(ctx context.Context, kubeconfig *rest.Config) ([]corev1.Node, error)

GetNodes returns the names of all nodes in the cluster.

func GetSecretDataValue

func GetSecretDataValue(ctx context.Context, kubeconfig *rest.Config, namespace, name, key string) (string, error)

GetSecretDataValue retrieves a specific data value from a secret by name It uses FindSecretByName to handle potential Unicode character issues

func GetStorageClass

func GetStorageClass(ctx context.Context, kubeconfig *rest.Config, name string) (*storagev1.StorageClass, error)

GetStorageClass returns the StorageClass with the given name, or (nil, nil) if it does not exist.

func GetVMIPFromBaseCluster

func GetVMIPFromBaseCluster(ctx context.Context, baseKubeconfig *rest.Config, namespace, vmName string) (string, error)

GetVMIPFromBaseCluster returns the IP address of a VirtualMachine in the base cluster (namespace). Used to SSH to the VM (e.g. cloud@ip) from the jump host to run lsblk on nested nodes.

func GetVMPodNodeAndContainerID

func GetVMPodNodeAndContainerID(ctx context.Context, baseConfig *rest.Config, namespace, vmName string) (nodeName, containerID string, err error)

GetVMPodNodeAndContainerID returns the base cluster node name and the first container ID for the Pod that runs the given VM (e.g. virt-launcher-<vmName>-*). Used to run nsenter into the VM container from the base cluster node.

func GetWorkerNodes

func GetWorkerNodes(ctx context.Context, kubeconfig *rest.Config) ([]corev1.Node, error)

GetWorkerNodes returns all worker nodes in the cluster. A worker node is any node that does NOT have the "node-role.kubernetes.io/control-plane" label.

func IsNodeCordoned

func IsNodeCordoned(ctx context.Context, kubeconfig *rest.Config, nodeName string) (bool, error)

IsNodeCordoned checks whether a node has NoSchedule or NoExecute taints that would prevent DaemonSet pods from scheduling.

func LabelBlockDevice

func LabelBlockDevice(ctx context.Context, kubeconfig *rest.Config, name, labelKey, labelValue string) error

LabelBlockDevice sets a label on a single BlockDevice CR. Idempotent (skips the update when the label already has the desired value) and tolerant of optimistic-concurrency conflicts. Used to mark BlockDevices eligible for adoption by an ElasticCluster's blockDeviceSelector.

func LabelNodes

func LabelNodes(ctx context.Context, kubeconfig *rest.Config, nodeNames []string, labelKey, labelValue string) error

LabelNodes adds a label to each of the specified nodes. If a node already has the label with the desired value, it is skipped. Uses retry with re-fetch to handle optimistic concurrency conflicts.

func ListElasticRookCephClusterNames

func ListElasticRookCephClusterNames(ctx context.Context, kubeconfig *rest.Config, namespace string) ([]string, error)

ListElasticRookCephClusterNames returns the names of all renamed-group CephClusters in the namespace. Used to assert the sds-elastic controller created exactly the CephCluster(s) it should have.

func ListVirtualMachineNames

func ListVirtualMachineNames(ctx context.Context, kubeconfig *rest.Config, namespace string) ([]string, error)

ListVirtualMachineNames returns names of VirtualMachines in the given namespace. Used to pick a VM when attaching a VirtualDisk (e.g. in alwaysUseExisting mode).

func NewClientsetWithRetry

func NewClientsetWithRetry(ctx context.Context, config *rest.Config) (*kubernetes.Clientset, error)

NewClientsetWithRetry creates a new Kubernetes clientset with retry logic for transient network errors. While kubernetes.NewForConfig itself does not make network calls, this wrapper provides a centralized factory with retry that validates the connection by performing a lightweight server version check. This ensures the cluster is reachable before returning the clientset.

func NewDynamicClientWithRetry

func NewDynamicClientWithRetry(ctx context.Context, config *rest.Config) (dynamic.Interface, error)

NewDynamicClientWithRetry creates a new Kubernetes dynamic client with retry logic for transient network errors. Similar to NewClientsetWithRetry, this provides a centralized factory for dynamic clients with built-in retry.

func NewVirtualizationClient

func NewVirtualizationClient(ctx context.Context, config *rest.Config) (*virtualization.Client, error)

func ReadFileFromDistrolessPod

func ReadFileFromDistrolessPod(
	ctx context.Context,
	kubeconfig *rest.Config,
	namespace, pod, targetContainer, path string,
	opts ReadFileOptions,
) (string, error)

ReadFileFromDistrolessPod reads `path` from inside `targetContainer` of pod `namespace/pod` even when targetContainer ships no shell, no cat and no tar — i.e. a distroless or scratch image like csi-controller. It does so by injecting a short-lived ephemeral container (TargetContainerName=targetContainer, which gives it a shared PID namespace with the target) and then catting /proc/1/root<path>. /proc/1 is PID 1 inside the target container's PID namespace, and /proc/<pid>/root is the well-known kernel-exposed view of that process's filesystem root.

Why this does NOT restart the target pod or any of its containers:

  • Ephemeral containers are added through the dedicated /pods/<name>/ephemeralcontainers subresource (UpdateEphemeralContainers in client-go). The apiserver explicitly allows this mutation on a running pod; the ordinary pod PUT/PATCH path that would trigger re-creation is bypassed entirely. Without this dedicated path, adding a container to a live pod would be flat-out forbidden.
  • metadata.generation, spec.containers, the pod sandbox UID and the ReplicaSet/DaemonSet observation all stay intact. The kubelet simply launches the new container in the existing pod sandbox without disturbing existing containers. Workload-controller rollouts and pod-template `checksum/...` annotations are not affected, so e2e suites that subsequently assert on rollout state see a clean signal — the FS read does not contaminate it.
  • Ephemeral containers are forbidden from declaring ports, probes, lifecycle hooks or resources, which guarantees the inject is a cheap no-op for the pod's lifecycle.

Caveat: ephemeral containers cannot be removed once added. The cat process exits with the container after `sleep`, but the entry remains in pod.spec.ephemeralContainers and pod.status.ephemeralContainerStatuses (state=Terminated). For long-running suites those entries simply pile up until the next pod recycle. Each invocation here generates a unique container name, so repeat calls against the same pod are safe.

For polling loops or any scenario that reads the same pod multiple times, prefer OpenDistrolessReader: each ReadFileFromDistrolessPod call pays the full ephemeral-container cold-start cost (~10–20 s for kubelet to launch a new container in the existing pod sandbox), and that cost dominates the runtime of a Eventually-style poll.

func ReadFileFromPod

func ReadFileFromPod(
	ctx context.Context,
	kubeconfig *rest.Config,
	namespace, pod, container, path string,
) (string, error)

ReadFileFromPod cat's `path` from inside `container` of pod `namespace/pod`. Equivalent to `kubectl exec -c container -- cat path`, with stderr surfaced as part of the error if non-empty.

Requires the container image to ship cat. For distroless / scratch images, use ReadFileFromDistrolessPod.

func RenderCephGlobalConfig

func RenderCephGlobalConfig(globals map[string]string) string

RenderCephGlobalConfig renders a `[global]` section for ceph.conf from the provided key/value pairs. Keys are sorted so the rendered output is stable across calls with logically-equivalent maps (avoids unnecessary CM updates).

func ResizeList

func ResizeList(ctx context.Context, clientset *kubernetes.Clientset, namespace string, pvcNames []string, newSize string) error

ResizeList resizes multiple PVCs to a new size in parallel

func ServerHasAPIGroup

func ServerHasAPIGroup(ctx context.Context, kubeconfig *rest.Config, group string) (bool, error)

ServerHasAPIGroup reports whether the apiserver advertises the given API group in discovery. The e2e suite uses it to assert that the upstream ceph.rook.io group is absent on a cluster running sds-elastic (the module renames Rook to internal.sdselastic.deckhouse.io to avoid clobbering a user-installed upstream Rook).

func SetGlobalDefaultStorageClass

func SetGlobalDefaultStorageClass(ctx context.Context, kubeconfig *rest.Config, storageClassName string) error

SetGlobalDefaultStorageClass updates the "global" ModuleConfig to set spec.settings.storageClass to the given name, making it the cluster default.

func SetRookConfigOverride

func SetRookConfigOverride(ctx context.Context, kubeconfig *rest.Config, namespace string, globals map[string]string) error

SetRookConfigOverride creates or updates the `rook-config-override` ConfigMap in the given Rook operator namespace so that Ceph daemons pick up the provided global settings.

The ConfigMap format expected by Rook is:

apiVersion: v1
kind: ConfigMap
metadata:
  name: rook-config-override
  namespace: <rook-namespace>
data:
  config: |
    [global]
    key1 = value1
    key2 = value2

`globals` is rendered under `[global]`. Keys are sorted for a stable output. Passing an empty/nil `globals` map produces an empty `[global]` section, which effectively clears previously-set overrides.

func WaitForAllPodsReadyInNamespace

func WaitForAllPodsReadyInNamespace(ctx context.Context, kubeconfig *rest.Config, namespace string, timeout time.Duration) error

WaitForAllPodsReadyInNamespace waits for all pods in a namespace to be in Ready condition

func WaitForCephFilesystemGone

func WaitForCephFilesystemGone(ctx context.Context, kubeconfig *rest.Config, namespace, name string, timeout time.Duration) error

WaitForCephFilesystemGone polls until the CephFilesystem is fully GC'd by Kubernetes (GET returns NotFound). Use this after DeleteCephFilesystem to be sure the parent CephCluster's deletion won't be blocked by `ObjectHasDependents`.

func WaitForCephFilesystemReady

func WaitForCephFilesystemReady(ctx context.Context, kubeconfig *rest.Config, namespace, name string, timeout time.Duration) error

WaitForCephFilesystemReady blocks until the CephFilesystem reports `status.phase == "Ready"`. As a fallback (some Rook revisions populate `status.conditions` first) the function also accepts a Ready=True condition.

Per-call deadlines and loud (WARN) logging on consecutive network failures are inherited from pollResourceUntilReady.

func WaitForElasticClusterCondition

func WaitForElasticClusterCondition(ctx context.Context, kubeconfig *rest.Config, name, condType, wantStatus string, timeout time.Duration) error

WaitForElasticClusterCondition blocks until the named ElasticCluster has a status condition of the given type observed at the wanted status (e.g. type="Ready", status="True"). It refuses to wait on a Terminating object — use GetElasticClusterCondition + a Gomega Eventually loop when you need to observe a teardown-guard reason on a CR that is already being deleted.

func WaitForElasticClusterGone

func WaitForElasticClusterGone(ctx context.Context, kubeconfig *rest.Config, name string, timeout time.Duration) error

WaitForElasticClusterGone polls until the ElasticCluster GET returns NotFound (Kubernetes has GC'd it after the controller finalizer completed).

func WaitForElasticClusterReady

func WaitForElasticClusterReady(ctx context.Context, kubeconfig *rest.Config, name string, timeout time.Duration) error

WaitForElasticClusterReady waits for the aggregate Ready condition to flip to True (i.e. storage staged, Rook CephCluster up, credentials backed up, csi-ceph wired).

func WaitForElasticRookCephBlockPoolReady

func WaitForElasticRookCephBlockPoolReady(ctx context.Context, kubeconfig *rest.Config, namespace, name string, timeout time.Duration) error

WaitForElasticRookCephBlockPoolReady blocks until the renamed-group CephBlockPool reports status.phase=Ready.

func WaitForElasticRookCephClusterReady

func WaitForElasticRookCephClusterReady(ctx context.Context, kubeconfig *rest.Config, namespace, name string, timeout time.Duration) error

WaitForElasticRookCephClusterReady blocks until the renamed-group CephCluster reports state=Created (or phase=Ready). Mirrors the readiness logic of WaitForCephClusterReady but against internal.sdselastic.deckhouse.io.

func WaitForElasticRookCephFilesystemReady

func WaitForElasticRookCephFilesystemReady(ctx context.Context, kubeconfig *rest.Config, namespace, name string, timeout time.Duration) error

WaitForElasticRookCephFilesystemReady blocks until the renamed-group CephFilesystem reports status.phase=Ready.

func WaitForElasticStorageClassCondition

func WaitForElasticStorageClassCondition(ctx context.Context, kubeconfig *rest.Config, name, condType, wantStatus string, timeout time.Duration) error

WaitForElasticStorageClassCondition blocks until the named ESC has a status condition of the given type at the wanted status. Refuses to wait on a Terminating object (see WaitForElasticClusterCondition).

func WaitForElasticStorageClassGone

func WaitForElasticStorageClassGone(ctx context.Context, kubeconfig *rest.Config, name string, timeout time.Duration) error

WaitForElasticStorageClassGone polls until the ESC GET returns NotFound.

func WaitForElasticStorageClassReady

func WaitForElasticStorageClassReady(ctx context.Context, kubeconfig *rest.Config, name string, timeout time.Duration) error

WaitForElasticStorageClassReady waits for the aggregate Ready condition to flip to True (pool/filesystem provisioned, csi-ceph SC materialized).

func WaitForLVMVolumeGroupDeletion

func WaitForLVMVolumeGroupDeletion(ctx context.Context, kubeconfig *rest.Config, name string, timeout time.Duration) error

WaitForLVMVolumeGroupDeletion waits for an LVMVolumeGroup to be deleted

func WaitForLVMVolumeGroupReady

func WaitForLVMVolumeGroupReady(ctx context.Context, kubeconfig *rest.Config, name string, timeout time.Duration) error

WaitForLVMVolumeGroupReady waits for an LVMVolumeGroup to become Ready

func WaitForLocalStorageClassCreated

func WaitForLocalStorageClassCreated(ctx context.Context, kubeconfig *rest.Config, name string, timeout time.Duration) error

WaitForLocalStorageClassCreated waits for the LocalStorageClass CR status to indicate that the controller has created the corresponding StorageClass.

func WaitForModuleReady

func WaitForModuleReady(ctx context.Context, kubeconfig *rest.Config, moduleName string, timeout time.Duration) error

WaitForModuleReady polls a Deckhouse Module until it reaches the Ready phase.

Reliability notes (this replaces an earlier one-shot phase check that was flaky during cluster creation):

  • The whole wait is bounded by a derived context deadline, so persistent GetModule failures (dropped SSH tunnel, API hiccup) also time out instead of hanging until the parent context is canceled.
  • Transient GetModule errors and intermediate phases (Downloading, Installing, Reconciling, and even Error — modules can recover) are tolerated; only the timeout is terminal.
  • On timeout the error carries the last observed phase and the IsReady condition message so a stuck module is diagnosable from logs alone.

func WaitForModulesReady

func WaitForModulesReady(ctx context.Context, kubeconfig *rest.Config, clusterDef *config.ClusterDefinition, timeout time.Duration) error

WaitForModulesReady waits for all modules specified in cluster definition to be ready It builds a dependency graph and waits for modules level by level using topological sort

func WaitForModulesReadyWithSpecs

func WaitForModulesReadyWithSpecs(ctx context.Context, kubeconfig *rest.Config, clusterDef *config.ClusterDefinition, modules []ModuleSpec, timeout time.Duration) error

WaitForModulesReadyWithSpecs waits for the specified modules to become ready. This is typically called after EnableModulesWithSpecs to ensure all modules are operational.

Parameters:

  • ctx: context for cancellation
  • kubeconfig: kubernetes client config
  • clusterDef: cluster definition (can be nil for existing clusters)
  • modules: list of module specifications to wait for
  • timeout: maximum time to wait for all modules

func WaitForNodesLabeled

func WaitForNodesLabeled(ctx context.Context, kubeconfig *rest.Config, nodeNames []string, labelKey, labelValue string) error

WaitForNodesLabeled waits for all specified nodes to have the given label with the expected value. It polls each node in parallel every 10 seconds until all nodes have the label or the context times out. Parameters:

  • ctx: context with timeout/cancellation
  • kubeconfig: Kubernetes REST config
  • nodeNames: list of node names to check
  • labelKey: the label key to look for (e.g., "storage.deckhouse.io/node-ready-for-iscsi")
  • labelValue: the expected label value (e.g., "true")

func WaitForPVCsBound

func WaitForPVCsBound(ctx context.Context, clientset *kubernetes.Clientset, namespace, labelSelector string, expectedCount int, maxAttempts int, interval time.Duration) error

WaitForPVCsBound waits for PVCs matching the label selector to be in Bound state

func WaitForPVCsResized

func WaitForPVCsResized(ctx context.Context, clientset *kubernetes.Clientset, namespace string, pvcNames []string, targetSize string, maxAttempts int, interval time.Duration) error

WaitForPVCsResized waits for PVCs to be resized to the target size

func WaitForPodsStatus

func WaitForPodsStatus(ctx context.Context, clientset *kubernetes.Clientset, namespace, labelSelector, status string, expectedCount int, maxAttempts int, interval time.Duration) error

WaitForPodsStatus waits for pods to reach a specific status

func WaitForStorageClass

func WaitForStorageClass(ctx context.Context, kubeconfig *rest.Config, storageClassName string, timeout time.Duration) error

WaitForStorageClass waits for a storage class to become available

func WaitForStorageClasses

func WaitForStorageClasses(ctx context.Context, kubeconfig *rest.Config, storageClassNames []string, timeout time.Duration) map[string]error

WaitForStorageClasses waits for multiple storage classes to become available in parallel Returns map of storage class names to errors (nil if successful, error if failed/not found)

func WaitForVirtualDiskAttached

func WaitForVirtualDiskAttached(ctx context.Context, kubeconfig *rest.Config, namespace, attachmentName string, pollInterval time.Duration) error

WaitForVirtualDiskAttached waits for the VirtualMachineBlockDeviceAttachment to reach the Attached phase. It polls the attachment status until it's attached or the context is cancelled/times out. The pollInterval parameter specifies how often to check the status (recommended: 10 seconds).

func WaitForVolumeSnapshotClass

func WaitForVolumeSnapshotClass(ctx context.Context, kubeconfig *rest.Config, name string, timeout time.Duration) error

Types

type ApplyClient

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

ApplyClient handles applying YAML manifests to a Kubernetes cluster

func NewApplyClient

func NewApplyClient(config *rest.Config) (*ApplyClient, error)

NewApplyClient creates a new ApplyClient Includes retry logic for transient network errors during client creation

func (*ApplyClient) ApplyYAML

func (c *ApplyClient) ApplyYAML(ctx context.Context, yamlContent string, namespace string) error

ApplyYAML applies YAML manifest(s) to the cluster The yamlContent can contain multiple YAML documents separated by "---" namespace parameter is optional - if empty, uses namespace from manifest or "default"

func (*ApplyClient) CreateYAML

func (c *ApplyClient) CreateYAML(ctx context.Context, yamlContent string, namespace string) error

CreateYAML creates resources from YAML manifest(s) Unlike ApplyYAML, this will fail if resources already exist

func (*ApplyClient) CreateYAMLFromFileWithEnvvars

func (c *ApplyClient) CreateYAMLFromFileWithEnvvars(ctx context.Context, filePath string, namespace string) error

CreateYAMLFromFileWithEnvvars reads a YAML file, validates environment variables, substitutes them, and creates resources Returns error if file cannot be read, any ${VAR} is not set, or resource creation fails

type BlockDevice

type BlockDevice = storage.BlockDeviceInfo

BlockDevice represents a block device in the cluster (re-export for public API)

func GetConsumableBlockDevices

func GetConsumableBlockDevices(ctx context.Context, kubeconfig *rest.Config) ([]BlockDevice, error)

GetConsumableBlockDevices returns all consumable BlockDevices from the cluster

func GetConsumableBlockDevicesByNode

func GetConsumableBlockDevicesByNode(ctx context.Context, kubeconfig *rest.Config, nodeName string) ([]BlockDevice, error)

GetConsumableBlockDevicesByNode returns consumable BlockDevices for a specific node.

type CephFilesystemConfig

type CephFilesystemConfig struct {
	// Name of the CephFilesystem CR.
	Name string

	// Namespace the Rook operator watches (typically "d8-sds-elastic").
	Namespace string

	// FailureDomain is the CRUSH failure domain: "host" or "osd"
	// (default: "osd" when MetadataPoolReplicas == DataPoolReplicas == 1,
	// "host" otherwise).
	FailureDomain string

	// MetadataPoolReplicas is the metadata pool replication factor. Default: 1.
	MetadataPoolReplicas int

	// DataPoolName is the (Rook-side) data pool name. The full Ceph pool
	// name is "<Name>-<DataPoolName>" — see CephFSDataPoolFullName.
	// Default: "data0".
	DataPoolName string

	// DataPoolReplicas is the data pool replication factor. Default: 1.
	DataPoolReplicas int

	// MetadataServerActiveCount is the number of active MDS daemons.
	// Default: 1.
	MetadataServerActiveCount int

	// RequireSafeReplicaSize toggles Ceph's safeguard against single-replica
	// pools. When nil, it is set to false for replicas==1 (unsafe single
	// replica, accepted for e2e test clusters) and left unset otherwise.
	RequireSafeReplicaSize *bool
}

CephFilesystemConfig describes a minimal Rook CephFilesystem with one metadata pool and exactly one data pool. Defaults are tuned for tiny single-node test clusters.

type DistrolessReader

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

DistrolessReader is a long-lived ephemeral-container reader session against a single distroless pod. Open one with OpenDistrolessReader, then call ReadFile as many times as you need — each ReadFile is just an exec into the already-running ephemeral container (cheap), so a polling loop pays the ephemeral-container cold start ONCE instead of per-iteration.

The session expires when the ephemeral container's `sleep` (opts.SessionTTL, default DefaultDistrolessSessionTTL) elapses; there is no Close — Kubernetes does not allow removing an ephemeral container — but the inert "Terminated" status entry has no effect on the pod. Callers that need fresh sessions across pod identities (e.g. after a workload rollout) should re-open against the new pod.

func OpenDistrolessReader

func OpenDistrolessReader(
	ctx context.Context,
	kubeconfig *rest.Config,
	namespace, pod, targetContainer string,
	opts ReadFileOptions,
) (*DistrolessReader, error)

OpenDistrolessReader injects a long-lived ephemeral container into the target pod and waits for it to become Running. The returned DistrolessReader can then be used for arbitrarily many cheap ReadFile calls until opts.SessionTTL elapses (default 30 minutes).

Failure modes (returned as errors): pod not found, ephemeral container terminates before Running, image pull failure, startup timeout. On any of these no usable reader is returned.

See ReadFileFromDistrolessPod for the rationale on why this does not restart the target pod or any of its existing containers.

func (*DistrolessReader) EphemeralName

func (r *DistrolessReader) EphemeralName() string

EphemeralName returns the auto-generated name of the injected ephemeral container, mostly for logging.

func (*DistrolessReader) PodName

func (r *DistrolessReader) PodName() string

PodName returns the name of the pod this reader is bound to. Useful for callers that need to detect rollouts (the pod name changes when the workload-controller recycles the pod) and re-open the session.

func (*DistrolessReader) ReadFile

func (r *DistrolessReader) ReadFile(ctx context.Context, path string) (string, error)

ReadFile cat's `path` from inside the target container's filesystem (resolved through the ephemeral container's view of /proc/1/root). Cheap — just a pods/exec round-trip; no apiserver mutations.

type ElasticClusterCephTopology

type ElasticClusterCephTopology struct {
	MonCount int64
	MgrCount int64
	Reason   string
}

ElasticClusterCephTopology mirrors status.cephTopology — the effective mon/mgr counts the controller asked Rook to apply, plus the audit reason.

func GetElasticClusterCephTopology

func GetElasticClusterCephTopology(ctx context.Context, kubeconfig *rest.Config, name string) (topology ElasticClusterCephTopology, found bool, err error)

GetElasticClusterCephTopology reads status.cephTopology of the named ElasticCluster. found is false when the controller has not recorded a topology yet (cluster still bootstrapping).

type ElasticClusterParams

type ElasticClusterParams struct {
	// Name of the ElasticCluster (cluster-scoped, so no namespace).
	Name string

	// NodeSelectorMatchLabels populates spec.storage.nodeSelector.matchLabels.
	// Must be non-empty: it is how the controller picks storage nodes.
	NodeSelectorMatchLabels map[string]string

	// BlockDeviceSelectorMatchLabels populates
	// spec.storage.blockDeviceSelector.matchLabels. Must be non-empty: it is
	// how the controller adopts BlockDevices for OSDs.
	BlockDeviceSelectorMatchLabels map[string]string

	// NetworkPublic / NetworkCluster optionally pin spec.network.{public,
	// cluster}. Both must be set together; otherwise spec.network is omitted.
	NetworkPublic  string
	NetworkCluster string

	// Labels / Annotations are applied verbatim to metadata.
	Labels      map[string]string
	Annotations map[string]string
}

ElasticClusterParams is the minimal description of an ElasticCluster the e2e suite needs to render. Selectors are expressed as plain matchLabels maps (the only selector form the suite exercises); spec.network is emitted only when both CIDRs are provided (otherwise Rook uses host networking on every storage-node IP, which is what the default e2e cluster wants).

type ElasticStorageClassParams

type ElasticStorageClassParams struct {
	// Name of the ElasticStorageClass; also the name of the resulting
	// csi-ceph CephStorageClass and the core k8s StorageClass.
	Name string

	// ClusterRef is the ElasticCluster this ESC belongs to. Required.
	ClusterRef string

	// Type selects RBD (block) or CephFS (shared filesystem). Required.
	Type string

	// Replication picks the high-level replication strategy. Empty defaults
	// to ConsistencyAndAvailability (the CRD default).
	Replication string

	// Labels / Annotations are applied verbatim to metadata.
	Labels      map[string]string
	Annotations map[string]string
}

ElasticStorageClassParams is the minimal description of an ElasticStorageClass the e2e suite renders.

type LocalStorageClassConfig

type LocalStorageClassConfig struct {
	Name              string
	LVMVolumeGroups   []string // LVMVolumeGroup resource names
	LVMType           string   // "Thick" or "Thin"
	ThinPoolName      string   // required when LVMType is "Thin"
	ReclaimPolicy     string   // "Delete" or "Retain" (default: "Delete")
	VolumeBindingMode string   // "WaitForFirstConsumer" or "Immediate" (default: "WaitForFirstConsumer")
}

type ModuleSpec

type ModuleSpec struct {
	// Name is the name of the module (e.g., "snapshot-controller", "csi-hpe")
	Name string

	// Version is the module config version (typically 1)
	Version int

	// Enabled indicates whether the module should be enabled
	Enabled bool

	// Settings contains module-specific settings
	Settings map[string]interface{}

	// Dependencies lists module names that must be enabled before this one
	Dependencies []string

	// ModulePullOverride overrides the module pull branch/tag (e.g., "main", "pr123")
	// Only used for dev registries (registries starting with "dev-")
	ModulePullOverride string
}

ModuleSpec defines a module to be enabled in the cluster. This is a simplified version of config.ModuleConfig that provides a clean API for test writers.

type ReadFileOptions

type ReadFileOptions struct {
	// DebugImage is the ephemeral container image (required). Use a minimal
	// image that ships cat and sleep, e.g. busybox from your cluster registry.
	DebugImage string
	// StartupTimeout caps the wait for the ephemeral container to reach
	// state.Running. Defaults to DefaultEphemeralStartupTimeout.
	StartupTimeout time.Duration
	// SessionTTL controls how long the injected ephemeral container's
	// `sleep` process stays alive. Defaults to DefaultDistrolessSessionTTL.
	// Used by OpenDistrolessReader; ReadFileFromDistrolessPod does not
	// rely on this value (the entry's status flip after the cat exits
	// has no effect on the pod).
	SessionTTL time.Duration
}

ReadFileOptions tunes ReadFileFromDistrolessPod and OpenDistrolessReader.

type StorageClassCreateConfig

type StorageClassCreateConfig struct {
	Name              string
	Provisioner       string
	Parameters        map[string]string
	VolumeBindingMode storagev1.VolumeBindingMode
	ReclaimPolicy     corev1.PersistentVolumeReclaimPolicy
	AllowExpansion    bool
	MakeDefault       bool
	AdditionalLabels  map[string]string
	AdditionalAnnot   map[string]string
}

StorageClassCreateConfig describes a StorageClass to create via CreateStorageClass.

type TestClusterResourcesInterface

type TestClusterResourcesInterface interface {
	GetKubeconfig() *rest.Config
	GetSSHClient() ssh.SSHClient
	GetClusterDefinition() *config.ClusterDefinition
}

TestClusterResourcesInterface defines the interface for accessing test cluster resources This avoids circular imports with the cluster package

type ThinPoolSpec

type ThinPoolSpec struct {
	Name            string // Thin pool name
	Size            string // Size of the thin pool (e.g., "50%" or "10Gi")
	AllocationLimit string // Allocation limit (optional)
}

ThinPoolSpec represents a thin pool specification for LVMVolumeGroup

type VirtualDiskAttachmentConfig

type VirtualDiskAttachmentConfig struct {
	// VMName is the name of the VirtualMachine to attach the disk to
	VMName string
	// Namespace is the namespace where the VM and disk resources are located
	Namespace string
	// DiskName is the name for the new VirtualDisk (optional, auto-generated if empty)
	DiskName string
	// DiskSize is the size of the disk (e.g., "200Gi")
	DiskSize string
	// StorageClassName is the storage class to use for the disk
	StorageClassName string
}

VirtualDiskAttachmentConfig holds configuration for attaching a virtual disk to a VM

type VirtualDiskAttachmentResult

type VirtualDiskAttachmentResult struct {
	// DiskName is the name of the created VirtualDisk
	DiskName string
	// AttachmentName is the name of the created VirtualMachineBlockDeviceAttachment
	AttachmentName string
}

VirtualDiskAttachmentResult holds the result of attaching a virtual disk

func AttachVirtualDiskToVM

func AttachVirtualDiskToVM(ctx context.Context, kubeconfig *rest.Config, config VirtualDiskAttachmentConfig) (*VirtualDiskAttachmentResult, error)

AttachVirtualDiskToVM creates a VirtualDisk and attaches it to the specified VM using VirtualMachineBlockDeviceAttachment. The disk is created as a blank disk with the specified size and storage class. Returns the names of created resources for later use (e.g., waiting for attachment or cleanup).

func ReattachVirtualDiskToVM

func ReattachVirtualDiskToVM(ctx context.Context, kubeconfig *rest.Config, config VirtualDiskReattachmentConfig) (*VirtualDiskAttachmentResult, error)

ReattachVirtualDiskToVM attaches an existing VirtualDisk to the specified VM. It creates a VirtualMachineBlockDeviceAttachment using the provided disk and attachment names.

type VirtualDiskReattachmentConfig

type VirtualDiskReattachmentConfig struct {
	// AttachmentName is the name of the VirtualMachineBlockDeviceAttachment to create.
	AttachmentName string
	// VMName is the name of the VirtualMachine to attach the disk to.
	VMName string
	// Namespace is the namespace where the VM and disk resources are located.
	Namespace string
	// DiskName is the name of an existing VirtualDisk to attach.
	DiskName string
}

VirtualDiskReattachmentConfig holds configuration for reattaching an existing virtual disk to a VM.

type VolumeSnapshotClassConfig

type VolumeSnapshotClassConfig struct {
	Name           string
	Driver         string
	DeletionPolicy string // "Delete" or "Retain"
	Parameters     map[string]string
	MakeDefault    bool
}

Jump to

Keyboard shortcuts

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