state

package
v0.15.1 Latest Latest
Warning

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

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

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

View Source
const (
	// BlockNodeChartName is the chart name used to identify block node installations
	BlockNodeChartName = "block-node-server"
)
View Source
const ModelVersion = "v2" // State model version (from v0.14.0) — increment on breaking changes requiring migration
View Source
const StateFileName = "state.yaml"

Variables

View Source
var (
	ErrNamespace  = errorx.NewNamespace("state")
	NotFoundError = ErrNamespace.NewType("not_found", errorx.NotFound())
)

Functions

func GetBlockNodeNamespace added in v0.9.0

func GetBlockNodeNamespace() (string, error)

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

func ReadProvisionerVersionFromDisk() (string, error)

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

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 (*HelmReleaseSchemaV2Migration) Rollback added in v0.14.0

Rollback reverses the v1→v2 migration, restoring the v1 on-disk shape. Best-effort: intended for recovery scenarios only.

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

type Manager interface {
	Reader
	Writer
	Persister
}

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 ProvisionerInfo struct {
	Version    string `yaml:"version" json:"version"`
	Commit     string `yaml:"commit" json:"commit"`
	GoVersion  string `yaml:"goversion" json:"goversion"`
	Executable string `yaml:"executable" json:"executable"` // location of the executable
}

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

func NewState(stateFile string) State

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) Clone added in v0.12.0

func (s *State) Clone() (*State, error)

Clone creates a deep copy of State

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

func (*UnifiedStateMigration) Rollback added in v0.7.0

func (m *UnifiedStateMigration) Rollback(ctx context.Context, mctx *migration.Context) error

Rollback restores the legacy state files from the unified state.

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.

Jump to

Keyboard shortcuts

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