cluster

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2024 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package cluster contains information about the cluster

Index

Constants

View Source
const (
	// ZoneRegionsFileName indicates the file containing
	// region names as references
	ZoneRegionsFileName = "regions"

	// RegionClusterTokenFileName contains the kubernetes
	// token of the cluster this region represents
	RegionClusterTokenFileName = "k8s_token"
)
View Source
const (
	// MaxZoneID indicates the highest ID allowed for a Zone
	MaxZoneID = 0xf
	// MaxNodeID indicates the highest Machine ID allowed within a Zone
	MaxNodeID = 0xff - 1
	// RingsCount indicates how many wireguard rings we have
	RingsCount = 2
	// RingZeroPort is the port wireguard uses for ring0
	RingZeroPort = 51800
	// RingOnePort is the port wireguard uses for ring1
	RingOnePort = 51810
)

Variables

View Source
var (
	// ErrInvalidName indicates the name isn't valid
	ErrInvalidName = errors.New("invalid name")

	// ErrUnknownNode indicates there is a reference to a node
	// we don't have on the tree
	ErrUnknownNode = errors.New("node does not exist")

	// ErrInvalidNode indicates the nodes can't be used for
	// the intended purpose
	ErrInvalidNode = errors.New("invalid node")
)
View Source
var (
	// RingZero is a wg0 address encoder/decoder
	RingZero = RingAddressEncoder{
		ID:     0,
		Port:   RingZeroPort,
		Decode: ParseRingZeroAddress,
		Encode: RingZeroAddress,
	}
	// RingOne is a wg1 address encoder/decoder
	RingOne = RingAddressEncoder{
		ID:     1,
		Port:   RingOnePort,
		Decode: ParseRingOneAddress,
		Encode: RingOneAddress,
	}
	// Rings provides indexed access to the ring address encoders
	Rings = [RingsCount]RingAddressEncoder{
		RingZero,
		RingOne,
	}
)

Functions

func DefaultLogger

func DefaultLogger() slog.Logger

DefaultLogger returns a logger that doesn't log anything

func DefaultLookuper

func DefaultLookuper() resolver.Lookuper

DefaultLookuper returns a resolver.Lookuper using Cloudflare's 1.1.1.1

func DirFS added in v0.6.2

func DirFS(dir string) (fs.FS, error)

DirFS returns a file system (an [fs.FS]) for the tree of files rooted at the directory dir.

func ParseRingOneAddress

func ParseRingOneAddress(addr netip.Addr) (zoneID int, nodeID int, ok bool)

ParseRingOneAddress extracts zone and node ID from a wg1 netip.Addr wg1 addresses are of the form `10.{{zoneID << 4}}.{{nodeID}}`

func ParseRingZeroAddress

func ParseRingZeroAddress(addr netip.Addr) (zoneID int, nodeID int, ok bool)

ParseRingZeroAddress extracts zone and node ID from a wg0 netip.Addr wg0 addresses are of the form `10.0.{{zoneID}}.{{nodeID}}`

func RingOneAddress

func RingOneAddress(zoneID, nodeID int) (netip.Addr, bool)

RingOneAddress returns a wg1 IP address

func RingZeroAddress

func RingZeroAddress(zoneID, nodeID int) (netip.Addr, bool)

RingZeroAddress returns a wg0 IP address

func SortRegions added in v0.6.11

func SortRegions(regions []string) []string

SortRegions sorts regions. first by length those 3-character or shorter, and then by length. It's mostly aimed at supporting ISO-3166 order

func ValidNodeID

func ValidNodeID(nodeID int) bool

ValidNodeID checks if the given nodeID is a valid 8 bit number. nodeID is unique within a Zone. 0 is reserved, and only allowed when composing CIDRs.

func ValidZoneID

func ValidZoneID(zoneID int) bool

ValidZoneID checks if the given zoneID is a valid 4 bit zone number.

0 is reserved, and only allowed when composing CIDRs.

Types

type Cluster

type Cluster struct {
	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"`
	Regions  []Region  `json:",omitempty"          yaml:",omitempty"`
	Zones    []*Zone   `json:",omitempty"          yaml:",omitempty"`
	// contains filtered or unexported fields
}

Cluster represents all zones in a cluster

func NewFromConfig added in v0.6.2

func NewFromConfig(filename string, opts ...ScanOption) (*Cluster, error)

NewFromConfig loads the cluster data from the given file

func NewFromDirectory

func NewFromDirectory(dir, domain string, opts ...ScanOption) (*Cluster, error)

NewFromDirectory builds a Cluster tree using the given directory

func (*Cluster) CreateFile

func (m *Cluster) CreateFile(name string, args ...any) (io.WriteCloser, error)

CreateFile creates a file on the cluster's config directory

func (*Cluster) CreateTruncFile

func (m *Cluster) CreateTruncFile(name string, args ...any) (io.WriteCloser, error)

CreateTruncFile creates or truncates a file on the cluster's config directory

func (*Cluster) Env

func (m *Cluster) Env(export bool) (*Env, error)

Env returns a shell environment factory

func (*Cluster) ForEachMachine

func (m *Cluster) ForEachMachine(fn func(*Machine) bool)

ForEachMachine calls a function for each Machine in the cluster until instructed to terminate the loop

func (*Cluster) ForEachRegion added in v0.6.6

func (m *Cluster) ForEachRegion(fn func(r *Region) bool)

ForEachRegion calls a function for each Region of the cluster until instructed to terminate the loop

func (*Cluster) ForEachZone

func (m *Cluster) ForEachZone(fn func(*Zone) bool)

ForEachZone calls a function for each Zone in the cluster until instructed to terminate the loop

func (*Cluster) GenCephConfig

func (m *Cluster) GenCephConfig() (*ceph.Config, error)

GenCephConfig prepares a ceph.Config using the cluster information

func (*Cluster) GetCephConfig

func (m *Cluster) GetCephConfig() (*ceph.Config, error)

GetCephConfig reads the ceph.conf file

func (*Cluster) GetCephFSID

func (m *Cluster) GetCephFSID() (uuid.UUID, error)

GetCephFSID returns our Ceph's FSID

func (*Cluster) GetMachineByName

func (m *Cluster) GetMachineByName(name string) (*Machine, bool)

GetMachineByName looks for a machine with the specified name on any zone

func (*Cluster) MkdirAll added in v0.6.11

func (m *Cluster) MkdirAll(name string, args ...any) error

MkdirAll creates directories relative to the cluster's config directory

func (*Cluster) OpenFile

func (m *Cluster) OpenFile(name string, flags int, args ...any) (fs.File, error)

OpenFile opens a file on the cluster's config directory with the specified flags

func (*Cluster) PruneWireguardConfig

func (m *Cluster) PruneWireguardConfig(ring int) error

PruneWireguardConfig removes wgN.conf files of machines with the corresponding ring disabled on all zones

func (*Cluster) ReadFile

func (m *Cluster) ReadFile(name string, args ...any) ([]byte, error)

ReadFile reads a file from the cluster's config directory

func (*Cluster) ReadLines added in v0.6.11

func (m *Cluster) ReadLines(name string, args ...any) ([]string, error)

ReadLines reads a file from the cluster's config directory, split by lines, trimmed, and accepting `#` to comment lines out.

func (*Cluster) RemoveFile added in v0.6.11

func (m *Cluster) RemoveFile(name string, args ...any) error

RemoveFile deletes a file from the cluster's config directory

func (*Cluster) SyncAll

func (m *Cluster) SyncAll() error

SyncAll updates all config files

func (*Cluster) SyncAllCeph

func (m *Cluster) SyncAllCeph() error

SyncAllCeph updates the ceph.conf file

func (*Cluster) SyncAllRegions added in v0.6.12

func (m *Cluster) SyncAllRegions() error

SyncAllRegions rewrites all region data

func (*Cluster) SyncAllWireguard

func (m *Cluster) SyncAllWireguard() error

SyncAllWireguard updates all wireguard config files

func (*Cluster) SyncMkdirAll added in v0.6.11

func (m *Cluster) SyncMkdirAll() error

SyncMkdirAll creates the directories needed to store files required to represent the cluster.

func (*Cluster) SyncWireguardConfig

func (m *Cluster) SyncWireguardConfig(ring int) error

SyncWireguardConfig updates all wgN.conf files for the specified ring

func (*Cluster) WriteCephConfig

func (m *Cluster) WriteCephConfig(cfg *ceph.Config) error

WriteCephConfig writes the ceph.conf file

func (*Cluster) WriteHosts added in v0.6.1

func (m *Cluster) WriteHosts() error

WriteHosts rewrites all hosts files on the tree

func (*Cluster) WriteStringFile added in v0.6.11

func (m *Cluster) WriteStringFile(value string, name string, args ...any) error

WriteStringFile writes the given content to a file on the machine's config directory

func (*Cluster) WriteWireguardConfig

func (m *Cluster) WriteWireguardConfig(ring int) error

WriteWireguardConfig rewrites all wgN.conf on all machines attached to that ring

func (*Cluster) WriteWireguardKeys

func (m *Cluster) WriteWireguardKeys(ring int) error

WriteWireguardKeys rewrites all wgN.{key,pub} files

type Env

type Env struct {
	ZoneIterator
	RegionIterator
	// contains filtered or unexported fields
}

Env is a shell environment factory for this cluster

func (*Env) Regions added in v0.8.0

func (m *Env) Regions() []string

Regions returns the list of primary regions

func (*Env) WriteTo

func (m *Env) WriteTo(w io.Writer) (int64, error)

WriteTo generates environment variables for shell scripts

func (*Env) Zones

func (m *Env) Zones() []int

Zones returns the list of Zone IDs

type Machine

type Machine struct {
	ID   int
	Name string `json:"-" yaml:"-"`

	Inactive        bool         `json:"inactive,omitempty"     yaml:"inactive,omitempty"`
	CephMonitor     bool         `json:"ceph_monitor,omitempty" yaml:"ceph_monitor,omitempty"`
	PublicAddresses []netip.Addr `json:"public,omitempty"       yaml:"public,omitempty"`
	Rings           []*RingInfo  `json:"rings,omitempty"        yaml:"rings,omitempty"`
	// contains filtered or unexported fields
}

A Machine is a machine on a Zone

func (*Machine) CreateFile

func (m *Machine) CreateFile(name string, args ...any) (io.WriteCloser, error)

CreateFile creates a file on the machine's config directory

func (*Machine) CreateTruncFile

func (m *Machine) CreateTruncFile(name string, args ...any) (io.WriteCloser, error)

CreateTruncFile creates or truncates a file on the machine's config directory

func (*Machine) FullName

func (m *Machine) FullName() string

FullName returns the Name of the machine including domain name

func (*Machine) GetWireguardConfig

func (m *Machine) GetWireguardConfig(ring int) (*wireguard.Config, error)

GetWireguardConfig reads a wgN.conf file

func (*Machine) GetWireguardKeys

func (m *Machine) GetWireguardKeys(ring int) (wireguard.KeyPair, error)

GetWireguardKeys reads a wgN.key/wgN.pub files

func (*Machine) IsActive added in v0.6.11

func (m *Machine) IsActive() bool

IsActive indicates the machine is to be included in regions' DNS entries

func (*Machine) IsGateway

func (m *Machine) IsGateway() bool

IsGateway tells if the Machine is a ring0 gateway

func (*Machine) LookupNetIP

func (m *Machine) LookupNetIP(timeout time.Duration) ([]netip.Addr, error)

LookupNetIP uses the DNS Resolver to get the public addresses associated to a Machine

func (*Machine) MkdirAll added in v0.6.11

func (m *Machine) MkdirAll(name string, args ...any) error

MkdirAll creates directories relative to the machine's config directory

func (*Machine) OpenFile

func (m *Machine) OpenFile(name string, flags int, args ...any) (fs.File, error)

OpenFile opens a file on the machine's config directory with the specified flags

func (*Machine) PruneWireguardConfig

func (m *Machine) PruneWireguardConfig(ring int) error

PruneWireguardConfig deletes the wgN.conf file if its presence on the ring is disabled

func (*Machine) ReadFile

func (m *Machine) ReadFile(name string, args ...any) ([]byte, error)

ReadFile reads a file from the machine's config directory

func (*Machine) ReadLines added in v0.6.11

func (m *Machine) ReadLines(name string, args ...any) ([]string, error)

ReadLines reads a file from the machine's config directory, split by lines, trimmed, and accepting `#` to comment lines out.

func (*Machine) RemoveFile

func (m *Machine) RemoveFile(name string, args ...any) error

RemoveFile deletes a file from the machine's config directory

func (*Machine) RemoveWireguardConfig

func (m *Machine) RemoveWireguardConfig(ring int) error

RemoveWireguardConfig deletes wgN.conf from the machine's config directory.

func (*Machine) RemoveWireguardKeys

func (m *Machine) RemoveWireguardKeys(ring int) error

RemoveWireguardKeys deletes wgN.key and wgN.pub from the machine's config directory

func (*Machine) SetGateway

func (m *Machine) SetGateway(enabled bool) error

SetGateway enables/disables a Machine ring0 integration

func (*Machine) String

func (m *Machine) String() string

func (*Machine) SyncWireguardConfig

func (m *Machine) SyncWireguardConfig(ring int) error

SyncWireguardConfig updates all wgN.conf files for the specified ring

func (*Machine) UpdatePublicAddresses

func (m *Machine) UpdatePublicAddresses() error

UpdatePublicAddresses uses the DNS Resolver to set Machine.PublicAddresses

func (*Machine) WriteHosts added in v0.6.1

func (p *Machine) WriteHosts() error

WriteHosts rewrites the hosts file

func (*Machine) WriteStringFile

func (m *Machine) WriteStringFile(value string, name string, args ...any) error

WriteStringFile writes the given content to a file on the machine's config directory

func (*Machine) WriteWireguardConfig

func (m *Machine) WriteWireguardConfig(ring int) error

WriteWireguardConfig rewrites the wgN.conf file of this Machine if enabled

func (*Machine) WriteWireguardKeys

func (m *Machine) WriteWireguardKeys(ring int) error

WriteWireguardKeys writes the wgN.key/wgN.pub files

func (*Machine) Zone

func (m *Machine) Zone() int

Zone indicates the Zone this machine belongs to

type MachineIterator

type MachineIterator interface {
	ForEachMachine(func(*Machine) bool)
}

A MachineIterator is a set of Machines we can iterate on

type Machines

type Machines []*Machine

Machines is a list of Machine objects

func FilterMachines

func FilterMachines(m MachineIterator, cond func(*Machine) bool) (Machines, int)

FilterMachines produces a subset of the machines offered by the given iterator fulfilling a condition

func (Machines) ForEachMachine

func (m Machines) ForEachMachine(fn func(*Machine) bool)

ForEachMachine calls a function for each Machine in the list until instructed to terminate the loop

func (Machines) Len

func (m Machines) Len() int

Len returns the number of machines in the list

func (Machines) Less

func (m Machines) Less(i, j int) bool

Less implements sort.Interface to sort the list

func (Machines) Swap

func (m Machines) Swap(i, j int)

Swap implements sort.Interface to sort the list

type Region added in v0.6.4

type Region struct {
	Name    string
	Cluster *string  `json:",omitempty" yaml:",omitempty"`
	Regions []string `json:",omitempty" yaml:",omitempty"`
	// contains filtered or unexported fields
}

Region represents a group of zones geographically related

func (*Region) ForEachMachine added in v0.6.6

func (r *Region) ForEachMachine(fn func(*Machine) bool)

ForEachMachine calls a function for each Machine in the region until instructed to terminate the loop

func (*Region) ForEachZone added in v0.6.6

func (r *Region) ForEachZone(fn func(*Zone) bool)

ForEachZone calls a function for each Zone in the region until instructed to terminate the loop

func (*Region) SyncRegions added in v0.6.12

func (r *Region) SyncRegions() error

SyncRegions writes to the file system the regions covered by this meta-region

type RegionIterator added in v0.8.0

type RegionIterator interface {
	ForEachRegion(func(*Region) bool)
}

A RegionIterator is a set of Regions we can iterate on

type Ring

type Ring struct {
	RingAddressEncoder
	ZoneIterator

	Peers []*RingPeer
}

A Ring describes all peers on a ring

func NewRing

func NewRing(z ZoneIterator, m MachineIterator, ring int) (*Ring, error)

NewRing composes a new Ring for Wireguard setup

func (*Ring) AddPeer

func (r *Ring) AddPeer(p *Machine) bool

AddPeer adds a Machine to the ring

func (*Ring) ExportConfig

func (r *Ring) ExportConfig(p *Machine) (*wireguard.Config, error)

ExportConfig builds a wgN.conf for the specified machine on the ring

func (*Ring) ForEachMachine

func (r *Ring) ForEachMachine(fn func(*Machine) bool)

ForEachMachine calls a function for each Machine in the ring until instructed to terminate the loop

type RingAddressEncoder

type RingAddressEncoder struct {
	ID     int
	Port   uint16
	Encode func(zoneID, nodeID int) (netip.Addr, bool)
	Decode func(addr netip.Addr) (zoneID, nodeID int, ok bool)
}

RingAddressEncoder provides encoder/decoder access for a particular Wireguard ring

type RingInfo

type RingInfo struct {
	Ring    int
	Enabled bool
	Keys    wireguard.KeyPair
}

RingInfo contains represents the Wireguard endpoint details for a Machine on a particular ring

func (*RingInfo) Merge

func (ri *RingInfo) Merge(alter *RingInfo) error

Merge attempts to combine two RingInfo structs

type RingPeer

type RingPeer struct {
	Node *Machine

	Address    netip.Addr
	PrivateKey wireguard.PrivateKey
	PeerConfig wireguard.PeerConfig
}

A RingPeer is a node on a Ring

func (*RingPeer) AllowCIDR

func (rp *RingPeer) AllowCIDR(addr netip.Addr, bits int)

AllowCIDR allows an IP range via this peer

type ScanOption

type ScanOption func(*Cluster, *ScanOptions) error

A ScanOption pre-configures the Zones before scanning

func ResolvePublicAddresses

func ResolvePublicAddresses(resolve bool) ScanOption

ResolvePublicAddresses instructs the scanner to use the DNS resolver to get PublicAddresses of nodes. Default is true

func WithLogger

func WithLogger(log slog.Logger) ScanOption

WithLogger specifies what to use for logging

func WithLookuper

func WithLookuper(h resolver.Lookuper) ScanOption

WithLookuper specifies what resolver.Lookuper to use to find public addresses

func WithResolver

func WithResolver(h resolver.Resolver) ScanOption

WithResolver specifies what resolver to use to find public addresses. if nil is passed, the net.Resolver will be used. The default is using Cloudflare's 1.1.1.1.

type ScanOptions

type ScanOptions struct {
	// DontResolvePublicAddresses indicates we shouldn't
	// pre-populate Machine.PublicAddresses during the
	// initial scan
	DontResolvePublicAddresses bool

	// Logger specifies the logger to be used. otherwise
	// the scanner will be mute
	slog.Logger
}

ScanOptions contains flags used by the initial scan

type WireguardConfigPruner

type WireguardConfigPruner interface {
	PruneWireguardConfig(ring int) error
}

A WireguardConfigPruner deletes wgN.conf on all machines under its scope with the specified ring disabled

type WireguardConfigSyncer

type WireguardConfigSyncer interface {
	SyncWireguardConfig(ring int) error
}

A WireguardConfigSyncer updates all wgN.conf on all machines under its scope reflecting the state of the ring

type WireguardConfigWriter

type WireguardConfigWriter interface {
	WriteWireguardConfig(ring int) error
}

A WireguardConfigWriter rewrites all wgN.conf on all machines under its scope attached to that ring

type WireguardKeysWriter

type WireguardKeysWriter interface {
	WriteWireguardKeys(ring int) error
}

A WireguardKeysWriter writes the Wireguard Keys for all machines under its scope for the specified ring

type Zone

type Zone struct {
	ID      int
	Name    string
	Regions []string `json:",omitempty" yaml:",omitempty"`

	Machines
	// contains filtered or unexported fields
}

A Zone is a set of machines in close proximity and strong affinity.

func (*Zone) ForEachRegion added in v0.8.0

func (z *Zone) ForEachRegion(fn func(*Region) bool)

ForEachRegion calls a function on all regions this zone belongs to.

func (*Zone) GatewayIDs

func (z *Zone) GatewayIDs() ([]int, int)

GatewayIDs returns the list of IDs of machines that act as ring0 gateways

func (*Zone) GetCephMonitors

func (z *Zone) GetCephMonitors() Machines

GetCephMonitors returns the set of Ceph monitors on the zone

func (*Zone) GetGateway

func (z *Zone) GetGateway() (*Machine, bool, error)

GetGateway returns the first gateway found, if none files will be created to enable the first Machine to be one

func (*Zone) Hosts added in v0.6.1

func (z *Zone) Hosts() string

Hosts renders the /etc/hosts to be used on this zone

func (*Zone) PruneWireguardConfig

func (z *Zone) PruneWireguardConfig(ring int) error

PruneWireguardConfig removes wgN.conf files of machines with the corresponding ring disabled.

func (*Zone) SetGateway

func (z *Zone) SetGateway(gatewayID int, enabled bool) error

SetGateway configures a machine to be the zone's ring0 gateway

func (*Zone) String

func (z *Zone) String() string

func (*Zone) SyncRegions added in v0.6.12

func (z *Zone) SyncRegions() error

SyncRegions writes to the file system the regions this Zone belongs to.

func (*Zone) SyncWireguardConfig

func (z *Zone) SyncWireguardConfig(ring int) error

SyncWireguardConfig updates all wgN.conf files for the specified ring

func (*Zone) WriteHosts added in v0.6.1

func (z *Zone) WriteHosts() error

WriteHosts rewrites all hosts files in the zone

func (*Zone) WriteWireguardConfig

func (z *Zone) WriteWireguardConfig(ring int) error

WriteWireguardConfig rewrites all wgN.conf on all machines on the Zone attached to that ring

func (*Zone) WriteWireguardKeys

func (z *Zone) WriteWireguardKeys(ring int) error

WriteWireguardKeys rewrites all wgN.{key,pub} files on this zone

type ZoneIterator

type ZoneIterator interface {
	ForEachZone(func(*Zone) bool)
}

A ZoneIterator is a set of Zones we can iterate on

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL