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.
130 lines
2.7 KiB
130 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(m *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, opt *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, opt *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 |
|
}
|
|
|