From 5abb4c2f9232b5b5f914165fce442e7cca2bfb97 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Sun, 10 Sep 2023 19:01:36 +0000 Subject: [PATCH 1/5] cluster: rename pkg/zones to pkg/cluster Signed-off-by: Alejandro Mery --- cmd/jpictl/config.go | 10 +++++----- cmd/jpictl/gateway.go | 19 ++++++++++--------- pkg/{zones => cluster}/ceph.go | 2 +- pkg/{zones => cluster}/ceph_scan.go | 2 +- pkg/cluster/cluster.go | 2 ++ pkg/{zones => cluster}/env.go | 2 +- pkg/{zones => cluster}/errors.go | 2 +- pkg/{zones => cluster}/log.go | 2 +- pkg/{zones => cluster}/machine.go | 2 +- pkg/{zones => cluster}/machine_file.go | 2 +- pkg/{zones => cluster}/machine_rings.go | 2 +- pkg/{zones => cluster}/machine_scan.go | 2 +- pkg/{zones => cluster}/options.go | 2 +- pkg/{zones => cluster}/rings.go | 2 +- pkg/{zones => cluster}/scan.go | 2 +- pkg/{zones => cluster}/sync.go | 2 +- pkg/{zones => cluster}/wireguard.go | 2 +- pkg/{zones => cluster}/zones.go | 3 +-- pkg/{zones => cluster}/zones_file.go | 2 +- 19 files changed, 33 insertions(+), 31 deletions(-) rename pkg/{zones => cluster}/ceph.go (99%) rename pkg/{zones => cluster}/ceph_scan.go (99%) create mode 100644 pkg/cluster/cluster.go rename pkg/{zones => cluster}/env.go (99%) rename pkg/{zones => cluster}/errors.go (96%) rename pkg/{zones => cluster}/log.go (98%) rename pkg/{zones => cluster}/machine.go (98%) rename pkg/{zones => cluster}/machine_file.go (99%) rename pkg/{zones => cluster}/machine_rings.go (99%) rename pkg/{zones => cluster}/machine_scan.go (99%) rename pkg/{zones => cluster}/options.go (99%) rename pkg/{zones => cluster}/rings.go (99%) rename pkg/{zones => cluster}/scan.go (99%) rename pkg/{zones => cluster}/sync.go (97%) rename pkg/{zones => cluster}/wireguard.go (99%) rename pkg/{zones => cluster}/zones.go (98%) rename pkg/{zones => cluster}/zones_file.go (98%) diff --git a/cmd/jpictl/config.go b/cmd/jpictl/config.go index d58439d..df1cd7c 100644 --- a/cmd/jpictl/config.go +++ b/cmd/jpictl/config.go @@ -1,6 +1,6 @@ package main -import "git.jpi.io/amery/jpictl/pkg/zones" +import "git.jpi.io/amery/jpictl/pkg/cluster" // Config describes the repository type Config struct { @@ -14,9 +14,9 @@ var cfg = &Config{ } // LoadZones loads all zones and machines in the config directory -func (cfg *Config) LoadZones(resolve bool) (*zones.Zones, error) { - return zones.New(cfg.Base, cfg.Domain, - zones.ResolvePublicAddresses(resolve), - zones.WithLogger(log), +func (cfg *Config) LoadZones(resolve bool) (*cluster.Zones, error) { + return cluster.New(cfg.Base, cfg.Domain, + cluster.ResolvePublicAddresses(resolve), + cluster.WithLogger(log), ) } diff --git a/cmd/jpictl/gateway.go b/cmd/jpictl/gateway.go index 41b869b..a2489e3 100644 --- a/cmd/jpictl/gateway.go +++ b/cmd/jpictl/gateway.go @@ -7,8 +7,9 @@ import ( "strconv" "strings" - "git.jpi.io/amery/jpictl/pkg/zones" "github.com/spf13/cobra" + + "git.jpi.io/amery/jpictl/pkg/cluster" ) // Command @@ -38,9 +39,9 @@ var gatewaySetCmd = &cobra.Command{ }, } -func gatewaySet(zi zones.ZoneIterator, gw string) error { +func gatewaySet(zi cluster.ZoneIterator, gw string) error { var err error - zi.ForEachZone(func(z *zones.Zone) bool { + zi.ForEachZone(func(z *cluster.Zone) bool { for _, m := range z.Machines { if m.Name == gw { z.SetGateway(m.ID, true) @@ -74,9 +75,9 @@ var gatewayUnsetCmd = &cobra.Command{ }, } -func gatewayUnset(zi zones.ZoneIterator, ngw string) error { +func gatewayUnset(zi cluster.ZoneIterator, ngw string) error { var err error - zi.ForEachZone(func(z *zones.Zone) bool { + zi.ForEachZone(func(z *cluster.Zone) bool { for _, m := range z.Machines { if m.Name == ngw && m.IsGateway() { z.SetGateway(m.ID, false) @@ -115,10 +116,10 @@ var gatewayListCmd = &cobra.Command{ }, } -func gatewayListAll(zi zones.ZoneIterator) error { +func gatewayListAll(zi cluster.ZoneIterator) error { var b bytes.Buffer var err error - zi.ForEachZone(func(z *zones.Zone) bool { + zi.ForEachZone(func(z *cluster.Zone) bool { b.WriteString(z.Name + ":") var sIDs []string ids, num := z.GatewayIDs() @@ -137,10 +138,10 @@ func gatewayListAll(zi zones.ZoneIterator) error { return err } -func gatewayList(zi zones.ZoneIterator, m string) error { +func gatewayList(zi cluster.ZoneIterator, m string) error { var b bytes.Buffer var err error - zi.ForEachZone(func(z *zones.Zone) bool { + zi.ForEachZone(func(z *cluster.Zone) bool { if z.Name == m { b.WriteString(z.Name + ":") ids, num := z.GatewayIDs() diff --git a/pkg/zones/ceph.go b/pkg/cluster/ceph.go similarity index 99% rename from pkg/zones/ceph.go rename to pkg/cluster/ceph.go index 676339b..185dc3d 100644 --- a/pkg/zones/ceph.go +++ b/pkg/cluster/ceph.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "bytes" diff --git a/pkg/zones/ceph_scan.go b/pkg/cluster/ceph_scan.go similarity index 99% rename from pkg/zones/ceph_scan.go rename to pkg/cluster/ceph_scan.go index 7cb4f37..a64e2d7 100644 --- a/pkg/zones/ceph_scan.go +++ b/pkg/cluster/ceph_scan.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "os" diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go new file mode 100644 index 0000000..bd55f18 --- /dev/null +++ b/pkg/cluster/cluster.go @@ -0,0 +1,2 @@ +// Package cluster contains information about the cluster +package cluster diff --git a/pkg/zones/env.go b/pkg/cluster/env.go similarity index 99% rename from pkg/zones/env.go rename to pkg/cluster/env.go index 8780da9..86439e4 100644 --- a/pkg/zones/env.go +++ b/pkg/cluster/env.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "bytes" diff --git a/pkg/zones/errors.go b/pkg/cluster/errors.go similarity index 96% rename from pkg/zones/errors.go rename to pkg/cluster/errors.go index 6fd068f..9035d36 100644 --- a/pkg/zones/errors.go +++ b/pkg/cluster/errors.go @@ -1,4 +1,4 @@ -package zones +package cluster import "errors" diff --git a/pkg/zones/log.go b/pkg/cluster/log.go similarity index 98% rename from pkg/zones/log.go rename to pkg/cluster/log.go index ceaf5ee..d386041 100644 --- a/pkg/zones/log.go +++ b/pkg/cluster/log.go @@ -1,4 +1,4 @@ -package zones +package cluster import "darvaza.org/slog" diff --git a/pkg/zones/machine.go b/pkg/cluster/machine.go similarity index 98% rename from pkg/zones/machine.go rename to pkg/cluster/machine.go index e8f3dbe..d8c38f1 100644 --- a/pkg/zones/machine.go +++ b/pkg/cluster/machine.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "net/netip" diff --git a/pkg/zones/machine_file.go b/pkg/cluster/machine_file.go similarity index 99% rename from pkg/zones/machine_file.go rename to pkg/cluster/machine_file.go index 6fd0eac..a6e90eb 100644 --- a/pkg/zones/machine_file.go +++ b/pkg/cluster/machine_file.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "bytes" diff --git a/pkg/zones/machine_rings.go b/pkg/cluster/machine_rings.go similarity index 99% rename from pkg/zones/machine_rings.go rename to pkg/cluster/machine_rings.go index 4baaaee..cffcd4f 100644 --- a/pkg/zones/machine_rings.go +++ b/pkg/cluster/machine_rings.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "bytes" diff --git a/pkg/zones/machine_scan.go b/pkg/cluster/machine_scan.go similarity index 99% rename from pkg/zones/machine_scan.go rename to pkg/cluster/machine_scan.go index cb5a1be..e282800 100644 --- a/pkg/zones/machine_scan.go +++ b/pkg/cluster/machine_scan.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "context" diff --git a/pkg/zones/options.go b/pkg/cluster/options.go similarity index 99% rename from pkg/zones/options.go rename to pkg/cluster/options.go index e7a66f2..b4f0ac2 100644 --- a/pkg/zones/options.go +++ b/pkg/cluster/options.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "io/fs" diff --git a/pkg/zones/rings.go b/pkg/cluster/rings.go similarity index 99% rename from pkg/zones/rings.go rename to pkg/cluster/rings.go index 3a88a8e..64cae1c 100644 --- a/pkg/zones/rings.go +++ b/pkg/cluster/rings.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "fmt" diff --git a/pkg/zones/scan.go b/pkg/cluster/scan.go similarity index 99% rename from pkg/zones/scan.go rename to pkg/cluster/scan.go index c7b4eef..090ba89 100644 --- a/pkg/zones/scan.go +++ b/pkg/cluster/scan.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "io/fs" diff --git a/pkg/zones/sync.go b/pkg/cluster/sync.go similarity index 97% rename from pkg/zones/sync.go rename to pkg/cluster/sync.go index b7c8b89..f8eb344 100644 --- a/pkg/zones/sync.go +++ b/pkg/cluster/sync.go @@ -1,4 +1,4 @@ -package zones +package cluster // SyncAll updates all config files func (m *Zones) SyncAll() error { diff --git a/pkg/zones/wireguard.go b/pkg/cluster/wireguard.go similarity index 99% rename from pkg/zones/wireguard.go rename to pkg/cluster/wireguard.go index 35888db..7bf94af 100644 --- a/pkg/zones/wireguard.go +++ b/pkg/cluster/wireguard.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "io/fs" diff --git a/pkg/zones/zones.go b/pkg/cluster/zones.go similarity index 98% rename from pkg/zones/zones.go rename to pkg/cluster/zones.go index 952b305..26d9bb8 100644 --- a/pkg/zones/zones.go +++ b/pkg/cluster/zones.go @@ -1,5 +1,4 @@ -// Package zones contains information about the cluster -package zones +package cluster import ( "io/fs" diff --git a/pkg/zones/zones_file.go b/pkg/cluster/zones_file.go similarity index 98% rename from pkg/zones/zones_file.go rename to pkg/cluster/zones_file.go index b711163..b5adce5 100644 --- a/pkg/zones/zones_file.go +++ b/pkg/cluster/zones_file.go @@ -1,4 +1,4 @@ -package zones +package cluster import ( "fmt" From bedf62977fb24c3f36a1c60b07395093db9fb0d5 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Sun, 10 Sep 2023 19:08:13 +0000 Subject: [PATCH 2/5] cluster: move Machines to a dedicated file Signed-off-by: Alejandro Mery --- pkg/cluster/machines.go | 69 +++++++++++++++++++++++++++++++++++++++++ pkg/cluster/zones.go | 65 -------------------------------------- 2 files changed, 69 insertions(+), 65 deletions(-) create mode 100644 pkg/cluster/machines.go diff --git a/pkg/cluster/machines.go b/pkg/cluster/machines.go new file mode 100644 index 0000000..e49f2d5 --- /dev/null +++ b/pkg/cluster/machines.go @@ -0,0 +1,69 @@ +package cluster + +import "sort" + +var ( + _ MachineIterator = Machines(nil) + _ sort.Interface = Machines(nil) +) + +// A MachineIterator is a set of Machines we can iterate on +type MachineIterator interface { + ForEachMachine(func(*Machine) bool) +} + +// Machines is a list of Machine objects +type Machines []*Machine + +// ForEachMachine calls a function for each Machine in the list +// until instructed to terminate the loop +func (m Machines) ForEachMachine(fn func(*Machine) bool) { + for _, p := range m { + if fn(p) { + return + } + } +} + +// Len returns the number of machines in the list +func (m Machines) Len() int { + return len(m) +} + +// Less implements sort.Interface to sort the list +func (m Machines) Less(i, j int) bool { + a, b := m[i], m[j] + za, zb := a.Zone(), b.Zone() + + switch { + case za == zb: + return a.ID < b.ID + default: + return za < zb + } +} + +// Swap implements sort.Interface to sort the list +func (m Machines) Swap(i, j int) { + m[i], m[j] = m[j], m[i] +} + +// FilterMachines produces a subset of the machines offered by the given +// iterator fulfilling a condition +func FilterMachines(m MachineIterator, cond func(*Machine) bool) (Machines, int) { + var out []*Machine + + if cond == nil { + // unconditional + cond = func(*Machine) bool { return true } + } + + m.ForEachMachine(func(p *Machine) bool { + if cond(p) { + out = append(out, p) + } + return false + }) + + return out, len(out) +} diff --git a/pkg/cluster/zones.go b/pkg/cluster/zones.go index 26d9bb8..000c575 100644 --- a/pkg/cluster/zones.go +++ b/pkg/cluster/zones.go @@ -2,7 +2,6 @@ package cluster import ( "io/fs" - "sort" "darvaza.org/resolver" "darvaza.org/slog" @@ -10,80 +9,16 @@ import ( ) var ( - _ MachineIterator = Machines(nil) - _ sort.Interface = Machines(nil) - _ MachineIterator = (*Zone)(nil) _ MachineIterator = (*Zones)(nil) _ ZoneIterator = (*Zones)(nil) ) -// A MachineIterator is a set of Machines we can iterate on -type MachineIterator interface { - ForEachMachine(func(*Machine) bool) -} - // A ZoneIterator is a set of Zones we can iterate on type ZoneIterator interface { ForEachZone(func(*Zone) bool) } -// Machines is a list of Machine objects -type Machines []*Machine - -// ForEachMachine calls a function for each Machine in the list -// until instructed to terminate the loop -func (m Machines) ForEachMachine(fn func(*Machine) bool) { - for _, p := range m { - if fn(p) { - return - } - } -} - -// Len returns the number of machines in the list -func (m Machines) Len() int { - return len(m) -} - -// Less implements sort.Interface to sort the list -func (m Machines) Less(i, j int) bool { - a, b := m[i], m[j] - za, zb := a.Zone(), b.Zone() - - switch { - case za == zb: - return a.ID < b.ID - default: - return za < zb - } -} - -// Swap implements sort.Interface to sort the list -func (m Machines) Swap(i, j int) { - m[i], m[j] = m[j], m[i] -} - -// FilterMachines produces a subset of the machines offered by the given -// iterator fulfilling a condition -func FilterMachines(m MachineIterator, cond func(*Machine) bool) (Machines, int) { - var out []*Machine - - if cond == nil { - // unconditional - cond = func(*Machine) bool { return true } - } - - m.ForEachMachine(func(p *Machine) bool { - if cond(p) { - out = append(out, p) - } - return false - }) - - return out, len(out) -} - // Zone represents one zone in a cluster type Zone struct { zones *Zones From 24059dc9eec830f1a2533f5a1a81eaa64520f7d9 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Sun, 10 Sep 2023 19:16:36 +0000 Subject: [PATCH 3/5] 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 -} From 2a2e6c121edc47280591c08e38a5b90cccd4375f Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Sun, 10 Sep 2023 18:41:58 +0000 Subject: [PATCH 4/5] cluster: group default option factories Signed-off-by: Alejandro Mery --- pkg/cluster/cluster_scan_options.go | 5 ++--- pkg/cluster/defaults.go | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 pkg/cluster/defaults.go diff --git a/pkg/cluster/cluster_scan_options.go b/pkg/cluster/cluster_scan_options.go index 0f71516..8284e9f 100644 --- a/pkg/cluster/cluster_scan_options.go +++ b/pkg/cluster/cluster_scan_options.go @@ -6,7 +6,6 @@ import ( "darvaza.org/resolver" "darvaza.org/slog" - "darvaza.org/slog/handlers/discard" "github.com/hack-pad/hackpadfs/os" ) @@ -65,7 +64,7 @@ func WithResolver(h resolver.Resolver) ScanOption { func WithLogger(log slog.Logger) ScanOption { return func(m *Cluster, opt *ScanOptions) error { if log == nil { - log = discard.New() + log = DefaultLogger() } opt.Logger = log @@ -76,7 +75,7 @@ func WithLogger(log slog.Logger) ScanOption { func (m *Cluster) setDefaults(opt *ScanOptions) error { if m.resolver == nil { - h := resolver.NewCloudflareLookuper() + h := DefaultLookuper() if err := WithLookuper(h)(m, opt); err != nil { return err diff --git a/pkg/cluster/defaults.go b/pkg/cluster/defaults.go new file mode 100644 index 0000000..925b3d5 --- /dev/null +++ b/pkg/cluster/defaults.go @@ -0,0 +1,17 @@ +package cluster + +import ( + "darvaza.org/resolver" + "darvaza.org/slog" + "darvaza.org/slog/handlers/discard" +) + +// DefaultLogger returns a logger that doesn't log anything +func DefaultLogger() slog.Logger { + return discard.New() +} + +// DefaultLookuper returns a [resolver.Lookuper] using Cloudflare's 1.1.1.1 +func DefaultLookuper() resolver.Lookuper { + return resolver.NewCloudflareLookuper() +} From d0b0698c103bc9a8a77d09cde897f812d11f7e48 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Sun, 10 Sep 2023 21:38:07 +0000 Subject: [PATCH 5/5] cluster: make domain, basedir and cluster name public fields Signed-off-by: Alejandro Mery --- cmd/jpictl/config.go | 6 ++-- pkg/cluster/cluster.go | 7 +++-- pkg/cluster/cluster_scan_options.go | 46 ++++++++++++++--------------- pkg/cluster/machine.go | 17 ++++++----- 4 files changed, 40 insertions(+), 36 deletions(-) diff --git a/cmd/jpictl/config.go b/cmd/jpictl/config.go index dba4f2f..a7649fc 100644 --- a/cmd/jpictl/config.go +++ b/cmd/jpictl/config.go @@ -9,13 +9,13 @@ type Config struct { } var cfg = &Config{ - Base: "./m", - Domain: "m.jpi.cloud", + Base: "m", + Domain: "jpi.cloud", } // LoadZones loads all zones and machines in the config directory func (cfg *Config) LoadZones(resolve bool) (*cluster.Cluster, error) { - return cluster.New(cfg.Base, cfg.Domain, + return cluster.NewFromDirectory(cfg.Base, cfg.Domain, cluster.ResolvePublicAddresses(resolve), cluster.WithLogger(log), ) diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index 8475fb8..654333a 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -21,10 +21,13 @@ type Cluster struct { dir fs.FS log slog.Logger resolver resolver.Resolver - domain string + + BaseDir string `json:"dir,omitempty" yaml:"dir,omitempty"` + Name string `json:"name,omitempty" yaml:"name,omitempty"` + Domain string `json:"domain,omitempty" yaml:"domain,omitempty"` CephFSID uuid.UUID `json:"ceph_fsid,omitempty" yaml:"ceph_fsid,omitempty"` - Zones []*Zone + Zones []*Zone `json:"zones,omitempty" yaml:"zones,omitempty"` } // revive:enable:line-length-limit diff --git a/pkg/cluster/cluster_scan_options.go b/pkg/cluster/cluster_scan_options.go index 8284e9f..53d2a28 100644 --- a/pkg/cluster/cluster_scan_options.go +++ b/pkg/cluster/cluster_scan_options.go @@ -73,7 +73,7 @@ func WithLogger(log slog.Logger) ScanOption { } } -func (m *Cluster) setDefaults(opt *ScanOptions) error { +func (m *Cluster) setScanDefaults(opt *ScanOptions) error { if m.resolver == nil { h := DefaultLookuper() @@ -91,43 +91,41 @@ func (m *Cluster) setDefaults(opt *ScanOptions) error { return nil } -// NewFS builds a [Cluster] tree using the given directory -func NewFS(dir fs.FS, domain string, opts ...ScanOption) (*Cluster, error) { +// NewFromDirectory builds a [Cluster] tree using the given directory +func NewFromDirectory(dir, domain string, opts ...ScanOption) (*Cluster, error) { var scanOptions ScanOptions - z := &Cluster{ - dir: dir, - domain: domain, - } - - for _, opt := range opts { - if err := opt(z, &scanOptions); err != nil { - return nil, err - } + dir = filepath.Clean(dir) + fullPath, err := filepath.Abs(dir) + if err != nil { + return nil, err } - if err := z.setDefaults(&scanOptions); err != nil { + sub, err := os.NewFS().Sub(fullPath[1:]) + if err != nil { return nil, err } - if err := z.scan(&scanOptions); err != nil { - return nil, err + m := &Cluster{ + dir: sub, + BaseDir: dir, + Name: filepath.Base(fullPath), + Domain: domain, } - return z, nil -} + for _, opt := range opts { + if err := opt(m, &scanOptions); err != nil { + return nil, err + } + } -// 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 { + if err := m.setScanDefaults(&scanOptions); err != nil { return nil, err } - base, err := os.NewFS().Sub(dir[1:]) - if err != nil { + if err := m.scan(&scanOptions); err != nil { return nil, err } - return NewFS(base, domain, opts...) + return m, nil } diff --git a/pkg/cluster/machine.go b/pkg/cluster/machine.go index d8c38f1..46ac7e9 100644 --- a/pkg/cluster/machine.go +++ b/pkg/cluster/machine.go @@ -28,16 +28,19 @@ func (m *Machine) String() string { // FullName returns the Name of the machine including domain name func (m *Machine) FullName() string { - if domain := m.zone.zones.domain; domain != "" { - var s = []string{ - m.Name, - domain, + var name []string + + for _, s := range []string{ + m.Name, + m.zone.zones.Name, + m.zone.zones.Domain, + } { + if s != "" { + name = append(name, s) } - - return strings.Join(s, ".") } - return m.Name + return strings.Join(name, ".") } // IsGateway tells if the Machine is a ring0 gateway