Documentation
¶
Index ¶
- Variables
- func BackupConfigFile(dataDir, fileName string) error
- func BackupKey(dataDir string) error
- func BuildResultMessage(result *models.CommandResult) *models.Message
- func DetectPublicIP(ctx context.Context) string
- func EnsureDataDirs(dataDir string) error
- func ExportKey(dataDir string) (string, error)
- func ExtractBLSPublicKey(configDir string) (string, error)
- func FindAvailablePort(startPort int) int
- func IsPortAvailable(port int) bool
- func ReadConfigFile(dataDir, fileName string) (string, error)
- func RemoveDataDirectory(dataDir string) error
- func ResetDBFastBootstrap(ctx context.Context, docker *DockerClient, req *models.ResetDBRequest, ...) error
- func RestoreConfigBackup(dataDir, backupName string) error
- func RestoreConfigVersion(dataDir, backupName string) error
- func RestoreDB(ctx context.Context, docker *DockerClient, req *models.RestoreDBRequest, ...) error
- func RollbackBinary(backupPath string) error
- func SHA256Hex(data []byte) string
- func ValidateCommand(action string, containerName string) error
- func WriteConfigFile(dataDir, fileName, content string) error
- type Agent
- func (a *Agent) BuildAgentInfo(publicIP string) *models.AgentInfo
- func (a *Agent) BuildDiscoveryMessage(report *models.DiscoveryReport) *models.Message
- func (a *Agent) BuildInfoMessage(publicIP string) *models.Message
- func (a *Agent) Config() *Config
- func (a *Agent) IsRegistered() bool
- func (a *Agent) LoadConfig() error
- func (a *Agent) Register(dashboardURL, token string) error
- func (a *Agent) RunDiscovery(dockerSocket string) *models.DiscoveryReport
- func (a *Agent) SaveConfig() error
- func (a *Agent) TLSConfig() (*tls.Config, error)
- type BenchmarkProgress
- type BenchmarkResult
- type BenchmarkSection
- type CommandSpec
- type Config
- type ConfigDiffItem
- type ConfigFile
- type ConfigPreview
- type ConfigUpgradeResult
- type ConfigVersionBackup
- type ContainerConfig
- type DBResetProgressFunc
- type DBRestoreProgressFunc
- type DiscoveredNode
- type DockerClient
- func (d *DockerClient) CreateContainer(ctx context.Context, cfg *ContainerConfig) (string, error)
- func (d *DockerClient) DiscoverNodes(ctx context.Context) ([]DiscoveredNode, error)
- func (d *DockerClient) FetchLogs(ctx context.Context, containerName string, tail int, since int64) ([]LogLine, error)
- func (d *DockerClient) GenerateKey(ctx context.Context, dataDir, imageTag string) (*KeyInfo, error)
- func (d *DockerClient) GetContainerStatus(ctx context.Context, containerName string) (string, error)
- func (d *DockerClient) InspectContainer(ctx context.Context, containerID string) (*containerJSON, error)
- func (d *DockerClient) ListKleverContainers(ctx context.Context) ([]string, error)
- func (d *DockerClient) ListKleverImages(ctx context.Context) ([]ImageInfo, error)
- func (d *DockerClient) ListLocalImages(ctx context.Context) ([]string, error)
- func (d *DockerClient) PullImage(ctx context.Context, image string) error
- func (d *DockerClient) PullImageWithProgress(ctx context.Context, image string, onProgress func(status string)) error
- func (d *DockerClient) RecreateWithStartInEpoch(ctx context.Context, containerName string) error
- func (d *DockerClient) RecreateWithoutStartInEpoch(ctx context.Context, containerName string) error
- func (d *DockerClient) RemoveContainer(ctx context.Context, containerName string, force bool) error
- func (d *DockerClient) RemoveImage(ctx context.Context, imageID string) error
- func (d *DockerClient) RestartContainer(ctx context.Context, containerName string, timeoutSec int) error
- func (d *DockerClient) RunBenchmark(ctx context.Context, onProgress BenchmarkProgress) (*BenchmarkResult, error)
- func (d *DockerClient) StartContainer(ctx context.Context, containerName string) error
- func (d *DockerClient) StopContainer(ctx context.Context, containerName string, timeoutSec int) error
- func (d *DockerClient) StreamLogs(ctx context.Context, containerName string, since int64, onLine func(LogLine)) error
- func (d *DockerClient) UpgradeContainer(ctx context.Context, containerName, newTag string) (string, error)
- func (d *DockerClient) UpgradeContainerWithRollback(ctx context.Context, containerName, newTag string, ...) (string, error)
- type Executor
- type ImageInfo
- type KeyInfo
- type LogLine
- type LogStreamManager
- type MetricsCollector
- type NodeMetricsCollector
- func (c *NodeMetricsCollector) CollectAll(serverID string) ([]*models.NodeMetricsEvent, []*models.NodeNonceStallEvent)
- func (c *NodeMetricsCollector) CollectOne(nodeID, serverID string) (*models.NodeMetricsEvent, error)
- func (c *NodeMetricsCollector) PollInterval() time.Duration
- func (c *NodeMetricsCollector) RunPoller(ctx context.Context, serverID string, metricsCh chan<- *models.Message, ...)
- func (c *NodeMetricsCollector) UpdateNodes(report *models.DiscoveryReport)
- type NodeMetricsCollectorOption
- type ProgressFunc
- type ProvisionStep
- type Provisioner
- type UpdateResult
- type UpgradeProgress
Constants ¶
This section is empty.
Variables ¶
var AllowedCommands = map[string]CommandSpec{ "node.start": {Description: "Start a Klever node container", RequiresContainer: true}, "node.stop": {Description: "Stop a Klever node container", RequiresContainer: true}, "node.restart": {Description: "Restart a Klever node container", RequiresContainer: true}, "node.status": {Description: "Get status of a Klever node container", RequiresContainer: true}, "node.create": {Description: "Create a new Klever node container", RequiresContainer: false}, "node.remove": {Description: "Remove a Klever node container", RequiresContainer: true}, "node.upgrade": {Description: "Upgrade a Klever node to a new image tag", RequiresContainer: true}, "node.pull": {Description: "Pull a Docker image", RequiresContainer: false}, "node.provision": {Description: "Provision a new Klever node from scratch", RequiresContainer: false}, "node.restore-db": {Description: "Restore a node's chain DB from the official Klever backup", RequiresContainer: true}, "node.reset-db": {Description: "Delete a node's chain DB and re-bootstrap from the latest epoch", RequiresContainer: true}, "node.discovery": {Description: "Scan for existing Klever nodes", RequiresContainer: false}, "docker.images.list": {Description: "List local Klever Docker images", RequiresContainer: false}, "docker.images.remove": {Description: "Remove unused Klever Docker images", RequiresContainer: false}, "config.list": {Description: "List configuration files for a node", RequiresContainer: false}, "config.read": {Description: "Read a configuration file", RequiresContainer: false}, "config.write": {Description: "Write a configuration file (auto-backup)", RequiresContainer: false}, "config.backup": {Description: "Create a backup of a configuration file", RequiresContainer: false}, "config.backups": {Description: "List backups of a configuration file", RequiresContainer: false}, "config.restore": {Description: "Restore a configuration file from backup", RequiresContainer: false}, "config.upgrade": {Description: "Download and apply new Klever configs during upgrade", RequiresContainer: false}, "config.preview": {Description: "Compare current configs with the new Klever download (read-only)", RequiresContainer: false}, "config.version-backups": {Description: "List version-labeled config backups", RequiresContainer: false}, "config.version-restore": {Description: "Restore config from a version backup", RequiresContainer: false}, "node.logs": {Description: "Fetch historical logs from a container", RequiresContainer: true}, "key.info": {Description: "Get validator key info", RequiresContainer: false}, "key.generate": {Description: "Generate a new BLS key pair", RequiresContainer: false}, "key.import": {Description: "Import a validator key", RequiresContainer: false}, "key.export": {Description: "Export a validator key", RequiresContainer: false}, "key.backup": {Description: "Backup the validator key", RequiresContainer: false}, "key.backups": {Description: "List validator key backups", RequiresContainer: false}, "agent.update": {Description: "Update agent binary", RequiresContainer: false}, "agent.restart": {Description: "Restart the agent process", RequiresContainer: false}, "server.benchmark": {Description: "Run server hardware benchmark", RequiresContainer: false}, }
AllowedCommands defines the set of commands the agent will execute.
Functions ¶
func BackupConfigFile ¶
BackupConfigFile creates a timestamped backup of a configuration file.
func BuildResultMessage ¶
func BuildResultMessage(result *models.CommandResult) *models.Message
BuildResultMessage wraps a CommandResult in a Message envelope.
func DetectPublicIP ¶
DetectPublicIP queries external services to determine the agent's public IP. Returns empty string on failure (graceful degradation).
func EnsureDataDirs ¶
EnsureDataDirs creates the required data directory structure.
func ExtractBLSPublicKey ¶
ExtractBLSPublicKey reads a validatorKey.pem from the config directory and extracts the BLS public key (hex-encoded).
The PEM file contains the private key in a custom format used by Klever. The public key is extracted from the last 96 bytes of the decoded key data (BLS12-381 public key = 96 bytes).
func FindAvailablePort ¶
FindAvailablePort finds the next available port starting from startPort.
func IsPortAvailable ¶
IsPortAvailable checks if a TCP port is available on the host. "Available" here means nothing is currently accepting connections on it.
The bounded dial timeout matters: a firewalled black-hole port (SYN silently dropped, no RST) would block indefinitely without it, and provisioning's FindAvailablePort calls this in a 100-port loop.
func ReadConfigFile ¶
ReadConfigFile reads a configuration file's contents.
func RemoveDataDirectory ¶
RemoveDataDirectory removes the data directory for a node. Requires explicit confirmation to prevent accidental data loss.
func ResetDBFastBootstrap ¶ added in v0.3.85
func ResetDBFastBootstrap(ctx context.Context, docker *DockerClient, req *models.ResetDBRequest, onProgress DBResetProgressFunc) error
ResetDBFastBootstrap deletes a node's local chain DB and restarts it with --start-in-epoch so it re-bootstraps from the latest epoch. This is the deliberate opposite of RestoreDB (which downloads the full-history snapshot): here we throw the local DB away and let the node fetch a fresh, epoch-aligned state on its own. It is for operators who do NOT need archival history.
Only the db/ subtree is removed — config/, keys and validatorKey.pem are left untouched. The empty db/ is recreated with the container user's ownership (999:999) so the validator process can write into it; if the directory were left for Docker to create it would be owned by root and the node could not write to it.
func RestoreConfigBackup ¶
RestoreConfigBackup restores a config file from a backup.
func RestoreConfigVersion ¶
RestoreConfigVersion restores all config files from a version backup.
func RestoreDB ¶ added in v0.3.78
func RestoreDB(ctx context.Context, docker *DockerClient, req *models.RestoreDBRequest, onProgress DBRestoreProgressFunc) error
RestoreDB replaces a node's chain DB with the official Klever FullNode snapshot. Flow: preflight disk check -> stop node -> rotate old db aside (or delete if space is tight) -> stream-download + extract only the db/ entries -> fix permissions -> start node. On failure before the new DB is in place, the old DB is rolled back.
It streams the archive straight through gzip+tar (never staging the tens of GB on disk) and only extracts entries under db/, so a stray config/ in the archive can't clobber the node's existing configuration.
func RollbackBinary ¶
RollbackBinary restores the previous agent binary from backup.
func ValidateCommand ¶
ValidateCommand checks if a command action is allowed and parameters are valid. Returns an error describing why the command was rejected, or nil if valid.
func WriteConfigFile ¶
WriteConfigFile writes content to a configuration file, creating a backup first.
Types ¶
type Agent ¶
type Agent struct {
// contains filtered or unexported fields
}
Agent is the main agent process.
func (*Agent) BuildAgentInfo ¶
BuildAgentInfo creates the agent.info payload.
func (*Agent) BuildDiscoveryMessage ¶
func (a *Agent) BuildDiscoveryMessage(report *models.DiscoveryReport) *models.Message
BuildDiscoveryMessage creates a discovery report message.
func (*Agent) BuildInfoMessage ¶
BuildInfoMessage creates a complete agent.info message.
func (*Agent) IsRegistered ¶
IsRegistered returns true if the agent has a stored certificate.
func (*Agent) LoadConfig ¶
LoadConfig loads the agent configuration from disk.
func (*Agent) RunDiscovery ¶
func (a *Agent) RunDiscovery(dockerSocket string) *models.DiscoveryReport
RunDiscovery scans the server for Klever nodes and returns a discovery report.
func (*Agent) SaveConfig ¶
SaveConfig saves the agent configuration to disk.
func (*Agent) TLSConfig ¶
TLSConfig builds a tls.Config using the agent's mTLS credentials. The returned config trusts the dashboard CA and presents the agent's client certificate, AND verifies the dashboard's server certificate against the CA the agent stored at registration time.
The CA we already load was previously ignored: InsecureSkipVerify was set to true on the assumption that mTLS alone was sufficient. It is not — mTLS only ensures the dashboard authenticates the agent, not the reverse. Without verifying the dashboard's cert against the stored CA, an attacker who has stolen any client cert can intercept the connection.
ServerName is pinned to "localhost" because crypto.DashboardTLSConfig issues the dashboard's server certificate with DNSNames: ["localhost"] regardless of the host/IP the agent dials. The cert is still signed by the trusted CA, so verifying against that SAN proves authenticity.
type BenchmarkProgress ¶ added in v0.3.54
BenchmarkProgress is called during benchmark execution to report progress.
type BenchmarkResult ¶ added in v0.3.49
type BenchmarkResult struct {
Timestamp int64 `json:"timestamp"`
Score int `json:"score"` // 0-1000
MaxScore int `json:"max_score"` // 1000
Grade string `json:"grade"` // "A", "B", "C", etc.
Verdict string `json:"verdict"` // "Excellent — production-ready..."
Sections []BenchmarkSection `json:"sections"`
RawOutput string `json:"raw_output"`
}
BenchmarkResult holds the parsed results of a server hardware benchmark.
type BenchmarkSection ¶ added in v0.3.51
type BenchmarkSection struct {
Name string `json:"name"` // "GOROUTINE SCALABILITY", "DISK I/O", etc.
Status string `json:"status"` // "PASS", "WARN", "FAIL"
Score int `json:"score"` // section score
MaxScore int `json:"max_score"` // section max
Percent float64 `json:"percent"` // score percentage
}
BenchmarkSection is one category in the benchmark report.
type CommandSpec ¶
CommandSpec defines constraints for a whitelisted command.
type Config ¶
type Config struct {
ServerID string `json:"server_id"`
DashboardURL string `json:"dashboard_url"`
CertPEM string `json:"cert_pem"`
KeyPEM string `json:"key_pem"`
CACertPEM string `json:"ca_cert_pem"`
AgentPort int `json:"agent_port,omitempty"`
}
Config holds the agent's persistent configuration.
type ConfigDiffItem ¶ added in v0.3.88
type ConfigDiffItem struct {
ID string `json:"id"` // "<file>::<key>", stable between preview and upgrade
File string `json:"file"`
Key string `json:"key"`
Kind string `json:"kind"`
Mine string `json:"mine"`
New string `json:"new"`
}
ConfigDiffItem is one difference between the node's current config and the freshly downloaded one that the operator can decide on.
type ConfigFile ¶
type ConfigFile struct {
Name string `json:"name"`
Path string `json:"path"`
Size int64 `json:"size"`
Modified int64 `json:"modified"` // Unix timestamp
}
ConfigFile represents a configuration file's metadata.
func ListConfigBackups ¶
func ListConfigBackups(dataDir, fileName string) ([]ConfigFile, error)
ListConfigBackups lists backup files for a specific config file.
func ListConfigFiles ¶
func ListConfigFiles(dataDir string) ([]ConfigFile, error)
ListConfigFiles lists configuration files in a node's config directory.
func ListKeyBackups ¶
func ListKeyBackups(dataDir string) ([]ConfigFile, error)
ListKeyBackups lists backup key files.
type ConfigPreview ¶ added in v0.3.88
type ConfigPreview struct {
Items []ConfigDiffItem `json:"items"`
AddedByFile map[string]int `json:"added_by_file,omitempty"`
DownloadSource string `json:"download_source"`
}
ConfigPreview is the result of comparing current configs with the new download.
func PreviewConfigUpgrade ¶ added in v0.3.88
func PreviewConfigUpgrade(ctx context.Context, dataDir, network string) (*ConfigPreview, error)
PreviewConfigUpgrade downloads the new configs and compares them with the node's current ones without touching anything, so the operator can decide which local values to keep before UpgradeConfigs runs.
type ConfigUpgradeResult ¶
type ConfigUpgradeResult struct {
BackupDir string `json:"backup_dir"`
BackupVersion string `json:"backup_version"`
ReplacedFiles []string `json:"replaced_files"`
MergedFiles []string `json:"merged_files"`
SkippedFiles []string `json:"skipped_files,omitempty"`
DownloadSource string `json:"download_source"` // "primary" or "fallback"
// KeptValues lists the operator's local values written back over the new
// defaults; UnappliedKeeps lists requested ones that no longer matched.
KeptValues []string `json:"kept_values,omitempty"`
UnappliedKeeps []string `json:"unapplied_keeps,omitempty"`
}
ConfigUpgradeResult describes what happened during a config upgrade.
func UpgradeConfigs ¶
func UpgradeConfigs(ctx context.Context, dataDir, network, versionLabel string, keep []string) (*ConfigUpgradeResult, error)
UpgradeConfigs downloads new config files and replaces system configs while preserving user-specific values in config.toml.
Steps:
- Backup all current configs into a version-labeled directory
- Download new configs (primary: Klever backup server, fallback: GitHub)
- Replace system configs (yaml, json) with the download, writing back the local values the operator chose to keep (ids from PreviewConfigUpgrade)
- Merge config.toml: new defaults + preserved user values
type ConfigVersionBackup ¶
type ConfigVersionBackup struct {
Name string `json:"name"`
CreatedAt int64 `json:"created_at"`
FileCount int `json:"file_count"`
}
ConfigVersionBackup represents a version-labeled config backup directory.
func ListConfigVersionBackups ¶
func ListConfigVersionBackups(dataDir string) ([]ConfigVersionBackup, error)
ListConfigVersionBackups lists all version-labeled config backups.
type ContainerConfig ¶
type ContainerConfig struct {
Name string `json:"name"` // Container name, e.g. "klever-node1"
ImageTag string `json:"image_tag"` // e.g. "v0.60.0" or "latest"
DataDir string `json:"data_dir"` // Host data directory
RestAPIPort int `json:"rest_api_port"` // REST API port
DisplayName string `json:"display_name"` // Node display name
RedundancyLevel int `json:"redundancy_level"` // 0 = active, 1 = fallback
StartInEpoch bool `json:"start_in_epoch"` // add --start-in-epoch (fast bootstrap)
}
ContainerConfig defines parameters for creating a Klever node container.
type DBResetProgressFunc ¶ added in v0.3.85
type DBResetProgressFunc func(*models.DBResetProgress)
DBResetProgressFunc receives status updates during a fast-reset.
type DBRestoreProgressFunc ¶ added in v0.3.78
type DBRestoreProgressFunc func(p *models.DBRestoreProgress)
DBRestoreProgressFunc receives progress updates during a restore.
type DiscoveredNode ¶
type DiscoveredNode struct {
ContainerID string `json:"container_id"`
ContainerName string `json:"container_name"`
Status string `json:"status"` // "running" or "stopped"
RestAPIPort int `json:"rest_api_port"`
DisplayName string `json:"display_name,omitempty"`
RedundancyLevel int `json:"redundancy_level"`
DockerImageTag string `json:"docker_image_tag,omitempty"`
DataDirectory string `json:"data_directory,omitempty"`
ConfigDirectory string `json:"config_directory,omitempty"`
BLSPublicKey string `json:"bls_public_key,omitempty"`
CPUPercent float64 `json:"cpu_percent"`
MemUsed uint64 `json:"mem_used"`
MemLimit uint64 `json:"mem_limit"`
MemPercent float64 `json:"mem_percent"`
}
DiscoveredNode holds the information extracted from a running Klever container.
type DockerClient ¶
type DockerClient struct {
// contains filtered or unexported fields
}
DockerClient talks to the Docker Engine API via Unix socket.
func NewDockerClient ¶
func NewDockerClient(socketPath string) *DockerClient
NewDockerClient creates a client connected to the Docker socket.
func (*DockerClient) CreateContainer ¶
func (d *DockerClient) CreateContainer(ctx context.Context, cfg *ContainerConfig) (string, error)
CreateContainer creates a new Klever node container.
func (*DockerClient) DiscoverNodes ¶
func (d *DockerClient) DiscoverNodes(ctx context.Context) ([]DiscoveredNode, error)
DiscoverNodes scans Docker for all Klever containers and extracts their configuration.
func (*DockerClient) FetchLogs ¶
func (d *DockerClient) FetchLogs(ctx context.Context, containerName string, tail int, since int64) ([]LogLine, error)
FetchLogs retrieves historical logs from a container.
func (*DockerClient) GenerateKey ¶
GenerateKey runs the klever-go keygenerator to create a new BLS key pair.
func (*DockerClient) GetContainerStatus ¶
func (d *DockerClient) GetContainerStatus(ctx context.Context, containerName string) (string, error)
GetContainerStatus returns the current status of a container ("running", "exited", etc.).
func (*DockerClient) InspectContainer ¶
func (d *DockerClient) InspectContainer(ctx context.Context, containerID string) (*containerJSON, error)
InspectContainer returns detailed information about a container.
func (*DockerClient) ListKleverContainers ¶
func (d *DockerClient) ListKleverContainers(ctx context.Context) ([]string, error)
ListKleverContainers returns IDs of all containers using the klever-go image. We list ALL containers and filter by image name ourselves, because Docker's "ancestor" filter matches by image ID which can miss containers created from a different pull/digest of the same image name. When Docker returns a sha256 digest instead of the image name (happens when the original tag is removed after pulling a newer version), we fall back to inspecting the container to read Config.Image which always preserves the original name.
func (*DockerClient) ListKleverImages ¶ added in v0.3.79
func (d *DockerClient) ListKleverImages(ctx context.Context) ([]ImageInfo, error)
ListKleverImages returns detailed info for every local kleverapp/klever-go image, flagging which ones are still referenced by a container so the dashboard can block their deletion.
func (*DockerClient) ListLocalImages ¶
func (d *DockerClient) ListLocalImages(ctx context.Context) ([]string, error)
ListLocalImages returns images matching the klever-go image.
func (*DockerClient) PullImage ¶
func (d *DockerClient) PullImage(ctx context.Context, image string) error
PullImage pulls a Docker image from the registry.
func (*DockerClient) PullImageWithProgress ¶
func (d *DockerClient) PullImageWithProgress(ctx context.Context, image string, onProgress func(status string)) error
PullImageWithProgress pulls a Docker image and streams progress updates.
func (*DockerClient) RecreateWithStartInEpoch ¶ added in v0.3.85
func (d *DockerClient) RecreateWithStartInEpoch(ctx context.Context, containerName string) error
RecreateWithStartInEpoch recreates a container with the same config but with --start-in-epoch added. Used by the fast-reset flow: after the local chain DB is deleted, the node must fast-bootstrap from the latest epoch rather than try to resume from an empty DB. Docker only applies command args at create time, so a plain restart would keep whatever flag the container was created with — hence the recreate.
func (*DockerClient) RecreateWithoutStartInEpoch ¶ added in v0.3.79
func (d *DockerClient) RecreateWithoutStartInEpoch(ctx context.Context, containerName string) error
RecreateWithoutStartInEpoch recreates a container with the same config but with --start-in-epoch removed. Used after a full-DB restore: the node must resume from the restored DB's height and sync forward block-by-block, NOT fast-bootstrap to the latest epoch (which leaves a gap between the snapshot and now). Docker only applies command args at create time, so a plain restart would keep the original --start-in-epoch flag — hence the recreate.
func (*DockerClient) RemoveContainer ¶
RemoveContainer stops and removes a container.
func (*DockerClient) RemoveImage ¶ added in v0.3.79
func (d *DockerClient) RemoveImage(ctx context.Context, imageID string) error
RemoveImage deletes a single image by ID. noprune is left at Docker's default (false) so untagged parent layers freed by the delete are also reclaimed.
func (*DockerClient) RestartContainer ¶
func (d *DockerClient) RestartContainer(ctx context.Context, containerName string, timeoutSec int) error
RestartContainer restarts a container with a graceful timeout.
func (*DockerClient) RunBenchmark ¶ added in v0.3.49
func (d *DockerClient) RunBenchmark(ctx context.Context, onProgress BenchmarkProgress) (*BenchmarkResult, error)
RunBenchmark runs the klever-go benchmark tool in a one-shot Docker container.
func (*DockerClient) StartContainer ¶
func (d *DockerClient) StartContainer(ctx context.Context, containerName string) error
StartContainer starts a stopped container.
func (*DockerClient) StopContainer ¶
func (d *DockerClient) StopContainer(ctx context.Context, containerName string, timeoutSec int) error
StopContainer stops a running container with a graceful timeout.
func (*DockerClient) StreamLogs ¶
func (d *DockerClient) StreamLogs(ctx context.Context, containerName string, since int64, onLine func(LogLine)) error
StreamLogs streams live logs from a container, calling onLine for each new line. It blocks until the context is cancelled or the stream ends.
func (*DockerClient) UpgradeContainer ¶
func (d *DockerClient) UpgradeContainer(ctx context.Context, containerName, newTag string) (string, error)
UpgradeContainer upgrades a container to a new image tag. 1. Inspect current container for config 2. Pull new image 3. Stop and remove old container 4. Create new container with same config + new tag 5. Start new container
func (*DockerClient) UpgradeContainerWithRollback ¶
func (d *DockerClient) UpgradeContainerWithRollback(ctx context.Context, containerName, newTag string, onProgress ...UpgradeProgress) (string, error)
UpgradeContainerWithRollback upgrades a container and rolls back on failure. It verifies the new container is running after startup, and if not, recreates the container with the original image tag. The optional onProgress callback reports each step.
type Executor ¶
type Executor struct {
// contains filtered or unexported fields
}
Executor handles incoming commands from the dashboard.
func NewExecutor ¶
NewExecutor creates a new command executor.
func NewExecutorWithClient ¶
func NewExecutorWithClient(client *DockerClient) *Executor
NewExecutorWithClient creates an executor with a specific Docker client (for testing).
func (*Executor) Execute ¶
func (e *Executor) Execute(msg *models.Message, onProgress ProgressFunc) *models.CommandResult
Execute processes a command message and returns a result.
onProgress is per-call rather than an Executor field so that concurrent command goroutines don't race when assigning a new callback — each execution carries its own.
func (*Executor) SetUpdateSource ¶ added in v0.3.87
SetUpdateSource configures where and how the agent fetches its update binary over HTTP, used when the dashboard sends a download_path instead of inline base64 data. tlsConfig is the same client config used for the WebSocket, so the HTTP download trusts the dashboard exactly the same way. If this is never called (e.g. in tests), the agent falls back to the base64 payload.
type ImageInfo ¶ added in v0.3.79
type ImageInfo struct {
ID string `json:"id"` // full image ID (e.g. "sha256:abc...")
RepoTags []string `json:"repo_tags"` // e.g. ["kleverapp/klever-go:v1.2.3"]
Created int64 `json:"created"` // creation time, unix seconds
Size int64 `json:"size"` // size on disk, bytes
InUse bool `json:"in_use"` // referenced by an existing container
UsedBy []string `json:"used_by,omitempty"`
}
ImageInfo describes a local Docker image for the cleanup view.
type KeyInfo ¶
type KeyInfo struct {
BLSPublicKey string `json:"bls_public_key"`
KeyFile string `json:"key_file"`
FileSize int64 `json:"file_size"`
Modified int64 `json:"modified"`
HasBackup bool `json:"has_backup"`
}
KeyInfo represents information about a validator key.
func GetKeyInfo ¶
GetKeyInfo returns information about the validator key for a node.
type LogLine ¶
type LogLine struct {
Timestamp string `json:"timestamp,omitempty"`
Stream string `json:"stream"` // "stdout" or "stderr"
Message string `json:"message"`
}
LogLine represents a single log line from a container.
type LogStreamManager ¶
type LogStreamManager struct {
// contains filtered or unexported fields
}
LogStreamManager manages active log streams for containers.
The streams map is touched from at least three goroutines (the caller of StartStream/StopStream, the per-stream worker that removes itself when the stream ends, and any caller of StopAll/ActiveStreams). All access goes through mu — concurrent map writes panic at runtime, so the lock is correctness, not optimization.
func NewLogStreamManager ¶
func NewLogStreamManager(docker *DockerClient) *LogStreamManager
NewLogStreamManager creates a new log stream manager.
func (*LogStreamManager) ActiveStreams ¶
func (m *LogStreamManager) ActiveStreams() int
ActiveStreams returns the number of active streams.
func (*LogStreamManager) StartStream ¶
func (m *LogStreamManager) StartStream(containerName string, onLine func(LogLine)) error
StartStream starts streaming logs for a container. Only one stream per container is allowed.
func (*LogStreamManager) StopAll ¶
func (m *LogStreamManager) StopAll()
StopAll stops all active log streams.
func (*LogStreamManager) StopStream ¶
func (m *LogStreamManager) StopStream(containerName string)
StopStream stops streaming logs for a container.
type MetricsCollector ¶
type MetricsCollector struct {
// contains filtered or unexported fields
}
MetricsCollector collects system-level metrics from the host.
func NewMetricsCollector ¶
func NewMetricsCollector(diskPaths []string) *MetricsCollector
NewMetricsCollector creates a new metrics collector. diskPaths specifies which filesystem paths to monitor for disk usage.
func (*MetricsCollector) Collect ¶
func (mc *MetricsCollector) Collect() *models.SystemMetrics
Collect gathers current system metrics.
type NodeMetricsCollector ¶
type NodeMetricsCollector struct {
// contains filtered or unexported fields
}
NodeMetricsCollector polls /node/status for each discovered Klever node.
func NewNodeMetricsCollector ¶
func NewNodeMetricsCollector(opts ...NodeMetricsCollectorOption) *NodeMetricsCollector
NewNodeMetricsCollector creates a new collector for Klever node metrics.
func (*NodeMetricsCollector) CollectAll ¶
func (c *NodeMetricsCollector) CollectAll(serverID string) ([]*models.NodeMetricsEvent, []*models.NodeNonceStallEvent)
CollectAll polls all registered nodes and returns metrics events plus any stall alerts. Polling is parallel — a single unreachable node would otherwise block the whole cycle for defaultNodePollTimeout. With N nodes down, the previous serial loop took N * 5 s before the writer could send any of the partial results.
func (*NodeMetricsCollector) CollectOne ¶
func (c *NodeMetricsCollector) CollectOne(nodeID, serverID string) (*models.NodeMetricsEvent, error)
CollectOne polls a single node and returns its metrics event.
func (*NodeMetricsCollector) PollInterval ¶
func (c *NodeMetricsCollector) PollInterval() time.Duration
PollInterval returns the configured polling interval.
func (*NodeMetricsCollector) RunPoller ¶
func (c *NodeMetricsCollector) RunPoller(ctx context.Context, serverID string, metricsCh chan<- *models.Message, stallCh chan<- *models.Message)
RunPoller starts a background goroutine that polls all nodes at the configured interval. It sends metrics and stall events to the provided channels. The goroutine stops when ctx is canceled.
func (*NodeMetricsCollector) UpdateNodes ¶
func (c *NodeMetricsCollector) UpdateNodes(report *models.DiscoveryReport)
UpdateNodes updates the set of nodes to poll from a discovery report.
type NodeMetricsCollectorOption ¶
type NodeMetricsCollectorOption func(*NodeMetricsCollector)
NodeMetricsCollectorOption configures the NodeMetricsCollector.
func WithHTTPClient ¶
func WithHTTPClient(client *http.Client) NodeMetricsCollectorOption
WithHTTPClient sets a custom HTTP client (useful for testing).
func WithPollInterval ¶
func WithPollInterval(d time.Duration) NodeMetricsCollectorOption
WithPollInterval sets the polling interval.
func WithStallTimeout ¶
func WithStallTimeout(d time.Duration) NodeMetricsCollectorOption
WithStallTimeout sets the nonce stall detection timeout.
type ProgressFunc ¶ added in v0.3.54
ProgressFunc is called to send progress events during long-running commands.
type ProvisionStep ¶
type ProvisionStep struct {
Name string
Fn func(p *Provisioner, ctx context.Context) error
}
ProvisionStep represents a single provisioning step.
type Provisioner ¶
type Provisioner struct {
// contains filtered or unexported fields
}
Provisioner handles the multi-step node provisioning workflow.
func NewProvisioner ¶
func NewProvisioner(docker *DockerClient, req *models.ProvisionRequest, jobID string, progressFn func(*models.ProvisionProgress)) *Provisioner
NewProvisioner creates a new provisioner for a given request.
type UpdateResult ¶
type UpdateResult struct {
OldVersion string `json:"old_version"`
NewVersion string `json:"new_version"`
BackupPath string `json:"backup_path"`
NeedsRestart bool `json:"needs_restart"`
}
UpdateResult holds the result of an agent binary update.
func VerifyAndReplaceBinary ¶
func VerifyAndReplaceBinary(binaryData []byte, expectedChecksum string, agentConfigDir string) (*UpdateResult, error)
VerifyAndReplaceBinary verifies the checksum of new binary data and replaces the current agent binary. Keeps a backup of the previous version for rollback.