From c58c99e0616f13cd105cd0e72accd800d0268f65 Mon Sep 17 00:00:00 2001 From: Pavel Sviderski Date: Fri, 6 Sep 2024 09:26:45 +1000 Subject: [PATCH] rename machine config to state --- internal/cli/config/machine.go | 5 +-- internal/machine/cluster/cluster.go | 24 ++++++++----- internal/machine/daemon/daemon.go | 44 +++++++++++++----------- internal/machine/daemon/token.go | 6 ++-- internal/machine/{config.go => state.go} | 36 +++++++++---------- 5 files changed, 60 insertions(+), 55 deletions(-) rename internal/machine/{config.go => state.go} (75%) diff --git a/internal/cli/config/machine.go b/internal/cli/config/machine.go index 0d8cdffc..88c42bc9 100644 --- a/internal/cli/config/machine.go +++ b/internal/cli/config/machine.go @@ -5,9 +5,6 @@ import ( ) type MachineConnection struct { - User string `toml:"user,omitempty"` Host string `toml:"host"` - Port int `toml:"port"` - SSHKey string `toml:"ssh_key,omitempty"` - PublicKey secret.Secret `toml:"public_key,omitempty"` + PublicKey secret.Secret `toml:"public_key"` } diff --git a/internal/machine/cluster/cluster.go b/internal/machine/cluster/cluster.go index f219707d..06e1635a 100644 --- a/internal/machine/cluster/cluster.go +++ b/internal/machine/cluster/cluster.go @@ -22,31 +22,37 @@ const ( StateFile = "cluster.pb" ) +type Config struct { + APIAddr string + APISockPath string +} + type Cluster struct { // TODO: implement grpc ClusterServer pb.UnimplementedClusterServer - state *State - apiAddr string - server *grpc.Server + config Config + state *State + + server *grpc.Server } -func NewCluster(state *State, apiAddr string) *Cluster { +func NewCluster(config *Config, state *State) *Cluster { c := &Cluster{ - state: state, - apiAddr: apiAddr, - server: grpc.NewServer(), + config: *config, + state: state, + server: grpc.NewServer(), } pb.RegisterClusterServer(c.server, c) return c } func (c *Cluster) Run() error { - listener, err := net.Listen("tcp", c.apiAddr) + listener, err := net.Listen("tcp", c.config.APIAddr) if err != nil { return fmt.Errorf("listen API port: %w", err) } - slog.Info("Starting API server.", "addr", c.apiAddr) + slog.Info("Starting API server.", "addr", c.config.APIAddr) if err = c.server.Serve(listener); err != nil { return fmt.Errorf("API server failed: %w", err) } diff --git a/internal/machine/daemon/daemon.go b/internal/machine/daemon/daemon.go index 0aab4b61..90836b51 100644 --- a/internal/machine/daemon/daemon.go +++ b/internal/machine/daemon/daemon.go @@ -32,7 +32,7 @@ func InitCluster(dataDir, machineName string, netPrefix netip.Prefix, users []*p } state := cluster.NewState(cluster.StatePath(dataDir)) - c := cluster.NewCluster(state, "") + c := cluster.NewCluster(&cluster.Config{}, state) if err = c.SetNetwork(netPrefix); err != nil { return fmt.Errorf("set cluster network: %w", err) } @@ -69,7 +69,7 @@ func InitCluster(dataDir, machineName string, netPrefix netip.Prefix, users []*p if err != nil { return err } - mcfg := &machine.Config{ + mcfg := &machine.State{ ID: m.Id, Name: m.Name, Network: &network.Config{ @@ -97,7 +97,7 @@ func InitCluster(dataDir, machineName string, netPrefix netip.Prefix, users []*p } mcfg.Network.Peers = peers - mcfg.SetPath(machine.ConfigPath(dataDir)) + mcfg.SetPath(machine.StatePath(dataDir)) if err = mcfg.Save(); err != nil { return fmt.Errorf("save machine config: %w", err) } @@ -107,55 +107,57 @@ func InitCluster(dataDir, machineName string, netPrefix netip.Prefix, users []*p } type Daemon struct { - config *machine.Config + state *machine.State cluster *cluster.Cluster } func New(dataDir string) (*Daemon, error) { - cfgPath := machine.ConfigPath(dataDir) - cfg, err := machine.ParseConfig(cfgPath) + mstatePath := machine.StatePath(dataDir) + mstate, err := machine.ParseState(mstatePath) if err != nil { if !errors.Is(err, os.ErrNotExist) { return nil, fmt.Errorf("load machine config: %w", err) } // Generate an empty machine config with a new key pair. - slog.Info("Machine config not found, creating a new one.", "path", cfgPath) + slog.Info("Machine config not found, creating a new one.", "path", mstatePath) privKey, pubKey, kErr := network.NewMachineKeys() if kErr != nil { return nil, fmt.Errorf("generate machine keys: %w", kErr) } slog.Info("Generated machine key pair.", "pubkey", pubKey) - cfg = &machine.Config{ + mstate = &machine.State{ Network: &network.Config{ PrivateKey: privKey, PublicKey: pubKey, }, } - cfg.SetPath(cfgPath) - if err = cfg.Save(); err != nil { + mstate.SetPath(mstatePath) + if err = mstate.Save(); err != nil { return nil, fmt.Errorf("save machine config: %w", err) } } - statePath := cluster.StatePath(dataDir) - state := cluster.NewState(statePath) - if err = state.Load(); err != nil { + cstatePath := cluster.StatePath(dataDir) + cstate := cluster.NewState(cstatePath) + if err = cstate.Load(); err != nil { if !errors.Is(err, os.ErrNotExist) { return nil, fmt.Errorf("load cluster state: %w", err) } - slog.Info("Cluster state not found, creating a new one.", "path", statePath) - if err = state.Save(); err != nil { + slog.Info("Cluster state not found, creating a new one.", "path", cstatePath) + if err = cstate.Save(); err != nil { return nil, fmt.Errorf("save cluster state: %w", err) } } d := &Daemon{ - config: cfg, + state: mstate, } - if cfg.Network.IsConfigured() { - apiAddr := net.JoinHostPort(cfg.Network.ManagementIP.String(), strconv.Itoa(machine.APIPort)) - d.cluster = cluster.NewCluster(state, apiAddr) + if mstate.Network.IsConfigured() { + config := &cluster.Config{ + APIAddr: net.JoinHostPort(mstate.Network.ManagementIP.String(), strconv.Itoa(machine.APIPort)), + } + d.cluster = cluster.NewCluster(config, cstate) } return d, nil @@ -166,12 +168,12 @@ func (d *Daemon) Run(ctx context.Context) error { errGroup, ctx := errgroup.WithContext(ctx) // Start the network only if it is configured. - if d.config.Network.IsConfigured() { + if d.state.Network.IsConfigured() { wgnet, err := network.NewWireGuardNetwork() if err != nil { return fmt.Errorf("create WireGuard network: %w", err) } - if err = wgnet.Configure(*d.config.Network); err != nil { + if err = wgnet.Configure(*d.state.Network); err != nil { return fmt.Errorf("configure WireGuard network: %w", err) } diff --git a/internal/machine/daemon/token.go b/internal/machine/daemon/token.go index 109967eb..1fc67f0c 100644 --- a/internal/machine/daemon/token.go +++ b/internal/machine/daemon/token.go @@ -12,14 +12,14 @@ import ( // MachineToken returns the local machine's token that can be used for adding the machine to a cluster. // TODO: ideally, this should be an RPC call to the daemon API to ensure the config is created and up-to-date. func MachineToken(dataDir string) (machine.Token, error) { - cfg, err := machine.ParseConfig(machine.ConfigPath(dataDir)) + state, err := machine.ParseState(machine.StatePath(dataDir)) if err != nil { if errors.Is(err, os.ErrNotExist) { return machine.Token{}, fmt.Errorf("load machine config (is uncloudd daemon running?): %w", err) } return machine.Token{}, fmt.Errorf("load machine config: %w", err) } - if len(cfg.Network.PublicKey) == 0 { + if len(state.Network.PublicKey) == 0 { return machine.Token{}, errors.New("public key is not set in machine config") } @@ -37,5 +37,5 @@ func MachineToken(dataDir string) (machine.Token, error) { for i, ip := range ips { endpoints[i] = netip.AddrPortFrom(ip, network.WireGuardPort) } - return machine.NewToken(cfg.Network.PublicKey, endpoints), nil + return machine.NewToken(state.Network.PublicKey, endpoints), nil } diff --git a/internal/machine/config.go b/internal/machine/state.go similarity index 75% rename from internal/machine/config.go rename to internal/machine/state.go index 2c792ab2..03ef4103 100644 --- a/internal/machine/config.go +++ b/internal/machine/state.go @@ -14,13 +14,13 @@ import ( const ( DefaultDataDir = "/var/lib/uncloud" - ConfigFileName = "machine.json" + StateFileName = "machine.json" APIPort = 51000 ) -// Config defines the machine-specific configuration within a cluster for the Uncloud daemon. It encapsulates -// essential identifiers and settings required to establish an overlay network and join the cluster. -type Config struct { +// State defines the machine-specific configuration within a cluster. It encapsulates essential identifiers +// and settings required to establish an overlay network and operate as a member of a cluster. +type State struct { // ID uniquely identifies this machine in the cluster. ID string // Name provides a human-readable identifier for the machine. @@ -32,18 +32,18 @@ type Config struct { path string } -// ConfigPath returns the path to the machine configuration file within the given data directory. -func ConfigPath(dataDir string) string { - return filepath.Join(dataDir, ConfigFileName) +// StatePath returns the path to the machine state file within the given data directory. +func StatePath(dataDir string) string { + return filepath.Join(dataDir, StateFileName) } -// ParseConfig reads and decodes a config from the file at the given path. -func ParseConfig(path string) (*Config, error) { +// ParseState reads and decodes a state from the file at the given path. +func ParseState(path string) (*State, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read config file: %w", err) } - var config Config + var config State if err = json.Unmarshal(data, &config); err != nil { return nil, fmt.Errorf("parse config file %q: %w", path, err) } @@ -54,13 +54,13 @@ func ParseConfig(path string) (*Config, error) { return &config, nil } -// SetPath sets the file path the config can be saved to. -func (c *Config) SetPath(path string) { +// SetPath sets the file path the state can be saved to. +func (c *State) SetPath(path string) { c.path = path } -// Encode returns the JSON encoded config data. -func (c *Config) Encode() ([]byte, error) { +// Encode returns the JSON encoded state data. +func (c *State) Encode() ([]byte, error) { data, err := json.MarshalIndent(c, "", " ") if err != nil { return nil, fmt.Errorf("marshal config: %w", err) @@ -68,8 +68,8 @@ func (c *Config) Encode() ([]byte, error) { return data, nil } -// Save writes the config data to the file at the given path. -func (c *Config) Save() error { +// Save writes the state data to the file at the given path. +func (c *State) Save() error { if c.path == "" { return fmt.Errorf("config path not set") } @@ -105,7 +105,7 @@ func NewRandomName() (string, error) { } // NewBootstrapConfig returns a new machine configuration that should be applied to the first machine in a cluster. -func NewBootstrapConfig(name string, subnet netip.Prefix, peers ...network.PeerConfig) (*Config, error) { +func NewBootstrapConfig(name string, subnet netip.Prefix, peers ...network.PeerConfig) (*State, error) { mid, err := NewID() if err != nil { return nil, fmt.Errorf("generate machine ID: %w", err) @@ -125,7 +125,7 @@ func NewBootstrapConfig(name string, subnet netip.Prefix, peers ...network.PeerC subnet = netip.PrefixFrom(network.DefaultNetwork.Addr(), network.DefaultSubnetBits) } - return &Config{ + return &State{ ID: mid, Name: name, Network: &network.Config{