From 24059dc9eec830f1a2533f5a1a81eaa64520f7d9 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Sun, 10 Sep 2023 19:16:36 +0000 Subject: [PATCH] cluster: rename Zones to Cluster Signed-off-by: Alejandro Mery --- cmd/jpictl/config.go | 2 +- pkg/cluster/ceph.go | 8 +-- pkg/cluster/ceph_scan.go | 2 +- pkg/cluster/cluster.go | 72 +++++++++++++++++++ .../{zones_file.go => cluster_file.go} | 10 +-- pkg/cluster/{scan.go => cluster_scan.go} | 14 ++-- .../{options.go => cluster_scan_options.go} | 22 +++--- pkg/cluster/env.go | 2 +- pkg/cluster/log.go | 14 ++-- pkg/cluster/sync.go | 6 +- pkg/cluster/wireguard.go | 16 ++--- pkg/cluster/zones.go | 70 +----------------- 12 files changed, 123 insertions(+), 115 deletions(-) rename pkg/cluster/{zones_file.go => cluster_file.go} (66%) rename pkg/cluster/{scan.go => cluster_scan.go} (89%) rename pkg/cluster/{options.go => cluster_scan_options.go} (79%) diff --git a/cmd/jpictl/config.go b/cmd/jpictl/config.go index df1cd7c..dba4f2f 100644 --- a/cmd/jpictl/config.go +++ b/cmd/jpictl/config.go @@ -14,7 +14,7 @@ var cfg = &Config{ } // LoadZones loads all zones and machines in the config directory -func (cfg *Config) LoadZones(resolve bool) (*cluster.Zones, error) { +func (cfg *Config) LoadZones(resolve bool) (*cluster.Cluster, error) { return cluster.New(cfg.Base, cfg.Domain, cluster.ResolvePublicAddresses(resolve), cluster.WithLogger(log), diff --git a/pkg/cluster/ceph.go b/pkg/cluster/ceph.go index 185dc3d..b91b98b 100644 --- a/pkg/cluster/ceph.go +++ b/pkg/cluster/ceph.go @@ -12,7 +12,7 @@ import ( ) // GetCephFSID returns our Ceph's FSID -func (m *Zones) GetCephFSID() (uuid.UUID, error) { +func (m *Cluster) GetCephFSID() (uuid.UUID, error) { if core.IsZero(m.CephFSID) { // generate one v, err := uuid.NewV4() @@ -25,7 +25,7 @@ func (m *Zones) GetCephFSID() (uuid.UUID, error) { } // GetCephConfig reads the ceph.conf file -func (m *Zones) GetCephConfig() (*ceph.Config, error) { +func (m *Cluster) GetCephConfig() (*ceph.Config, error) { data, err := m.ReadFile("ceph.conf") if err != nil { return nil, err @@ -36,7 +36,7 @@ func (m *Zones) GetCephConfig() (*ceph.Config, error) { } // WriteCephConfig writes the ceph.conf file -func (m *Zones) WriteCephConfig(cfg *ceph.Config) error { +func (m *Cluster) WriteCephConfig(cfg *ceph.Config) error { f, err := m.CreateTruncFile("ceph.conf") if err != nil { return err @@ -48,7 +48,7 @@ func (m *Zones) WriteCephConfig(cfg *ceph.Config) error { } // GenCephConfig prepares a ceph.Config using the cluster information -func (m *Zones) GenCephConfig() (*ceph.Config, error) { +func (m *Cluster) GenCephConfig() (*ceph.Config, error) { fsid, err := m.GetCephFSID() if err != nil { return nil, err diff --git a/pkg/cluster/ceph_scan.go b/pkg/cluster/ceph_scan.go index a64e2d7..f85d09f 100644 --- a/pkg/cluster/ceph_scan.go +++ b/pkg/cluster/ceph_scan.go @@ -71,7 +71,7 @@ func newCephScanTODO(cfg *ceph.Config) *cephScanTODO { return todo } -func (m *Zones) scanCephMonitors(_ *ScanOptions) error { +func (m *Cluster) scanCephMonitors(_ *ScanOptions) error { cfg, err := m.GetCephConfig() switch { case os.IsNotExist(err): diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index bd55f18..8475fb8 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -1,2 +1,74 @@ // Package cluster contains information about the cluster package cluster + +import ( + "io/fs" + + "darvaza.org/resolver" + "darvaza.org/slog" + "github.com/gofrs/uuid/v5" +) + +var ( + _ MachineIterator = (*Cluster)(nil) + _ ZoneIterator = (*Cluster)(nil) +) + +// revive:disable:line-length-limit + +// Cluster represents all zones in a cluster +type Cluster struct { + dir fs.FS + log slog.Logger + resolver resolver.Resolver + domain string + + CephFSID uuid.UUID `json:"ceph_fsid,omitempty" yaml:"ceph_fsid,omitempty"` + Zones []*Zone +} + +// revive:enable:line-length-limit + +// ForEachMachine calls a function for each Machine in the cluster +// until instructed to terminate the loop +func (m *Cluster) ForEachMachine(fn func(*Machine) bool) { + m.ForEachZone(func(z *Zone) bool { + var term bool + + z.ForEachMachine(func(p *Machine) bool { + term = fn(p) + return term + }) + + return term + }) +} + +// ForEachZone calls a function for each Zone in the cluster +// until instructed to terminate the loop +func (m *Cluster) ForEachZone(fn func(*Zone) bool) { + for _, p := range m.Zones { + if fn(p) { + // terminate + return + } + } +} + +// GetMachineByName looks for a machine with the specified +// name on any zone +func (m *Cluster) GetMachineByName(name string) (*Machine, bool) { + var out *Machine + + if name != "" { + m.ForEachMachine(func(p *Machine) bool { + if p.Name == name { + out = p + } + + return out != nil + }) + } + + return out, out != nil +} diff --git a/pkg/cluster/zones_file.go b/pkg/cluster/cluster_file.go similarity index 66% rename from pkg/cluster/zones_file.go rename to pkg/cluster/cluster_file.go index b5adce5..306b3f2 100644 --- a/pkg/cluster/zones_file.go +++ b/pkg/cluster/cluster_file.go @@ -9,7 +9,7 @@ import ( ) // OpenFile opens a file on the cluster's config directory with the specified flags -func (m *Zones) OpenFile(name string, flags int, args ...any) (fs.File, error) { +func (m *Cluster) OpenFile(name string, flags int, args ...any) (fs.File, error) { if len(args) > 0 { name = fmt.Sprintf(name, args...) } @@ -18,16 +18,16 @@ func (m *Zones) OpenFile(name string, flags int, args ...any) (fs.File, error) { } // CreateTruncFile creates or truncates a file on the cluster's config directory -func (m *Zones) CreateTruncFile(name string, args ...any) (io.WriteCloser, error) { +func (m *Cluster) CreateTruncFile(name string, args ...any) (io.WriteCloser, error) { return m.openWriter(name, os.O_CREATE|os.O_TRUNC, args...) } // CreateFile creates a file on the cluster's config directory -func (m *Zones) CreateFile(name string, args ...any) (io.WriteCloser, error) { +func (m *Cluster) CreateFile(name string, args ...any) (io.WriteCloser, error) { return m.openWriter(name, os.O_CREATE, args...) } -func (m *Zones) openWriter(name string, flags int, args ...any) (io.WriteCloser, error) { +func (m *Cluster) openWriter(name string, flags int, args ...any) (io.WriteCloser, error) { f, err := m.OpenFile(name, os.O_WRONLY|flags, args...) if err != nil { return nil, err @@ -37,7 +37,7 @@ func (m *Zones) openWriter(name string, flags int, args ...any) (io.WriteCloser, } // ReadFile reads a file from the cluster's config directory -func (m *Zones) ReadFile(name string, args ...any) ([]byte, error) { +func (m *Cluster) ReadFile(name string, args ...any) ([]byte, error) { if len(args) > 0 { name = fmt.Sprintf(name, args...) } diff --git a/pkg/cluster/scan.go b/pkg/cluster/cluster_scan.go similarity index 89% rename from pkg/cluster/scan.go rename to pkg/cluster/cluster_scan.go index 090ba89..d148674 100644 --- a/pkg/cluster/scan.go +++ b/pkg/cluster/cluster_scan.go @@ -7,7 +7,7 @@ import ( "darvaza.org/core" ) -func (m *Zones) scan(opts *ScanOptions) error { +func (m *Cluster) scan(opts *ScanOptions) error { for _, fn := range []func(*ScanOptions) error{ m.scanDirectory, m.scanMachines, @@ -24,7 +24,7 @@ func (m *Zones) scan(opts *ScanOptions) error { return nil } -func (m *Zones) scanDirectory(_ *ScanOptions) error { +func (m *Cluster) scanDirectory(_ *ScanOptions) error { // each directory is a zone entries, err := fs.ReadDir(m.dir, ".") if err != nil { @@ -50,7 +50,7 @@ func (m *Zones) scanDirectory(_ *ScanOptions) error { return nil } -func (m *Zones) newZone(name string) (*Zone, error) { +func (m *Cluster) newZone(name string) (*Zone, error) { z := &Zone{ zones: m, logger: m, @@ -67,7 +67,7 @@ func (m *Zones) newZone(name string) (*Zone, error) { return z, nil } -func (m *Zones) scanMachines(opts *ScanOptions) error { +func (m *Cluster) scanMachines(opts *ScanOptions) error { var err error m.ForEachMachine(func(p *Machine) bool { err = p.scan(opts) @@ -76,7 +76,7 @@ func (m *Zones) scanMachines(opts *ScanOptions) error { return err } -func (m *Zones) scanZoneIDs(_ *ScanOptions) error { +func (m *Cluster) scanZoneIDs(_ *ScanOptions) error { var hasMissing bool var lastZoneID int @@ -106,7 +106,7 @@ func (m *Zones) scanZoneIDs(_ *ScanOptions) error { return nil } -func (m *Zones) scanSort(_ *ScanOptions) error { +func (m *Cluster) scanSort(_ *ScanOptions) error { sort.SliceStable(m.Zones, func(i, j int) bool { id1 := m.Zones[i].ID id2 := m.Zones[j].ID @@ -132,7 +132,7 @@ func (m *Zones) scanSort(_ *ScanOptions) error { return nil } -func (m *Zones) scanGateways(_ *ScanOptions) error { +func (m *Cluster) scanGateways(_ *ScanOptions) error { var err error m.ForEachZone(func(z *Zone) bool { diff --git a/pkg/cluster/options.go b/pkg/cluster/cluster_scan_options.go similarity index 79% rename from pkg/cluster/options.go rename to pkg/cluster/cluster_scan_options.go index b4f0ac2..0f71516 100644 --- a/pkg/cluster/options.go +++ b/pkg/cluster/cluster_scan_options.go @@ -11,7 +11,7 @@ import ( ) // A ScanOption pre-configures the Zones before scanning -type ScanOption func(*Zones, *ScanOptions) error +type ScanOption func(*Cluster, *ScanOptions) error // ScanOptions contains flags used by the initial scan type ScanOptions struct { @@ -29,7 +29,7 @@ type ScanOptions struct { // the DNS resolver to get PublicAddresses of nodes. // Default is true func ResolvePublicAddresses(resolve bool) ScanOption { - return func(m *Zones, opt *ScanOptions) error { + return func(m *Cluster, opt *ScanOptions) error { opt.DontResolvePublicAddresses = !resolve return nil } @@ -38,7 +38,7 @@ func ResolvePublicAddresses(resolve bool) ScanOption { // WithLookuper specifies what resolver.Lookuper to use to // find public addresses func WithLookuper(h resolver.Lookuper) ScanOption { - return func(m *Zones, opt *ScanOptions) error { + return func(m *Cluster, opt *ScanOptions) error { if h == nil { return fs.ErrInvalid } @@ -51,7 +51,7 @@ func WithLookuper(h resolver.Lookuper) ScanOption { // public addresses. if nil is passed, the [net.Resolver] will be used. // The default is using Cloudflare's 1.1.1.1. func WithResolver(h resolver.Resolver) ScanOption { - return func(m *Zones, opt *ScanOptions) error { + return func(m *Cluster, opt *ScanOptions) error { if h == nil { h = resolver.SystemResolver(true) } @@ -63,7 +63,7 @@ func WithResolver(h resolver.Resolver) ScanOption { // WithLogger specifies what to use for logging func WithLogger(log slog.Logger) ScanOption { - return func(m *Zones, opt *ScanOptions) error { + return func(m *Cluster, opt *ScanOptions) error { if log == nil { log = discard.New() } @@ -74,7 +74,7 @@ func WithLogger(log slog.Logger) ScanOption { } } -func (m *Zones) setDefaults(opt *ScanOptions) error { +func (m *Cluster) setDefaults(opt *ScanOptions) error { if m.resolver == nil { h := resolver.NewCloudflareLookuper() @@ -92,11 +92,11 @@ func (m *Zones) setDefaults(opt *ScanOptions) error { return nil } -// NewFS builds a [Zones] tree using the given directory -func NewFS(dir fs.FS, domain string, opts ...ScanOption) (*Zones, error) { +// NewFS builds a [Cluster] tree using the given directory +func NewFS(dir fs.FS, domain string, opts ...ScanOption) (*Cluster, error) { var scanOptions ScanOptions - z := &Zones{ + z := &Cluster{ dir: dir, domain: domain, } @@ -118,8 +118,8 @@ func NewFS(dir fs.FS, domain string, opts ...ScanOption) (*Zones, error) { return z, nil } -// New builds a [Zones] tree using the given directory -func New(dir, domain string, opts ...ScanOption) (*Zones, error) { +// New builds a [Cluster] tree using the given directory +func New(dir, domain string, opts ...ScanOption) (*Cluster, error) { dir, err := filepath.Abs(dir) if err != nil { return nil, err diff --git a/pkg/cluster/env.go b/pkg/cluster/env.go index 86439e4..cf5b171 100644 --- a/pkg/cluster/env.go +++ b/pkg/cluster/env.go @@ -16,7 +16,7 @@ type Env struct { } // Env returns a shell environment factory -func (m *Zones) Env(export bool) (*Env, error) { +func (m *Cluster) Env(export bool) (*Env, error) { fsid, err := m.GetCephFSID() if err != nil { return nil, err diff --git a/pkg/cluster/log.go b/pkg/cluster/log.go index d386041..7f01677 100644 --- a/pkg/cluster/log.go +++ b/pkg/cluster/log.go @@ -13,26 +13,26 @@ type logger interface { } var ( - _ logger = (*Zones)(nil) + _ logger = (*Cluster)(nil) ) -func (z *Zones) withDebug() (slog.Logger, bool) { +func (z *Cluster) withDebug() (slog.Logger, bool) { return z.debug().WithEnabled() } -func (z *Zones) withInfo() (slog.Logger, bool) { +func (z *Cluster) withInfo() (slog.Logger, bool) { return z.debug().WithEnabled() } -func (z *Zones) debug() slog.Logger { +func (z *Cluster) debug() slog.Logger { return z.log.Debug() } -func (z *Zones) info() slog.Logger { +func (z *Cluster) info() slog.Logger { return z.log.Info() } -func (z *Zones) warn(err error) slog.Logger { +func (z *Cluster) warn(err error) slog.Logger { l := z.log.Warn() if err != nil { l = l.WithField(slog.ErrorFieldName, err) @@ -40,7 +40,7 @@ func (z *Zones) warn(err error) slog.Logger { return l } -func (z *Zones) error(err error) slog.Logger { +func (z *Cluster) error(err error) slog.Logger { l := z.log.Error() if err != nil { l = l.WithField(slog.ErrorFieldName, err) diff --git a/pkg/cluster/sync.go b/pkg/cluster/sync.go index f8eb344..1c3fc2b 100644 --- a/pkg/cluster/sync.go +++ b/pkg/cluster/sync.go @@ -1,7 +1,7 @@ package cluster // SyncAll updates all config files -func (m *Zones) SyncAll() error { +func (m *Cluster) SyncAll() error { for _, fn := range []func() error{ m.SyncAllWireguard, m.SyncAllCeph, @@ -15,7 +15,7 @@ func (m *Zones) SyncAll() error { } // SyncAllWireguard updates all wireguard config files -func (m *Zones) SyncAllWireguard() error { +func (m *Cluster) SyncAllWireguard() error { var err error for ring := 0; ring < RingsCount; ring++ { @@ -34,7 +34,7 @@ func (m *Zones) SyncAllWireguard() error { } // SyncAllCeph updates the ceph.conf file -func (m *Zones) SyncAllCeph() error { +func (m *Cluster) SyncAllCeph() error { cfg, err := m.GenCephConfig() if err != nil { return err diff --git a/pkg/cluster/wireguard.go b/pkg/cluster/wireguard.go index 7bf94af..b6a801a 100644 --- a/pkg/cluster/wireguard.go +++ b/pkg/cluster/wireguard.go @@ -6,19 +6,19 @@ import ( ) var ( - _ WireguardConfigPruner = (*Zones)(nil) + _ WireguardConfigPruner = (*Cluster)(nil) _ WireguardConfigPruner = (*Zone)(nil) _ WireguardConfigPruner = (*Machine)(nil) - _ WireguardConfigWriter = (*Zones)(nil) + _ WireguardConfigWriter = (*Cluster)(nil) _ WireguardConfigWriter = (*Zone)(nil) _ WireguardConfigWriter = (*Machine)(nil) - _ WireguardConfigSyncer = (*Zones)(nil) + _ WireguardConfigSyncer = (*Cluster)(nil) _ WireguardConfigSyncer = (*Zone)(nil) _ WireguardConfigSyncer = (*Machine)(nil) - _ WireguardKeysWriter = (*Zones)(nil) + _ WireguardKeysWriter = (*Cluster)(nil) _ WireguardKeysWriter = (*Zone)(nil) _ WireguardKeysWriter = (*Machine)(nil) ) @@ -31,7 +31,7 @@ type WireguardConfigPruner interface { // PruneWireguardConfig removes wgN.conf files of machines with // the corresponding ring disabled on all zones -func (m *Zones) PruneWireguardConfig(ring int) error { +func (m *Cluster) PruneWireguardConfig(ring int) error { return pruneWireguardConfig(m, ring) } @@ -76,7 +76,7 @@ type WireguardConfigWriter interface { // WriteWireguardConfig rewrites all wgN.conf on all machines // attached to that ring -func (m *Zones) WriteWireguardConfig(ring int) error { +func (m *Cluster) WriteWireguardConfig(ring int) error { switch ring { case 0: return writeWireguardConfig(m, m, ring) @@ -154,7 +154,7 @@ type WireguardConfigSyncer interface { // SyncWireguardConfig updates all wgN.conf files for the specified // ring -func (m *Zones) SyncWireguardConfig(ring int) error { +func (m *Cluster) SyncWireguardConfig(ring int) error { switch ring { case 0: return syncWireguardConfig(m, m, ring) @@ -214,7 +214,7 @@ type WireguardKeysWriter interface { } // WriteWireguardKeys rewrites all wgN.{key,pub} files -func (m *Zones) WriteWireguardKeys(ring int) error { +func (m *Cluster) WriteWireguardKeys(ring int) error { return writeWireguardKeys(m, ring) } diff --git a/pkg/cluster/zones.go b/pkg/cluster/zones.go index 000c575..59898b9 100644 --- a/pkg/cluster/zones.go +++ b/pkg/cluster/zones.go @@ -2,16 +2,10 @@ package cluster import ( "io/fs" - - "darvaza.org/resolver" - "darvaza.org/slog" - "github.com/gofrs/uuid/v5" ) var ( _ MachineIterator = (*Zone)(nil) - _ MachineIterator = (*Zones)(nil) - _ ZoneIterator = (*Zones)(nil) ) // A ZoneIterator is a set of Zones we can iterate on @@ -19,9 +13,10 @@ type ZoneIterator interface { ForEachZone(func(*Zone) bool) } -// Zone represents one zone in a cluster +// A Zone is a set of machines in close proximity and strong +// affinity. type Zone struct { - zones *Zones + zones *Cluster logger `json:"-" yaml:"-"` ID int @@ -71,62 +66,3 @@ func (z *Zone) GatewayIDs() ([]int, int) { return out, len(out) } - -// revive:disable:line-length-limit - -// Zones represents all zones in a cluster -type Zones struct { - dir fs.FS - log slog.Logger - resolver resolver.Resolver - domain string - - CephFSID uuid.UUID `json:"ceph_fsid,omitempty" yaml:"ceph_fsid,omitempty"` - Zones []*Zone -} - -// revive:enable:line-length-limit - -// ForEachMachine calls a function for each Machine in the cluster -// until instructed to terminate the loop -func (m *Zones) ForEachMachine(fn func(*Machine) bool) { - m.ForEachZone(func(z *Zone) bool { - var term bool - - z.ForEachMachine(func(p *Machine) bool { - term = fn(p) - return term - }) - - return term - }) -} - -// ForEachZone calls a function for each Zone in the cluster -// until instructed to terminate the loop -func (m *Zones) ForEachZone(fn func(*Zone) bool) { - for _, p := range m.Zones { - if fn(p) { - // terminate - return - } - } -} - -// GetMachineByName looks for a machine with the specified -// name on any zone -func (m *Zones) GetMachineByName(name string) (*Machine, bool) { - var out *Machine - - if name != "" { - m.ForEachMachine(func(p *Machine) bool { - if p.Name == name { - out = p - } - - return out != nil - }) - } - - return out, out != nil -}