- Wizard: type pick → cloud region → token → node config → deploys via native.InstallNode / docker.DeployContainer - State saved after successful deployment with API token - Dashboard reflects real node state from ~/.wallarm/state.json - Removed old unused HuhForm stub
84 lines
2.5 KiB
Go
84 lines
2.5 KiB
Go
// Package state manages the persistent deployment state file (~/.wallarm/state.json).
|
|
package state
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
// StateDir is where wallarm stores its state.
|
|
const StateDir = ".wallarm"
|
|
|
|
// State represents the persistent deployment state.
|
|
type State struct {
|
|
DeploymentType string `json:"deployment_type,omitempty"` // docker or native
|
|
CloudRegion string `json:"cloud_region,omitempty"` // US or EU
|
|
APIHost string `json:"api_host,omitempty"` // e.g., api.wallarm.com
|
|
APIToken string `json:"api_token,omitempty"` // Wallarm API token (sensitive)
|
|
Nodes []Node `json:"nodes"`
|
|
}
|
|
|
|
// Node represents a single deployed Wallarm node (docker container or native systemd unit).
|
|
type Node struct {
|
|
Name string `json:"name"`
|
|
Type string `json:"type"` // docker or native
|
|
Address string `json:"address,omitempty"` // listen address for native
|
|
Port int `json:"port,omitempty"` // ingress port for docker
|
|
UpstreamIP string `json:"upstream_ip,omitempty"` // docker
|
|
UpstreamPort int `json:"upstream_port,omitempty"` // docker
|
|
Status string `json:"status"` // running, stopped, unknown
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
// Path returns the full path to the state file.
|
|
func Path() string {
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
home = "/root"
|
|
}
|
|
return filepath.Join(home, StateDir, "state.json")
|
|
}
|
|
|
|
// Load reads and parses the state file. Returns nil if the file doesn't exist.
|
|
func Load() (*State, error) {
|
|
p := Path()
|
|
data, err := os.ReadFile(p)
|
|
if os.IsNotExist(err) {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read state: %w", err)
|
|
}
|
|
var s State
|
|
if err := json.Unmarshal(data, &s); err != nil {
|
|
return nil, fmt.Errorf("parse state: %w", err)
|
|
}
|
|
return &s, nil
|
|
}
|
|
|
|
// Save writes the state to disk, creating directories as needed.
|
|
func Save(s *State) error {
|
|
p := Path()
|
|
if err := os.MkdirAll(filepath.Dir(p), 0700); err != nil {
|
|
return fmt.Errorf("create state dir: %w", err)
|
|
}
|
|
data, err := json.MarshalIndent(s, "", " ")
|
|
if err != nil {
|
|
return fmt.Errorf("marshal state: %w", err)
|
|
}
|
|
if err := os.WriteFile(p, data, 0600); err != nil {
|
|
return fmt.Errorf("write state: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// HasDeployment returns true if a state file exists with at least one node.
|
|
func HasDeployment() bool {
|
|
s, err := Load()
|
|
if err != nil || s == nil {
|
|
return false
|
|
}
|
|
return len(s.Nodes) > 0
|
|
}
|