You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
2.7 KiB

package cluster
import (
"io/fs"
"path/filepath"
"darvaza.org/resolver"
"darvaza.org/slog"
)
// A ScanOption pre-configures the Zones before scanning
type ScanOption func(*Cluster, *ScanOptions) error
// ScanOptions contains flags used by the initial scan
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
}
// ResolvePublicAddresses instructs the scanner to use
// the DNS resolver to get PublicAddresses of nodes.
// Default is true
func ResolvePublicAddresses(resolve bool) ScanOption {
return func(_ *Cluster, opt *ScanOptions) error {
opt.DontResolvePublicAddresses = !resolve
return nil
}
}
// WithLookuper specifies what resolver.Lookuper to use to
// find public addresses
func WithLookuper(h resolver.Lookuper) ScanOption {
return func(m *Cluster, _ *ScanOptions) error {
if h == nil {
return fs.ErrInvalid
}
m.resolver = resolver.NewResolver(h)
return nil
}
}
// 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.
func WithResolver(h resolver.Resolver) ScanOption {
return func(m *Cluster, _ *ScanOptions) error {
if h == nil {
h = resolver.SystemResolver(true)
}
m.resolver = h
return nil
}
}
// WithLogger specifies what to use for logging
func WithLogger(log slog.Logger) ScanOption {
return func(m *Cluster, opt *ScanOptions) error {
if log == nil {
log = DefaultLogger()
}
opt.Logger = log
m.log = log
return nil
}
}
func (m *Cluster) setScanDefaults(opt *ScanOptions) error {
if m.resolver == nil {
h := DefaultLookuper()
if err := WithLookuper(h)(m, opt); err != nil {
return err
}
}
if opt.Logger == nil {
if err := WithLogger(nil)(m, opt); err != nil {
return err
}
}
return nil
}
// NewFromDirectory builds a [Cluster] tree using the given directory
func NewFromDirectory(dir, domain string, opts ...ScanOption) (*Cluster, error) {
var scanOptions ScanOptions
dir = filepath.Clean(dir)
fullPath, err := filepath.Abs(dir)
if err != nil {
return nil, err
}
sub, err := DirFS(dir)
if err != nil {
return nil, err
}
m := &Cluster{
dir: sub,
BaseDir: dir,
Name: filepath.Base(fullPath),
Domain: domain,
}
for _, opt := range opts {
if err := opt(m, &scanOptions); err != nil {
return nil, err
}
}
if err := m.setScanDefaults(&scanOptions); err != nil {
return nil, err
}
if err := m.scan(&scanOptions); err != nil {
return nil, err
}
return m, nil
}