move pkg/zones to pkg/cluster and other rearrangements #18
Merged
amery
merged 5 commits from pr-amery-cluster
into main
1 year ago
22 changed files with 338 additions and 304 deletions
@ -0,0 +1,77 @@
|
||||
// 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 |
||||
|
||||
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 `json:"zones,omitempty" yaml:"zones,omitempty"` |
||||
} |
||||
|
||||
// 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 |
||||
} |
@ -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() |
||||
} |
@ -1,4 +1,4 @@
|
||||
package zones |
||||
package cluster |
||||
|
||||
import "errors" |
||||
|
@ -1,4 +1,4 @@
|
||||
package zones |
||||
package cluster |
||||
|
||||
import ( |
||||
"bytes" |
@ -1,4 +1,4 @@
|
||||
package zones |
||||
package cluster |
||||
|
||||
import ( |
||||
"bytes" |
@ -1,4 +1,4 @@
|
||||
package zones |
||||
package cluster |
||||
|
||||
import ( |
||||
"context" |
@ -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) |
||||
} |
@ -1,4 +1,4 @@
|
||||
package zones |
||||
package cluster |
||||
|
||||
import ( |
||||
"fmt" |
@ -0,0 +1,68 @@
|
||||
package cluster |
||||
|
||||
import ( |
||||
"io/fs" |
||||
) |
||||
|
||||
var ( |
||||
_ MachineIterator = (*Zone)(nil) |
||||
) |
||||
|
||||
// A ZoneIterator is a set of Zones we can iterate on
|
||||
type ZoneIterator interface { |
||||
ForEachZone(func(*Zone) bool) |
||||
} |
||||
|
||||
// A Zone is a set of machines in close proximity and strong
|
||||
// affinity.
|
||||
type Zone struct { |
||||
zones *Cluster |
||||
logger `json:"-" yaml:"-"` |
||||
|
||||
ID int |
||||
Name string |
||||
|
||||
Machines |
||||
} |
||||
|
||||
func (z *Zone) String() string { |
||||
return z.Name |
||||
} |
||||
|
||||
// SetGateway configures a machine to be the zone's ring0 gateway
|
||||
func (z *Zone) SetGateway(gatewayID int, enabled bool) error { |
||||
var err error |
||||
var found bool |
||||
|
||||
z.ForEachMachine(func(p *Machine) bool { |
||||
if p.ID == gatewayID { |
||||
found = true |
||||
err = p.SetGateway(enabled) |
||||
|
||||
return true |
||||
} |
||||
return false |
||||
}) |
||||
|
||||
switch { |
||||
case err != nil: |
||||
return err |
||||
case !found: |
||||
return fs.ErrNotExist |
||||
default: |
||||
return nil |
||||
} |
||||
} |
||||
|
||||
// GatewayIDs returns the list of IDs of machines that act as ring0 gateways
|
||||
func (z *Zone) GatewayIDs() ([]int, int) { |
||||
var out []int |
||||
z.ForEachMachine(func(p *Machine) bool { |
||||
if p.IsGateway() { |
||||
out = append(out, p.ID) |
||||
} |
||||
return false |
||||
}) |
||||
|
||||
return out, len(out) |
||||
} |
@ -1,198 +0,0 @@
|
||||
// Package zones contains information about the cluster
|
||||
package zones |
||||
|
||||
import ( |
||||
"io/fs" |
||||
"sort" |
||||
|
||||
"darvaza.org/resolver" |
||||
"darvaza.org/slog" |
||||
"github.com/gofrs/uuid/v5" |
||||
) |
||||
|
||||
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 |
||||
logger `json:"-" yaml:"-"` |
||||
|
||||
ID int |
||||
Name string |
||||
|
||||
Machines |
||||
} |
||||
|
||||
func (z *Zone) String() string { |
||||
return z.Name |
||||
} |
||||
|
||||
// SetGateway configures a machine to be the zone's ring0 gateway
|
||||
func (z *Zone) SetGateway(gatewayID int, enabled bool) error { |
||||
var err error |
||||
var found bool |
||||
|
||||
z.ForEachMachine(func(p *Machine) bool { |
||||
if p.ID == gatewayID { |
||||
found = true |
||||
err = p.SetGateway(enabled) |
||||
|
||||
return true |
||||
} |
||||
return false |
||||
}) |
||||
|
||||
switch { |
||||
case err != nil: |
||||
return err |
||||
case !found: |
||||
return fs.ErrNotExist |
||||
default: |
||||
return nil |
||||
} |
||||
} |
||||
|
||||
// GatewayIDs returns the list of IDs of machines that act as ring0 gateways
|
||||
func (z *Zone) GatewayIDs() ([]int, int) { |
||||
var out []int |
||||
z.ForEachMachine(func(p *Machine) bool { |
||||
if p.IsGateway() { |
||||
out = append(out, p.ID) |
||||
} |
||||
return false |
||||
}) |
||||
|
||||
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 |
||||
} |
Loading…
Reference in new issue