zone.ScanOptions, custom resolver and prevent unnecessary DNS calls #5
Merged
amery
merged 5 commits from pr-amery-scan_options
into main
2 years ago
8 changed files with 137 additions and 55 deletions
@ -0,0 +1,109 @@ |
|||||||
|
package zones |
||||||
|
|
||||||
|
import ( |
||||||
|
"io/fs" |
||||||
|
"path/filepath" |
||||||
|
|
||||||
|
"darvaza.org/resolver" |
||||||
|
"github.com/hack-pad/hackpadfs/os" |
||||||
|
) |
||||||
|
|
||||||
|
// A ScanOption preconfigures the Zones before scanning
|
||||||
|
type ScanOption func(*Zones, *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 |
||||||
|
} |
||||||
|
|
||||||
|
// 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 *Zones, 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 *Zones, 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 *Zones, opt *ScanOptions) error { |
||||||
|
if h == nil { |
||||||
|
h = resolver.SystemResolver(true) |
||||||
|
} |
||||||
|
|
||||||
|
m.resolver = h |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func (m *Zones) setDefaults(opt *ScanOptions) error { |
||||||
|
if m.resolver == nil { |
||||||
|
h := resolver.NewCloudflareLookuper() |
||||||
|
|
||||||
|
if err := WithLookuper(h)(m, opt); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
// NewFS builds a [Zones] tree using the given directory
|
||||||
|
func NewFS(dir fs.FS, domain string, opts ...ScanOption) (*Zones, error) { |
||||||
|
var scanOptions ScanOptions |
||||||
|
|
||||||
|
z := &Zones{ |
||||||
|
dir: dir, |
||||||
|
domain: domain, |
||||||
|
} |
||||||
|
|
||||||
|
for _, opt := range opts { |
||||||
|
if err := opt(z, &scanOptions); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if err := z.setDefaults(&scanOptions); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
if err := z.scan(&scanOptions); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
return z, nil |
||||||
|
} |
||||||
|
|
||||||
|
// New builds a [Zones] tree using the given directory
|
||||||
|
func New(dir, domain string, opts ...ScanOption) (*Zones, error) { |
||||||
|
dir, err := filepath.Abs(dir) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
base, err := os.NewFS().Sub(dir[1:]) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
return NewFS(base, domain, opts...) |
||||||
|
} |
Loading…
Reference in new issue