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