Documentation
¶
Overview ¶
Package state provides cluster state discovery functions. TODO: This is a temporary implementation. It will be refactored into a proper state management system in a future PR.
Index ¶
- Constants
- Variables
- func GetBlockNodeNamespace() (string, error)
- func ReadProvisionerVersionFromDisk() (string, error)
- type ActionHistory
- type BlockNodeState
- type ClusterNodeState
- type ClusterState
- type HardwareState
- type HelmReleaseInfo
- type HelmReleaseSchemaV2Migration
- func (m *HelmReleaseSchemaV2Migration) Applies(_ *migration.Context) (bool, error)
- func (m *HelmReleaseSchemaV2Migration) Description() string
- func (m *HelmReleaseSchemaV2Migration) Execute(_ context.Context, _ *migration.Context) error
- func (m *HelmReleaseSchemaV2Migration) ID() string
- func (m *HelmReleaseSchemaV2Migration) Rollback(_ context.Context, _ *migration.Context) error
- type MachineState
- type Manager
- type ManagerOption
- type Persister
- type ProvisionerInfo
- type Reader
- type SoftwareState
- type State
- type StateRecord
- type UnifiedStateMigration
- func (m *UnifiedStateMigration) Applies(mctx *migration.Context) (bool, error)
- func (m *UnifiedStateMigration) Description() string
- func (m *UnifiedStateMigration) Execute(ctx context.Context, mctx *migration.Context) error
- func (m *UnifiedStateMigration) ID() string
- func (m *UnifiedStateMigration) Rollback(ctx context.Context, mctx *migration.Context) error
- type Writer
Constants ¶
const (
// BlockNodeChartName is the chart name used to identify block node installations
BlockNodeChartName = "block-node-server"
)
const ModelVersion = "v2" // State model version (from v0.14.0) — increment on breaking changes requiring migration
const StateFileName = "state.yaml"
Variables ¶
var ( ErrNamespace = errorx.NewNamespace("state") NotFoundError = ErrNamespace.NewType("not_found", errorx.NotFound()) )
Functions ¶
func GetBlockNodeNamespace ¶ added in v0.9.0
GetBlockNodeNamespace discovers the namespace where block node is installed by querying Helm releases and matching the chart name. Returns the namespace if found, empty string if not installed, or an error if discovery failed.
func ReadProvisionerVersionFromDisk ¶ added in v0.14.0
ReadProvisionerVersionFromDisk extracts the provisioner version from the on-disk state file without loading the full state into memory. Returns an empty string when no state file exists.
Types ¶
type ActionHistory ¶ added in v0.12.0
type ActionHistory struct {
Intent models.Intent `yaml:"intent" json:"intent"` // e.g. "weaver block node init"
Inputs any `yaml:"inputs" json:"inputs"` // inputs used for this intent; any marshallable value is accepted (e.g. models.UserInputs[T])
Timestamp htime.Time `yaml:"timestamp" json:"timestamp"`
}
type BlockNodeState ¶ added in v0.12.0
type BlockNodeState struct {
ReleaseInfo HelmReleaseInfo `yaml:",inline" json:",inline"`
Storage models.BlockNodeStorage `yaml:"storage" json:"storage"`
LastSync htime.Time `yaml:"lastSync,omitempty" json:"lastSync,omitempty"` // last time state was reconciled
}
func NewBlockNodeState ¶ added in v0.12.0
func NewBlockNodeState() BlockNodeState
func (*BlockNodeState) Clone ¶ added in v0.12.0
func (b *BlockNodeState) Clone() (*BlockNodeState, error)
Clone creates a deep copy of BlockNodeState
func (*BlockNodeState) Equal ¶ added in v0.12.0
func (b *BlockNodeState) Equal(other BlockNodeState) bool
Equal returns true if two BlockNodeState values are equal, ignoring LastSync.
type ClusterNodeState ¶ added in v0.12.0
type ClusterNodeState struct {
Name string `yaml:"name" json:"name"`
Role string `yaml:"role" json:"role"` // e.g. "master", "worker"
Ready bool `yaml:"ready" json:"ready"`
KubeletVer string `yaml:"kubeletVersion" json:"kubeletVersion"`
Labels models.StringMap `yaml:"labels,omitempty" json:"labels,omitempty"`
Annotations models.StringMap `yaml:"annotations,omitempty" json:"annotations,omitempty"`
LastSync htime.Time `yaml:"lastSync,omitempty" json:"lastSync,omitempty"` // last time state was reconciled
}
ClusterNodeState represents a single Kubernetes node summary.
func (*ClusterNodeState) Clone ¶ added in v0.12.0
func (c *ClusterNodeState) Clone() (*ClusterNodeState, error)
Clone creates a deep copy of ClusterNodeState
func (*ClusterNodeState) Equal ¶ added in v0.12.0
func (c *ClusterNodeState) Equal(other ClusterNodeState) bool
Equal returns true if two ClusterNodeState values are equal, ignoring LastSync.
type ClusterState ¶ added in v0.12.0
type ClusterState struct {
models.ClusterInfo
Created bool `yaml:"created" json:"created"` // whether the cluster was created by the provisioner
LastSync htime.Time `yaml:"lastSync,omitempty" json:"lastSync,omitempty"` // last time state was reconciled
}
ClusterState represents the persisted state of a Kubernetes cluster.
func NewClusterState ¶ added in v0.12.0
func NewClusterState() ClusterState
func (*ClusterState) Clone ¶ added in v0.12.0
func (cs *ClusterState) Clone() (*ClusterState, error)
Clone creates a deep copy of ClusterState
func (*ClusterState) Equal ¶ added in v0.12.0
func (cs *ClusterState) Equal(other ClusterState) bool
Equal returns true if two ClusterState values are equal, ignoring LastSync.
func (*ClusterState) Initialize ¶ added in v0.12.0
func (cs *ClusterState) Initialize(clusterInfo *models.ClusterInfo)
type HardwareState ¶ added in v0.12.0
type HardwareState struct {
Type string `yaml:"type" json:"type"` // e.g. "CPU", "RAM", "Disk"
Info string `yaml:"info" json:"info"` // e.g. "Intel i7", "16GB", "1TB SSD"
Count int `yaml:"count,omitempty" json:"count,omitempty"` // e.g. number of CPUs
Size string `yaml:"size,omitempty" json:"size,omitempty"` // e.g. size for RAM or Disk
Metadata models.StringMap `yaml:"metadata,omitempty" json:"metadata,omitempty"`
LastSync htime.Time `yaml:"lastSync,omitempty" json:"lastSync,omitempty"` // last time state was reconciled
}
func (*HardwareState) Clone ¶ added in v0.12.0
func (s *HardwareState) Clone() (*HardwareState, error)
func (*HardwareState) Equal ¶ added in v0.12.0
func (s *HardwareState) Equal(other HardwareState) bool
Equal returns true if two HardwareState values are equal, ignoring LastSync.
type HelmReleaseInfo ¶ added in v0.12.0
type HelmReleaseInfo struct {
Name string `yaml:"name" json:"name"`
ChartVersion string `yaml:"version" json:"version"` // Helm chart version; yaml key "version" preserved for on-disk compatibility
AppVersion string `yaml:"appVersion" json:"appVersion"` // version of the application packaged inside the chart (Metadata.AppVersion)
Namespace string `yaml:"namespace" json:"namespace"`
ChartRef string `yaml:"chartRef" json:"chartRef"` // e.g. "oci://ghcr.io/hedera/solo-weaver-block-node" needs to match deployed chart
ChartName string `yaml:"chartName" json:"chartName"`
Status release.Status `yaml:"status,omitempty" json:"status,omitempty"` // current state of the release
// FirstDeployed is when the release was first deployed.
FirstDeployed htime.Time `yaml:"firstDeployed,omitempty" json:"first_deployed,omitempty"`
// LastDeployed is when the release was last deployed.
LastDeployed htime.Time `yaml:"lastDeployed,omitempty" json:"last_deployed,omitempty"`
// DeletedAt tracks when this release was deleted.
DeletedAt htime.Time `yaml:"deletedAt,omitempty" json:"deletedAt,omitempty"`
}
HelmReleaseInfo captures minimal status for a Helm release managed by the system.
Breaking change introduced in ModelVersion v2 (released with v0.14.0):
- yaml:"version" now stores the Helm chart version (was app version in v1).
- yaml:"appVersion" is new; stores the app version (was yaml:"version" in v1).
- yaml:"deletedAt" renamed from yaml:"deleted" in v1.
- yaml:"status" gained an explicit YAML tag (was JSON-only in v1).
func (*HelmReleaseInfo) Clone ¶ added in v0.12.0
func (h *HelmReleaseInfo) Clone() (*HelmReleaseInfo, error)
Clone creates a deep copy of HelmReleaseInfo
func (*HelmReleaseInfo) Equal ¶ added in v0.12.0
func (h *HelmReleaseInfo) Equal(other HelmReleaseInfo) bool
Equal returns true if two HelmReleaseInfo values are equal, ignoring time fields
type HelmReleaseSchemaV2Migration ¶ added in v0.14.0
type HelmReleaseSchemaV2Migration struct {
// contains filtered or unexported fields
}
HelmReleaseSchemaV2Migration migrates the HelmReleaseInfo field layout from ModelVersion "v1" to "v2".
func NewHelmReleaseSchemaV2Migration ¶ added in v0.14.0
func NewHelmReleaseSchemaV2Migration() *HelmReleaseSchemaV2Migration
NewHelmReleaseSchemaV2Migration returns a new HelmReleaseSchemaV2Migration.
func (*HelmReleaseSchemaV2Migration) Applies ¶ added in v0.14.0
func (m *HelmReleaseSchemaV2Migration) Applies(_ *migration.Context) (bool, error)
Applies returns true when the on-disk state file carries ModelVersion "v1".
func (*HelmReleaseSchemaV2Migration) Description ¶ added in v0.14.0
func (m *HelmReleaseSchemaV2Migration) Description() string
func (*HelmReleaseSchemaV2Migration) Execute ¶ added in v0.14.0
Execute transforms the on-disk state.yaml from v1 to v2 schema using raw yaml.Node manipulation and writes the result back atomically.
func (*HelmReleaseSchemaV2Migration) ID ¶ added in v0.14.0
func (m *HelmReleaseSchemaV2Migration) ID() string
type MachineState ¶ added in v0.12.0
type MachineState struct {
Software map[string]SoftwareState `yaml:"software" json:"software"`
Hardware map[string]HardwareState `yaml:"hardware" json:"hardware"` // e.g. CPU, RAM, Disk info
LastSync htime.Time `yaml:"lastSync,omitempty" json:"lastSync,omitempty"` // last time state was reconciled
}
func NewMachineState ¶ added in v0.12.0
func NewMachineState() MachineState
func (*MachineState) Clone ¶ added in v0.12.0
func (m *MachineState) Clone() (*MachineState, error)
Clone creates a deep copy of MachineState
func (*MachineState) Equal ¶ added in v0.12.0
func (m *MachineState) Equal(other MachineState) bool
Equal returns true if two MachineState values are equal, ignoring LastSync.
type Manager ¶
Manager defines the interface for managing the application state with IO operations. It is just a thin wrapper around State with added thread-safe disk persistence & refresh operations. However, the State itself is not thread-safe for mutations since State is a data model. It composes Reader, Writer and Persister so existing callers need no changes.
func NewStateManager ¶ added in v0.12.0
func NewStateManager(opts ...ManagerOption) (Manager, error)
NewStateManager creates a Manager with the provided options. Caller must call Refresh() to load the persisted state from disk before accessing the state.
type ManagerOption ¶ added in v0.12.0
type ManagerOption func(*stateManager) error
func WithFileManager ¶ added in v0.12.0
func WithFileManager(fm fsx.Manager) ManagerOption
func WithState ¶ added in v0.12.0
func WithState(s State) ManagerOption
func WithStateFile ¶ added in v0.12.0
func WithStateFile(path string) ManagerOption
type Persister ¶ added in v0.12.0
type Persister interface {
// Refresh reloads the persisted state from disk, overwriting in-memory state.
Refresh() error
// FileManager returns the underlying file-system abstraction.
FileManager() fsx.Manager
}
Persister groups lifecycle operations (load + save) that are needed at the composition root (cmd layer) but not inside domain logic.
type ProvisionerInfo ¶ added in v0.12.0
type Reader ¶ added in v0.12.0
type Reader interface {
// State returns a snapshot of the current in-memory state.
State() State
// HasPersistedState reports whether a state file already exists on disk.
HasPersistedState() (os.FileInfo, bool, error)
}
Reader is the read-only view of managed application state. Consumers that only need to inspect state (e.g. resolvers, reality checkers) should depend on this narrow interface rather than the full DefaultStateManager.
type SoftwareState ¶ added in v0.12.0
type SoftwareState struct {
Name string `yaml:"name" json:"name"`
Version string `yaml:"version" json:"version"`
Installed bool `yaml:"installed" json:"installed"`
Configured bool `yaml:"configured" json:"configured"`
Metadata models.StringMap `yaml:"metadata,omitempty" json:"metadata,omitempty"`
LastSync htime.Time `yaml:"lastSync,omitempty" json:"lastSync,omitempty"` // last time state was reconciled
}
func GetSoftwareState ¶ added in v0.12.0
func GetSoftwareState(s State, component string) SoftwareState
GetSoftwareState returns the SoftwareState for the given component name from the state. Returns a zero-value SoftwareState with Name set if the component is not present.
func (*SoftwareState) Clone ¶ added in v0.12.0
func (s *SoftwareState) Clone() (*SoftwareState, error)
Clone creates a deep copy of SoftwareState
func (*SoftwareState) Equal ¶ added in v0.12.0
func (s *SoftwareState) Equal(other SoftwareState) bool
Equal returns true if two SoftwareState values are equal, ignoring LastSync.
type State ¶ added in v0.12.0
type State struct {
// Envelope — excluded from hash; never add domain data here
Hash string `yaml:"hash,omitempty" json:"hash,omitempty"` // digest of StateRecord
HashAlgo string `yaml:"hashAlgo,omitempty" json:"hashAlgo,omitempty"` // algorithm used for Hash (e.g. "sha256")
StateFile string `yaml:"stateFile" json:"stateFile"` // path to the state file on disk
LastSync htime.Time `yaml:"lastSync,omitempty" json:"lastSync,omitempty"` // last time state was flushed to disk
// Domain content — serialised as a nested "state" object for readability.
// The named YAML/JSON tag does not affect Go field promotion: state.Version,
// state.MachineState, etc. all still resolve directly.
StateRecord `yaml:"state" json:"state"`
}
State is the on-disk envelope. Envelope fields (Hash, HashAlgo, StateFile, LastSync) are bookkeeping metadata that never participate in hashing.
StateRecord is serialised as a nested "state" object so the envelope/content split is immediately visible to anyone reading the YAML or JSON file:
hash: "e3b0c4..." hashAlgo: sha256 stateFile: /opt/solo/weaver/state/state.yaml lastSync: "2026-03-17T..." state: version: v2 machineState: ... clusterState: ... blockNodeState: ...
Go field promotion still applies — all StateRecord fields (Version, MachineState, …) are accessible directly as state.Version, state.MachineState, etc. without going through state.StateRecord.
func NewState ¶ added in v0.12.0
NewState creates a new State instance with default values It does not load any persisted state from disk.
func SetSoftwareState ¶ added in v0.12.0
func SetSoftwareState(s State, component string, sw SoftwareState) State
SetSoftwareState returns a copy of s with the given SoftwareState recorded under component. Callers must follow up with StateWriter.Set(updated).FlushState() to persist.
func (State) Hashable ¶ added in v0.12.0
func (s State) Hashable() StateRecord
Hashable returns a deep copy of the domain StateRecord with all reconciliation timestamps (LastSync) zeroed. This is the canonical input for hashing:
- Envelope fields (Hash, HashAlgo, StateFile, LastSync on State) are already excluded by returning only StateRecord.
- Sub-state LastSync fields are zeroed because they advance on every reconciliation cycle and do not represent meaningful provisioning changes.
Note: We don't want to use pointer receiver here because we don't need to modify the original state instance.
type StateRecord ¶ added in v0.12.0
type StateRecord struct {
Version string `yaml:"version" json:"version"`
ProvisionerState ProvisionerInfo `yaml:"provisioner" json:"provisioner"`
MachineState MachineState `yaml:"machineState" json:"machineState"`
ClusterState ClusterState `yaml:"clusterState" json:"clusterState"`
BlockNodeState BlockNodeState `yaml:"blockNodeState" json:"blockNodeState"`
LastAction ActionHistory `yaml:"lastAction,omitempty" json:"lastAction,omitempty"` // last action performed, used for tracking and debugging
}
StateRecord holds all provisioning domain data — the fields that participate in the content hash. Add new domain fields here, never directly to State.
Envelope fields (Hash, HashAlgo, StateFile, LastSync) live in State and are intentionally excluded from hashing because they are bookkeeping metadata, not provisioning state.
type UnifiedStateMigration ¶ added in v0.7.0
type UnifiedStateMigration struct {
// contains filtered or unexported fields
}
UnifiedStateMigration consolidates individual legacy state files into the unified state.yaml managed by DefaultStateManager.
func NewUnifiedStateMigration ¶ added in v0.7.0
func NewUnifiedStateMigration() *UnifiedStateMigration
NewUnifiedStateMigration creates a new unified state migration.
func (*UnifiedStateMigration) Applies ¶ added in v0.7.0
func (m *UnifiedStateMigration) Applies(mctx *migration.Context) (bool, error)
Applies returns true when legacy *.installed or *.configured files are present.
func (*UnifiedStateMigration) Description ¶ added in v0.7.0
func (m *UnifiedStateMigration) Description() string
func (*UnifiedStateMigration) Execute ¶ added in v0.7.0
Execute reads all legacy state files and merges them into the unified state via DefaultStateManager. The legacy files are removed on success.
func (*UnifiedStateMigration) ID ¶ added in v0.7.0
func (m *UnifiedStateMigration) ID() string
type Writer ¶ added in v0.12.0
type Writer interface {
// Set replaces the entire in-memory state and returns the Writer for chaining.
Set(s State) Writer
// AddActionHistory appends an entry to the pending action log and updates
// State.LastAction. Entries are flushed to disk on the next Flush() call.
// Returns the Writer for chaining.
AddActionHistory(entry ActionHistory) Writer
// FlushState persists the current state without flushing the action history.
FlushState() error
// FlushActionHistory persists only the pending action history to disk without flushing the full state.
FlushActionHistory() error
// FlushAll persists both state and action history
FlushAll() error
}
Writer is the mutation-only view of managed application state. Consumers that record side-effects (e.g. the BLL after a workflow run) should depend on this narrow interface so that their dependencies are explicit.
Set and AddActionHistory return Writer (not DefaultStateManager) so that callers depending only on Writer can chain calls without importing the full DefaultStateManager type.