wallarm/source/internal/state/state.go
admin 78e316af64 refactor: move Go source into source/ directory
- source/cmd/wallarm/main.go — binary entrypoint
- source/internal/ — all packages
- source/go.mod, source/go.sum
- deploy.sh builds from source/ subdirectory
- Clean separation: source code vs deployment configs
2026-08-01 15:33:17 +00:00

79 lines
2.4 KiB
Go

// Package state manages the persistent deployment state file (~/.wallarm/state.json).
package state
import (
"encoding/json"
"fmt"
"os"
)
// StateDir is where wallarm stores its state (under /opt/wallarm/).
const StateDir = "/opt/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 {
return 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 /opt/wallarm/state.json.
func Save(s *State) error {
p := Path()
if err := os.MkdirAll(StateDir, 0755); 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
}