Compare commits
2 commits
e9b5231cc8
...
feb86c29d3
| Author | SHA1 | Date | |
|---|---|---|---|
| feb86c29d3 | |||
| 5f212a103d |
22 changed files with 127 additions and 108 deletions
|
|
@ -9,18 +9,18 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/config"
|
"git.wzray.com/homelab/hivemind/internal/config"
|
||||||
"git.wzray.com/homelab/mastermind/internal/registry"
|
"git.wzray.com/homelab/hivemind/internal/registry"
|
||||||
"git.wzray.com/homelab/mastermind/internal/roles"
|
"git.wzray.com/homelab/hivemind/internal/roles"
|
||||||
"git.wzray.com/homelab/mastermind/internal/roles/dns"
|
"git.wzray.com/homelab/hivemind/internal/roles/dns"
|
||||||
"git.wzray.com/homelab/mastermind/internal/roles/host"
|
"git.wzray.com/homelab/hivemind/internal/roles/host"
|
||||||
"git.wzray.com/homelab/mastermind/internal/roles/master"
|
"git.wzray.com/homelab/hivemind/internal/roles/master"
|
||||||
"git.wzray.com/homelab/mastermind/internal/roles/node"
|
"git.wzray.com/homelab/hivemind/internal/roles/node"
|
||||||
"git.wzray.com/homelab/mastermind/internal/state"
|
"git.wzray.com/homelab/hivemind/internal/state"
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/client"
|
"git.wzray.com/homelab/hivemind/internal/web/client"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/middleware"
|
"git.wzray.com/homelab/hivemind/internal/web/middleware"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/server"
|
"git.wzray.com/homelab/hivemind/internal/web/server"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/rs/zerolog/pkgerrors"
|
"github.com/rs/zerolog/pkgerrors"
|
||||||
|
|
@ -76,8 +76,9 @@ func main() {
|
||||||
zerolog.SetGlobalLevel(levelToZerolog(config.Node.LogLevel))
|
zerolog.SetGlobalLevel(levelToZerolog(config.Node.LogLevel))
|
||||||
|
|
||||||
self := types.NewNode(
|
self := types.NewNode(
|
||||||
fmt.Sprintf("%v:%v", config.Node.Endpoint, config.Node.Port),
|
|
||||||
config.Node.Hostname,
|
config.Node.Hostname,
|
||||||
|
config.Node.Address,
|
||||||
|
config.Node.Port,
|
||||||
config.Roles,
|
config.Roles,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
20
config.toml
20
config.toml
|
|
@ -1,19 +1,19 @@
|
||||||
[node]
|
[node]
|
||||||
log_level = "DEBUG"
|
log_level = "DEBUG"
|
||||||
hostname = ""
|
address = "laptop.spb.wzray.com"
|
||||||
endpoint = ""
|
hostname = "laptop.spb.wzray.com"
|
||||||
bootstrap_master = ""
|
bootstrap_master = "hicpu.spb.wzray.com"
|
||||||
keepalive_interval = 1
|
keepalive_interval = 10
|
||||||
|
|
||||||
[roles.master]
|
[roles.master]
|
||||||
observer_interval = 4
|
observer_interval = 1
|
||||||
|
|
||||||
[roles.dns]
|
[roles.dns]
|
||||||
use_systemd = false
|
use_systemd = false
|
||||||
|
|
||||||
[roles.host]
|
[roles.host]
|
||||||
domain = ""
|
domain = "traefik.wzray.com"
|
||||||
ip = ""
|
ip = "10.161.4.11"
|
||||||
local_address = ""
|
local_address = "10.161.4.11"
|
||||||
internal_entrypoint = ""
|
internal_entrypoint = "https"
|
||||||
external_entrypoint = ""
|
external_entrypoint = "ehttps"
|
||||||
|
|
|
||||||
2
go.mod
2
go.mod
|
|
@ -1,4 +1,4 @@
|
||||||
module git.wzray.com/homelab/mastermind
|
module git.wzray.com/homelab/hivemind
|
||||||
|
|
||||||
go 1.25.5
|
go 1.25.5
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package config
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -29,28 +30,33 @@ func (l *LogLevel) UnmarshalText(data []byte) error {
|
||||||
|
|
||||||
type NodeConfig struct {
|
type NodeConfig struct {
|
||||||
Hostname string `toml:"hostname"`
|
Hostname string `toml:"hostname"`
|
||||||
Endpoint string `toml:"endpoint"`
|
Address string `toml:"address"`
|
||||||
|
Port int `toml:"port"`
|
||||||
|
|
||||||
KeepaliveInterval int `toml:"keepalive_interval"`
|
KeepaliveInterval int `toml:"keepalive_interval"`
|
||||||
LogLevel LogLevel `toml:"log_level"`
|
LogLevel LogLevel `toml:"log_level"`
|
||||||
|
|
||||||
BootstrapMaster string `toml:"bootstrap_master"`
|
BootstrapMaster string `toml:"bootstrap_master"`
|
||||||
ListenOn string `toml:"listen_on"`
|
ListenOn string `toml:"listen_on"`
|
||||||
Port int `toml:"port"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c NodeConfig) Validate() error {
|
func (c NodeConfig) Validate() error {
|
||||||
|
if c.Address == "" {
|
||||||
|
return errors.New("missing address")
|
||||||
|
}
|
||||||
|
|
||||||
if c.Hostname == "" {
|
if c.Hostname == "" {
|
||||||
return errors.New("missing hostname")
|
return errors.New("missing hostname")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Endpoint == "" {
|
|
||||||
return errors.New("missing endpoint")
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.KeepaliveInterval < 1 && c.KeepaliveInterval != -1 {
|
if c.KeepaliveInterval < 1 && c.KeepaliveInterval != -1 {
|
||||||
return errors.New("invalid keepalive_interval")
|
return errors.New("invalid keepalive_interval")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if net.ParseIP(c.ListenOn) == nil {
|
||||||
|
return errors.New("invalid listen_on")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,8 +65,8 @@ func (c *NodeConfig) Merge(other NodeConfig) {
|
||||||
c.Hostname = other.Hostname
|
c.Hostname = other.Hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
if other.Endpoint != "" {
|
if other.Address != "" {
|
||||||
c.Endpoint = other.Endpoint
|
c.Address = other.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
if other.BootstrapMaster != "" {
|
if other.BootstrapMaster != "" {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileStorage struct {
|
type FileStorage struct {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ func New(storage Storage, self types.Node) *Registry {
|
||||||
r.nodes = storedData.Nodes
|
r.nodes = storedData.Nodes
|
||||||
|
|
||||||
ret:
|
ret:
|
||||||
r.nodes[self.Name] = self
|
r.nodes[self.Hostname] = self
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +68,7 @@ func (r *Registry) AllNodes() []types.Node {
|
||||||
func (r *Registry) Nodes() []types.Node {
|
func (r *Registry) Nodes() []types.Node {
|
||||||
nodes := r.AllNodes()
|
nodes := r.AllNodes()
|
||||||
nodes = slices.DeleteFunc(nodes, func(n types.Node) bool {
|
nodes = slices.DeleteFunc(nodes, func(n types.Node) bool {
|
||||||
return n.Name == r.self.Name
|
return n.Hostname == r.self.Hostname
|
||||||
})
|
})
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +79,7 @@ func (r *Registry) ByRole(role types.Role) []types.Node {
|
||||||
|
|
||||||
o := make([]types.Node, 0, len(r.nodes))
|
o := make([]types.Node, 0, len(r.nodes))
|
||||||
for _, node := range r.nodes {
|
for _, node := range r.nodes {
|
||||||
if slices.Contains(node.Roles, role) && node.Name != r.self.Name {
|
if slices.Contains(node.Roles, role) && node.Hostname != r.self.Hostname {
|
||||||
o = append(o, node)
|
o = append(o, node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +88,7 @@ func (r *Registry) ByRole(role types.Role) []types.Node {
|
||||||
|
|
||||||
func (r *Registry) AddNode(node types.Node) error {
|
func (r *Registry) AddNode(node types.Node) error {
|
||||||
r.lock.Lock()
|
r.lock.Lock()
|
||||||
r.nodes[node.Name] = node
|
r.nodes[node.Hostname] = node
|
||||||
r.LastUpdate = time.Now()
|
r.LastUpdate = time.Now()
|
||||||
snapshot := r.snapshot()
|
snapshot := r.snapshot()
|
||||||
r.lock.Unlock()
|
r.lock.Unlock()
|
||||||
|
|
@ -119,7 +119,7 @@ func (r *Registry) Set(nodes []types.Node) error {
|
||||||
r.lock.Lock()
|
r.lock.Lock()
|
||||||
r.nodes = make(map[string]types.Node)
|
r.nodes = make(map[string]types.Node)
|
||||||
for _, n := range nodes {
|
for _, n := range nodes {
|
||||||
r.nodes[n.Name] = n
|
r.nodes[n.Hostname] = n
|
||||||
}
|
}
|
||||||
snapshot := r.snapshot()
|
snapshot := r.snapshot()
|
||||||
r.lock.Unlock()
|
r.lock.Unlock()
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
import "git.wzray.com/homelab/mastermind/internal/types"
|
import "git.wzray.com/homelab/hivemind/internal/types"
|
||||||
|
|
||||||
type Storage interface {
|
type Storage interface {
|
||||||
Save(*storedConfig) error
|
Save(*storedConfig) error
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/config"
|
"git.wzray.com/homelab/hivemind/internal/config"
|
||||||
"git.wzray.com/homelab/mastermind/internal/state"
|
"git.wzray.com/homelab/hivemind/internal/state"
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/client"
|
"git.wzray.com/homelab/hivemind/internal/web/client"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -48,10 +48,10 @@ func parseState(state types.HostState) (string, []byte) {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
|
|
||||||
for _, d := range state.Domains {
|
for _, d := range state.Domains {
|
||||||
builder.WriteString(fmt.Sprintf("%s %s\n", state.Endpoint, d))
|
builder.WriteString(fmt.Sprintf("%s %s\n", state.Address, d))
|
||||||
}
|
}
|
||||||
|
|
||||||
return hostsDir + state.Name, []byte(builder.String())
|
return hostsDir + state.Hostname, []byte(builder.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Role) OnStartup(ctx context.Context) error {
|
func (r *Role) OnStartup(ctx context.Context) error {
|
||||||
|
|
@ -76,15 +76,15 @@ func (r *Role) OnStartup(ctx context.Context) error {
|
||||||
|
|
||||||
func (r *Role) syncFromRegistry() {
|
func (r *Role) syncFromRegistry() {
|
||||||
for _, n := range r.state.Registry.ByRole(types.HostRole) {
|
for _, n := range r.state.Registry.ByRole(types.HostRole) {
|
||||||
state, err := client.Get[types.HostState](n.Address, types.PathHostDns)
|
state, err := client.Get[types.HostState](n.Endpoint, types.PathHostDns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn().Str("name", n.Name).Err(err).Msg("unable to get host config")
|
log.Warn().Str("name", n.Hostname).Err(err).Msg("unable to get host config")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
filename, data := parseState(*state)
|
filename, data := parseState(*state)
|
||||||
if err := r.updateDnsmasq(filename, data); err != nil {
|
if err := r.updateDnsmasq(filename, data); err != nil {
|
||||||
log.Warn().Str("name", n.Name).Err(err).Msg("unable to update dnsmasq")
|
log.Warn().Str("name", n.Hostname).Err(err).Msg("unable to update dnsmasq")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"slices"
|
"slices"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/config"
|
"git.wzray.com/homelab/hivemind/internal/config"
|
||||||
"git.wzray.com/homelab/mastermind/internal/state"
|
"git.wzray.com/homelab/hivemind/internal/state"
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/client"
|
"git.wzray.com/homelab/hivemind/internal/web/client"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -37,15 +37,15 @@ func New(state *state.RuntimeState, config config.HostConfig) *Role {
|
||||||
func (r *Role) sendUpdate(domains []string, role types.Role) {
|
func (r *Role) sendUpdate(domains []string, role types.Role) {
|
||||||
state := types.HostState{
|
state := types.HostState{
|
||||||
Domains: domains,
|
Domains: domains,
|
||||||
Name: r.state.Self.Name,
|
Address: r.config.IpAddress,
|
||||||
Endpoint: r.state.Self.Address,
|
Hostname: r.state.Self.Hostname,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range r.state.Registry.ByRole(role) {
|
for _, node := range r.state.Registry.ByRole(role) {
|
||||||
r.tasksGroup.Go(func() {
|
r.tasksGroup.Go(func() {
|
||||||
logger := log.With().Str("name", node.Name).Logger()
|
logger := log.With().Str("name", node.Hostname).Logger()
|
||||||
logger.Debug().Msg("sending update")
|
logger.Debug().Msg("sending update")
|
||||||
if _, err := client.Post[any](node.Address, types.PathDnsCallback, state); err != nil {
|
if _, err := client.Post[any](node.Endpoint, types.PathDnsCallback, state); err != nil {
|
||||||
logger.Warn().Err(err).Msg("unable to send dns info")
|
logger.Warn().Err(err).Msg("unable to send dns info")
|
||||||
} else {
|
} else {
|
||||||
logger.Debug().Msg("update sent")
|
logger.Debug().Msg("update sent")
|
||||||
|
|
@ -87,8 +87,8 @@ func (r *Role) onCallback(w http.ResponseWriter, req *http.Request) {
|
||||||
func (r *Role) getInternal() (types.HostState, error) {
|
func (r *Role) getInternal() (types.HostState, error) {
|
||||||
return types.HostState{
|
return types.HostState{
|
||||||
Domains: r.internalDomains,
|
Domains: r.internalDomains,
|
||||||
Endpoint: r.config.IpAddress,
|
Address: r.config.IpAddress,
|
||||||
Name: r.state.Self.Name,
|
Hostname: r.state.Self.Hostname,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/config"
|
"git.wzray.com/homelab/hivemind/internal/config"
|
||||||
"git.wzray.com/homelab/mastermind/internal/roles"
|
"git.wzray.com/homelab/hivemind/internal/roles"
|
||||||
"git.wzray.com/homelab/mastermind/internal/state"
|
"git.wzray.com/homelab/hivemind/internal/state"
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/client"
|
"git.wzray.com/homelab/hivemind/internal/web/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Role struct {
|
type Role struct {
|
||||||
|
|
@ -50,7 +50,7 @@ func (r *Role) OnShutdown() error {
|
||||||
|
|
||||||
func (r *Role) notify(path types.Path, v any) {
|
func (r *Role) notify(path types.Path, v any) {
|
||||||
for _, n := range r.state.Registry.Nodes() {
|
for _, n := range r.state.Registry.Nodes() {
|
||||||
addr := n.Address
|
addr := n.Endpoint
|
||||||
r.tasksGroup.Go(func() {
|
r.tasksGroup.Go(func() {
|
||||||
client.Post[any](addr, path, v)
|
client.Post[any](addr, path, v)
|
||||||
})
|
})
|
||||||
|
|
@ -68,17 +68,17 @@ func (r *Role) onJoin(node types.Node) ([]types.Node, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Role) onLeave(node types.Node) (bool, error) {
|
func (r *Role) onLeave(node types.Node) (bool, error) {
|
||||||
if err := r.state.Registry.RemoveNode(node.Name); err != nil {
|
if err := r.state.Registry.RemoveNode(node.Hostname); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
r.notify(types.PathNodeLeave, node.Name)
|
r.notify(types.PathNodeLeave, node)
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Role) onKeepAlive(node types.Node) (bool, error) {
|
func (r *Role) onKeepAlive(node types.Node) (bool, error) {
|
||||||
if ok := r.state.Registry.Exists(node.Name); !ok {
|
if ok := r.state.Registry.Exists(node.Hostname); !ok {
|
||||||
_, err := r.onJoin(node)
|
_, err := r.onJoin(node)
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/state"
|
"git.wzray.com/homelab/hivemind/internal/state"
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/client"
|
"git.wzray.com/homelab/hivemind/internal/web/client"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -33,14 +33,14 @@ func newObserver(
|
||||||
|
|
||||||
func (o *observer) pollNodes(ctx context.Context, onLeave func(types.Node) error) {
|
func (o *observer) pollNodes(ctx context.Context, onLeave func(types.Node) error) {
|
||||||
for _, n := range o.state.Registry.Nodes() {
|
for _, n := range o.state.Registry.Nodes() {
|
||||||
name := n.Name
|
name := n.Hostname
|
||||||
logger := log.With().Str("name", name).Logger()
|
logger := log.With().Str("name", name).Logger()
|
||||||
logger.Debug().Msg("checking node")
|
logger.Debug().Msg("checking node")
|
||||||
|
|
||||||
delay := time.Duration(o.backoff)
|
delay := time.Duration(o.backoff)
|
||||||
alive := false
|
alive := false
|
||||||
for i := o.backoffCount; i > 0; i-- {
|
for i := o.backoffCount; i > 0; i-- {
|
||||||
_, err := client.Get[any](n.Address, types.PathNodeHealthcheck)
|
_, err := client.Get[any](n.Endpoint, types.PathNodeHealthcheck)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logger.Debug().Msg("node is alive")
|
logger.Debug().Msg("node is alive")
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/config"
|
"git.wzray.com/homelab/hivemind/internal/config"
|
||||||
"git.wzray.com/homelab/mastermind/internal/state"
|
"git.wzray.com/homelab/hivemind/internal/state"
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/client"
|
"git.wzray.com/homelab/hivemind/internal/web/client"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -29,10 +29,10 @@ func New(state *state.RuntimeState, config config.NodeConfig) *Role {
|
||||||
func (r *Role) Join(bootstrap string) error {
|
func (r *Role) Join(bootstrap string) error {
|
||||||
masters := make(map[string]struct{})
|
masters := make(map[string]struct{})
|
||||||
for _, node := range r.state.Registry.ByRole(types.MasterRole) {
|
for _, node := range r.state.Registry.ByRole(types.MasterRole) {
|
||||||
if node.Name == r.state.Self.Name {
|
if node.Hostname == r.state.Self.Hostname {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
masters[node.Address] = struct{}{}
|
masters[node.Endpoint] = struct{}{}
|
||||||
}
|
}
|
||||||
if bootstrap != "" {
|
if bootstrap != "" {
|
||||||
masters[bootstrap] = struct{}{}
|
masters[bootstrap] = struct{}{}
|
||||||
|
|
@ -69,10 +69,10 @@ func (r *Role) Leave() error {
|
||||||
|
|
||||||
sent := false
|
sent := false
|
||||||
for _, m := range masters {
|
for _, m := range masters {
|
||||||
logger := log.With().Str("name", m.Name).Logger()
|
logger := log.With().Str("name", m.Hostname).Logger()
|
||||||
logger.Debug().Msg("sending leave message")
|
logger.Debug().Msg("sending leave message")
|
||||||
|
|
||||||
_, err := client.Post[any](m.Address, types.PathMasterLeave, r.state.Self)
|
_, err := client.Post[any](m.Endpoint, types.PathMasterLeave, r.state.Self)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Debug().Err(err).Msg("unable to send leave message")
|
logger.Debug().Err(err).Msg("unable to send leave message")
|
||||||
continue
|
continue
|
||||||
|
|
@ -114,10 +114,10 @@ func (r *Role) keepaliveFunc(ctx context.Context) func() {
|
||||||
|
|
||||||
sent := false
|
sent := false
|
||||||
for _, m := range masters {
|
for _, m := range masters {
|
||||||
logger := log.With().Str("name", m.Name).Logger()
|
logger := log.With().Str("name", m.Hostname).Logger()
|
||||||
logger.Debug().Msg("sending keepalive packet")
|
logger.Debug().Msg("sending keepalive packet")
|
||||||
|
|
||||||
if _, err := client.Post[any](m.Address, types.PathMasterKeepalive, r.state.Self); err != nil {
|
if _, err := client.Post[any](m.Endpoint, types.PathMasterKeepalive, r.state.Self); err != nil {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
logger.Debug().Msg("keepalive packet sent")
|
logger.Debug().Msg("keepalive packet sent")
|
||||||
|
|
@ -151,7 +151,7 @@ func (r *Role) onJoin(node types.Node) (bool, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Role) onLeave(node types.Node) (bool, error) {
|
func (r *Role) onLeave(node types.Node) (bool, error) {
|
||||||
if err := r.state.Registry.RemoveNode(node.Name); err != nil {
|
if err := r.state.Registry.RemoveNode(node.Hostname); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package roles
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Role interface {
|
type Role interface {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.wzray.com/homelab/mastermind/internal/registry"
|
"git.wzray.com/homelab/hivemind/internal/registry"
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RuntimeState struct {
|
type RuntimeState struct {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@ package types
|
||||||
|
|
||||||
type HostState struct {
|
type HostState struct {
|
||||||
Domains []string
|
Domains []string
|
||||||
Endpoint string
|
Address string
|
||||||
Name string
|
Hostname string
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,27 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
// TODO: consider moving this type back to registry
|
// TODO: consider moving this type back to registry
|
||||||
type Node struct {
|
type Node struct {
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Name string `json:"name"`
|
Port int `json:"port"`
|
||||||
Roles []Role `json:"roles"`
|
Roles []Role `json:"roles"`
|
||||||
|
Endpoint string `json:"endpoint"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewNode(address string, name string, roles []Role) Node {
|
func NewNode(
|
||||||
|
hostname string,
|
||||||
|
address string,
|
||||||
|
port int,
|
||||||
|
roles []Role,
|
||||||
|
) Node {
|
||||||
return Node{
|
return Node{
|
||||||
|
Hostname: hostname,
|
||||||
Address: address,
|
Address: address,
|
||||||
Name: name,
|
Port: port,
|
||||||
Roles: roles,
|
Roles: roles,
|
||||||
|
Endpoint: fmt.Sprintf("%s:%d", address, port),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
package types
|
|
||||||
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: split this up
|
||||||
|
|
||||||
type Path string
|
type Path string
|
||||||
|
|
||||||
func (p Path) String() string {
|
func (p Path) String() string {
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/middleware"
|
"git.wzray.com/homelab/hivemind/internal/web/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
"git.wzray.com/homelab/mastermind/internal/web/middleware"
|
"git.wzray.com/homelab/hivemind/internal/web/middleware"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.wzray.com/homelab/mastermind/internal/types"
|
"git.wzray.com/homelab/hivemind/internal/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fail(format string, a ...any) []byte {
|
func fail(format string, a ...any) []byte {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue