Documentation
¶
Index ¶
- Constants
- Variables
- func AvailablePresets() []string
- func BuildMigrationWorkflow(manager *Manager, profile, valuesFile string) (*automa.WorkflowBuilder, error)
- func IsKnownPreset(presetID string) bool
- func PluginListForPreset(presetID, chartVersion string) string
- func PluginsForVersion(chartVersion string) []string
- func PresetLabel(presetID string) string
- func ResolveStoragePaths(storage models.BlockNodeStorage, chartVersion string) (archivePath, livePath, logPath string, optionalPaths []string, err error)
- func ValidateStorageCompleteness(storage models.BlockNodeStorage, chartVersion string) error
- type Manager
- func (m *Manager) ClearStorageDirectory(dirPath string) error
- func (m *Manager) ComputeValuesFile(profile string, valuesFile string) (string, error)
- func (m *Manager) CreateNamespace(ctx context.Context, tempDir string) error
- func (m *Manager) CreateOptionalStorage(ctx context.Context, tempDir string, optStor OptionalStorage) error
- func (m *Manager) CreatePersistentVolumes(ctx context.Context, tempDir string) error
- func (m *Manager) DeleteAllPersistentVolumes(ctx context.Context) error
- func (m *Manager) DeleteHelmOwnedServices(ctx context.Context) error
- func (m *Manager) DeleteNamespace(ctx context.Context, tempDir string) error
- func (m *Manager) DeleteStatefulSetForUpgrade(ctx context.Context) error
- func (m *Manager) GetInstalledVersion() (string, error)
- func (m *Manager) GetReleaseValues() (map[string]interface{}, error)
- func (m *Manager) GetStoragePaths() (archivePath, livePath, logPath string, optionalPaths []string, err error)
- func (m *Manager) GetTargetVersion() string
- func (m *Manager) InstallChart(ctx context.Context, valuesFile string) (bool, error)
- func (m *Manager) ResetStorage(ctx context.Context) error
- func (m *Manager) ScaleStatefulSet(ctx context.Context, replicas int32) error
- func (m *Manager) SetupStorage(ctx context.Context) error
- func (m *Manager) UninstallChart(ctx context.Context) error
- func (m *Manager) UpgradeChart(ctx context.Context, valuesFile string, reuseValues bool) error
- func (m *Manager) VerifyExternalReachable(ctx context.Context) error
- func (m *Manager) WaitForPodReady(ctx context.Context) error
- func (m *Manager) WaitForPodsTerminated(ctx context.Context) error
- type OptionalStorage
- type StorageMigration
Constants ¶
const ( // PresetTier1LFH selects Local Full History storage (blocks stored on disk). PresetTier1LFH = "tier1-lfh" // PresetTier1RFH selects Remote Full History storage (blocks stored in cloud storage). PresetTier1RFH = "tier1-rfh" // PresetCustom indicates the operator selected a custom set of plugins. PresetCustom = "custom" )
Plugin preset IDs used by the --plugin-preset flag and TUI prompt.
Each preset maps to a fixed, ordered plugin list maintained here in lockstep with block-node chart releases. When the block-node team changes a preset's contents or adds/removes presets, this file must be updated in the same release cycle.
Adding a new BN version that changes plugin lists:
- Add a new blockNodePluginConfig entry to blockNodePluginHistory (in ascending MinVersion order).
- Populate Presets with ALL preset IDs (copy unchanged ones from the previous entry; update only the ones that changed).
- Populate AllPlugins with the full list for that version.
- Add tests in blocknode_plugins_test.go for the new version boundary.
- No changes to PluginListForPreset, PluginsForVersion, or any caller.
const ( // Kubernetes resources ResourceNameSuffix = "-block-node-server" PodLabelSelector = "app.kubernetes.io/name=block-node-server" // Template paths NamespacePath = "files/block-node/namespace.yaml" StorageConfigPath = "files/block-node/storage-config.yaml" OptionalStoragePath = "files/block-node/optional-storage.yaml" ValuesPath = "files/block-node/full-values.yaml" NanoValuesPath = "files/block-node/nano-values.yaml" // Timeouts PodReadyTimeoutSeconds = 300 ReachabilityProbeTimeoutSec = 60 )
const BlockNodeApplicationStateRequiredVersion = "0.37.0-0"
BlockNodeApplicationStateRequiredVersion is the chart version at which the applicationStateFacility volume first appears (introduced by hiero-ledger/hiero-block-node#3025). solo-weaver creates the PV/PVC and fires the upgrade-time storage migration at this boundary.
As of this PR, #3025 is on the upstream `main` branch but NOT cherry-picked to 0.36.x, so the volume first ships in 0.37.0. If upstream changes course and cherry-picks the volume into a 0.36.x release before 0.37.0 ships, bump this constant to that cherry-pick tag — no other structural change is needed.
The "-0" suffix is the lowest-possible prerelease per semver §11, so the boundary is satisfied by every prerelease of 0.37.0 (0.37.0-rc1, -rc2, …) as well as the final 0.37.0 tag. Without it, semver ranks `0.37.0-rc1 < 0.37.0` and release candidates would be wrongly excluded from the cutover. This is a comparison bound only — user-facing text (flag help, docs) should say "0.37.0".
const BlockNodePublicPort int64 = 40840
BlockNodePublicPort is the well-known TCP port the block-node gRPC service listens on. It's an ecosystem-wide contract (the chart defaults to it, every SDK and tool assumes it), so the reachability probe dials it directly instead of trying to look the port up by name on the Service — chart versions have used `http`, `grpc`, and other names for it, and matching any of those is more fragile than dialing the well-known number.
const BlockNodeVerificationRetirementVersion = "0.37.0-0"
BlockNodeVerificationRetirementVersion is the chart version at which the dedicated verification volume is removed from the Helm chart (also hiero-ledger/hiero-block-node#3025). Kept as a separate constant from BlockNodeApplicationStateRequiredVersion so a cherry-pick scenario that introduces the new volume before retiring the old one can be expressed by bumping only one of the two.
Carries the same "-0" prerelease floor as BlockNodeApplicationStateRequiredVersion so verification retires in lockstep across the 0.37.0 release candidates, not just the final tag.
const HelmOwnedServiceDeleteTimeout = 30 * time.Second
HelmOwnedServiceDeleteTimeout caps how long DeleteHelmOwnedServices waits for the API server to finalize deletion of the matched Services before failing the upgrade. Background propagation usually completes in <1s; the budget is generous enough to absorb a slow apiserver without masking a real stuck finalizer.
const SoloProvisionerStorageLabelSelector = "app.kubernetes.io/managed-by=solo-provisioner,app.kubernetes.io/component=block-node-storage"
SoloProvisionerStorageLabelSelector matches PVs/PVCs created by solo-provisioner's own block-node storage templates.
Variables ¶
var ( ReachabilityProbeDialTimeout = 10 * time.Second ReachabilityProbeRetryDelay = 2 * time.Second )
Reachability probe dial cadence. A single dial attempt uses ReachabilityProbeDialTimeout; failed attempts back off by ReachabilityProbeRetryDelay before retrying, until the overall ReachabilityProbeTimeoutSec budget is exhausted. The dial-timeout/back-off split gives MetalLB ARP convergence and Cilium reconciler latency time to settle without making the whole probe block on a single hung connection.
var AllBlockNodePlugins = blockNodePluginHistory[len(blockNodePluginHistory)-1].AllPlugins
AllBlockNodePlugins is the ordered list of available plugins for the current (latest) chart release. Use PluginsForVersion when the target chart version may be older.
Functions ¶
func AvailablePresets ¶ added in v0.17.0
func AvailablePresets() []string
AvailablePresets returns the ordered preset IDs for TUI display.
func BuildMigrationWorkflow ¶ added in v0.7.0
func BuildMigrationWorkflow(manager *Manager, profile, valuesFile string) (*automa.WorkflowBuilder, error)
BuildMigrationWorkflow returns an automa workflow for executing applicable migrations. Returns nil if no migrations are needed (installed version is empty or no applicable migrations).
The workflow structure is:
[migration-start] → [migration-<id>] → ... → [migration-upgrade-chart]
Each migration step creates its PV/PVC. The final upgrade step performs a single StatefulSet delete + Helm upgrade to the target version with all new storages included.
func IsKnownPreset ¶ added in v0.17.0
IsKnownPreset returns true when presetID is a recognised non-custom preset.
func PluginListForPreset ¶ added in v0.17.0
PluginListForPreset returns the canonical comma-separated plugin list for a named preset at the given chart version, or an empty string when the preset ID is not recognised. When chartVersion is empty, the current-default (latest) list is returned.
func PluginsForVersion ¶ added in v0.19.0
PluginsForVersion returns the ordered list of available plugins for the given chart version, for use in the TUI custom multi-select. When chartVersion is empty, the current-default (latest) list is returned. Always returns an independent copy.
func PresetLabel ¶ added in v0.17.0
PresetLabel returns the human-readable TUI label for a preset ID, or the preset ID itself when no label is registered.
func ResolveStoragePaths ¶ added in v0.17.0
func ResolveStoragePaths(storage models.BlockNodeStorage, chartVersion string) (archivePath, livePath, logPath string, optionalPaths []string, err error)
ResolveStoragePaths is the pure-logic counterpart of Manager.GetStoragePaths: it derives the effective archive/live/log/optional storage paths from a BlockNodeStorage config and a chart version, without requiring a Manager (and therefore without constructing fsx/helm/kube clients). Use this when you only need to canonicalize or compare paths.
func ValidateStorageCompleteness ¶ added in v0.15.0
func ValidateStorageCompleteness(storage models.BlockNodeStorage, chartVersion string) error
ValidateStorageCompleteness checks that enough storage paths are set to resolve all required paths for the given chart version. Either basePath must be set (to derive missing paths) or all required individual paths must be explicit. This includes core paths (archive, live, log) and version-dependent optional paths (verification, plugins, application-state).
Types ¶
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager handles block node setup and management operations. Methods are grouped by concern across sibling files:
- storage.go — directory setup, PV/PVC lifecycle, path resolution
- chart.go — Helm install/upgrade/uninstall, StatefulSet and pod lifecycle, helm-owned Service teardown
- values.go — Helm values file computation and YAML injection helpers
- reachability.go — post-upgrade external-reachability probe
func NewManager ¶
func NewManager(blockConfig models.BlockNodeInputs) (*Manager, error)
NewManager creates a new block node manager
func (*Manager) ClearStorageDirectory ¶ added in v0.8.0
ClearStorageDirectory removes all files and subdirectories from a storage directory while preserving the directory itself.
func (*Manager) ComputeValuesFile ¶
ComputeValuesFile generates the values file for helm installation based on profile and version. It writes the result to a temp file and returns the path.
The profile's embedded base template is always rendered first; when an operator --values file is provided, it is deep-merged on top of the base (operator keys win on conflict) using the same semantics as `helm install -f`. This preserves base defaults such as service.type: LoadBalancer, blockNode.config, initContainers, and persistence wiring that an operator file would otherwise drop by replacing the base entirely.
Persistence overrides are then applied unconditionally so that weaver-managed PVCs are referenced (create: false + existingClaim) regardless of what the operator file specified. Retention thresholds and plugin/service-annotation injections follow.
NOTE: Defense-in-depth path validation is applied even though the CLI layer also validates.
func (*Manager) CreateNamespace ¶
CreateNamespace creates the block-node namespace if it doesn't exist. ApplyManifest is idempotent so this is safe to call on every install.
func (*Manager) CreateOptionalStorage ¶ added in v0.10.0
func (m *Manager) CreateOptionalStorage(ctx context.Context, tempDir string, optStor OptionalStorage) error
CreateOptionalStorage creates a single optional PV/PVC using the unified template. Used during migration when other PVs already exist.
func (*Manager) CreatePersistentVolumes ¶
CreatePersistentVolumes creates PVs and PVCs from the storage config
func (*Manager) DeleteAllPersistentVolumes ¶ added in v0.17.0
DeleteAllPersistentVolumes deletes every block-node PV and PVC that belongs to this release: both solo-provisioner-managed (from our templates) and Helm-managed (if the chart's persistence.create override is ever turned on). PVs are cluster-scoped so the returned list is additionally filtered by spec.claimRef.namespace. Missing resources are silently ignored.
func (*Manager) DeleteHelmOwnedServices ¶ added in v0.18.1
DeleteHelmOwnedServices deletes every Service in the block-node namespace that belongs to the current Helm release (labels `app.kubernetes.io/managed-by=Helm` and `app.kubernetes.io/instance=<release>`) and waits for the API server to confirm their removal.
Run this immediately before `helm upgrade`. Helm's reconciliation phase will recreate the Services as part of the upgrade, which forces Cilium's eBPF service reconciler through a CREATE event rather than the `spec.type` transition UPDATE event it silently drops (see issue #619 / #644). Helm's 3-way merge handles the missing-from-cluster-but-in-last-release case transparently.
A no-match is a successful no-op: a prior failed upgrade may have already removed the Services, and the headless / LB Services may genuinely not exist on certain chart variants. The caller (the saga step) is responsible for the post-upgrade reachability probe that turns any remaining failure mode into a loud workflow error.
func (*Manager) DeleteNamespace ¶
DeleteNamespace deletes the block-node namespace
func (*Manager) DeleteStatefulSetForUpgrade ¶ added in v0.10.0
DeleteStatefulSetForUpgrade deletes the block node StatefulSet using orphan cascading and waits for it to be fully removed from the API server. This is required before any Helm upgrade that changes volumeClaimTemplates, since Kubernetes forbids in-place updates. Returns nil if the StatefulSet does not exist.
func (*Manager) GetInstalledVersion ¶ added in v0.7.0
GetInstalledVersion returns the currently installed Block Node chart version. Returns empty string if not installed.
func (*Manager) GetReleaseValues ¶ added in v0.7.0
GetReleaseValues returns the user-supplied values from the currently installed release. Returns nil if not installed or if no user values were supplied.
func (*Manager) GetStoragePaths ¶ added in v0.6.0
func (m *Manager) GetStoragePaths() (archivePath, livePath, logPath string, optionalPaths []string, err error)
GetStoragePaths returns the computed storage paths based on configuration. If individual paths are specified, they are used; otherwise, paths are derived from basePath. All paths are validated using sanity checks. optionalPaths contains the paths for applicable optional storages (in registry order).
func (*Manager) GetTargetVersion ¶ added in v0.10.0
GetTargetVersion returns the configured target version for block node.
func (*Manager) InstallChart ¶
InstallChart installs the block node helm chart
func (*Manager) ResetStorage ¶ added in v0.8.0
ResetStorage clears all block node storage directories.
func (*Manager) ScaleStatefulSet ¶ added in v0.8.0
ScaleStatefulSet scales the block node statefulset to the specified number of replicas
func (*Manager) SetupStorage ¶
SetupStorage creates the required directories for block node storage
func (*Manager) UninstallChart ¶
UninstallChart uninstalls the block node helm chart
func (*Manager) UpgradeChart ¶ added in v0.5.0
UpgradeChart upgrades the block node helm chart. When reuseValues is true and no custom values file is provided, the existing release values are reused unchanged (following Helm CLI convention).
func (*Manager) VerifyExternalReachable ¶ added in v0.18.0
VerifyExternalReachable opens a TCP connection from the host running solo-provisioner to the block-node LoadBalancer Service's external endpoint and closes it immediately. No-ops when LoadBalancerEnabled is false (e.g. local profile, no MetalLB pool).
The probe converts the silent failure mode described in issue #619 — pod healthy, kubectl happy, traffic blackholed — into an immediate workflow error regardless of whether the cause is Cilium, MetalLB, the chart, or a firewall.
Traffic from this process to the LB IP traverses the same MetalLB-ARP + Cilium-DNAT path that any external client would hit, so a failure here is the same failure an outside caller would experience.
func (*Manager) WaitForPodReady ¶
WaitForPodReady waits for the block node pod to be ready
type OptionalStorage ¶ added in v0.10.0
type OptionalStorage struct {
// Name is the kebab-case identifier used in logs, directory names, and CLI
// flag names (e.g., "verification", "plugins", "application-state"). It is
// NOT necessarily the Helm persistence key — see PersistenceKey, since some
// chart keys are camelCase (application-state → applicationState).
Name string
// PersistenceKey is the key under blockNode.persistence in the chart values
// that wires this volume's PVC. Set it only when the chart key differs from
// Name (application-state's chart key is camelCase "applicationState");
// callers fall back to Name when it is empty, which covers the common case
// where the chart key matches the kebab-case name (verification, plugins).
PersistenceKey string
// MinVersion is the minimum Block Node version at which solo-weaver
// provisions the PV/PVC. Drives `CreatePersistentVolumes` (install path)
// and the registry filter used by `GetApplicableOptionalStorages` /
// `RequiredByVersion`.
MinVersion string
// MaxVersion, when non-empty, is the exclusive upper bound: the storage is
// required only while target < MaxVersion. Use this to retire a storage that
// has been removed from the chart in a newer version. Empty means unbounded
// above.
MaxVersion string
// PVName is the PersistentVolume resource name (e.g., "verification-storage-pv").
PVName string
// PVCName is the PersistentVolumeClaim resource name (e.g., "verification-storage-pvc").
PVCName string
// DirName is the subdirectory name under basePath (e.g., "verification").
DirName string
// GetPath returns the models.red path from the storage models.
GetPath func(s *models.BlockNodeStorage) string
// SetPath sets the path in the storage models.
SetPath func(s *models.BlockNodeStorage, p string)
// GetSize returns the models.red size from the storage models.
GetSize func(s *models.BlockNodeStorage) string
}
OptionalStorage describes an optional storage volume that is conditionally required based on the target Block Node chart version.
func GetApplicableOptionalStorages ¶ added in v0.10.0
func GetApplicableOptionalStorages(targetVersion string) []OptionalStorage
GetApplicableOptionalStorages returns the subset of optional storages that are required by the given target version. Use this for PV/PVC provisioning decisions (CreatePersistentVolumes, migration registration) AND helm-values rendering (ComputeValuesFile, injectPersistenceOverrides) — since the chart-mount and provisioning boundaries are the same.
func GetOptionalStorages ¶ added in v0.10.0
func GetOptionalStorages() []OptionalStorage
GetOptionalStorages returns the full list of registered optional storages.
func (*OptionalStorage) RequiredByVersion ¶ added in v0.10.0
func (o *OptionalStorage) RequiredByVersion(targetVersion string) bool
RequiredByVersion returns true if the given target version requires this optional storage. The range is [MinVersion, MaxVersion) — MaxVersion empty means unbounded above.
type StorageMigration ¶ added in v0.10.0
type StorageMigration struct {
migration.VersionMigration
// contains filtered or unexported fields
}
StorageMigration handles the breaking change pattern where a new storage PV/PVC is added to the Block Node StatefulSet. It is parameterized by the OptionalStorage descriptor, allowing a single implementation to serve all storage migrations.
Execute only creates the storage directory and PV/PVC — no Helm upgrade is performed. The single upgrade is appended as a final workflow step by BuildMigrationWorkflow.
func NewApplicationStateMigration ¶ added in v0.21.0
func NewApplicationStateMigration() *StorageMigration
NewApplicationStateMigration creates the application-state storage migration.
At BlockNodeApplicationStateRequiredVersion (0.37.0) the Helm chart starts mounting the applicationStateFacility volume (hiero-ledger/hiero-block-node#3025) and stops mounting the verification volume in lockstep. The migration creates the new PV/PVC; existing verification PV/PVC objects are left in place — the chart no longer references them so they become orphan state, and cleanup is a manual operator step.
func NewPluginsStorageMigration ¶ added in v0.10.0
func NewPluginsStorageMigration() *StorageMigration
NewPluginsStorageMigration creates the plugins storage migration.
func NewStorageMigration ¶ added in v0.10.0
func NewStorageMigration(optStorage OptionalStorage) *StorageMigration
NewStorageMigration creates a new storage migration for the given optional storage entry.
func NewVerificationStorageMigration ¶ added in v0.7.0
func NewVerificationStorageMigration() *StorageMigration
NewVerificationStorageMigration creates the verification storage migration.
func (*StorageMigration) Applies ¶ added in v0.21.0
func (m *StorageMigration) Applies(mctx *migration.Context) (bool, error)
Applies extends VersionMigration.Applies with a MaxVersion guard: a storage that has been retired in newer chart versions must not be re-created when an operator skips across the retirement boundary. Concretely, if a cluster installed at 0.25.0 upgrades directly to >=0.36.0, the generic VersionMigration check (installed < 0.26.2 && target >= 0.26.2) reports the verification migration as applicable, but at target=0.36.0 verification has been retired (MaxVersion=0.36.0) and creating its PV/PVC would leave an orphan resource. The OptionalStorage's RequiredByVersion captures the [MinVersion, MaxVersion) range; AND-ing it in keeps the migration registry version-correct without duplicating the bound on every individual migration.