118 lines
2.3 KiB
Go
118 lines
2.3 KiB
Go
package hosts
|
|
|
|
import (
|
|
"github.com/miekg/dns"
|
|
"time"
|
|
)
|
|
|
|
type HostMap map[string][]Host
|
|
|
|
type Host struct {
|
|
Type uint16 `json:"type"`
|
|
TTL time.Duration `json:"ttl"`
|
|
Values []string `json:"values"`
|
|
}
|
|
|
|
func (h *Host) TypeString() string {
|
|
return dns.TypeToString[h.Type]
|
|
}
|
|
|
|
type ProviderList struct {
|
|
providers []Provider
|
|
}
|
|
|
|
// Provider is an interface specifying a host source
|
|
// Each source should support AT LEAST List and Get, but can support Writer as well
|
|
type Provider interface {
|
|
List() (HostMap, error)
|
|
Get(queryType uint16, domain string) (*Host, error)
|
|
}
|
|
|
|
// Writer is an interface to modify hosts.
|
|
// Examples of this include Redis, Bolt, MySQL, etc.
|
|
type Writer interface {
|
|
Set(domain string, host *Host) error
|
|
Delete(domain string) error
|
|
}
|
|
|
|
type ProviderWriter interface {
|
|
Provider
|
|
Writer
|
|
}
|
|
|
|
func NewHosts(providers []Provider) *ProviderList {
|
|
return &ProviderList{providers}
|
|
}
|
|
|
|
// List returns all results, merged into one HostMap
|
|
func (h *ProviderList) List() (HostMap, error) {
|
|
hostMap := make(HostMap)
|
|
|
|
for _, provider := range h.providers {
|
|
hosts, err := provider.List()
|
|
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for k, v := range hosts {
|
|
if existing, ok := hostMap[k]; ok {
|
|
existing = append(existing, v...)
|
|
|
|
hostMap[k] = existing
|
|
} else {
|
|
hostMap[k] = v
|
|
}
|
|
}
|
|
}
|
|
|
|
return hostMap, nil
|
|
}
|
|
|
|
// Get Matches values to providers, loping each in order
|
|
func (h *ProviderList) Get(queryType uint16, domain string) (*Host, error) {
|
|
var host *Host
|
|
var err error
|
|
|
|
for _, provider := range h.providers {
|
|
host, err = provider.Get(queryType, domain)
|
|
|
|
if host != nil {
|
|
break
|
|
}
|
|
}
|
|
|
|
return host, err
|
|
}
|
|
|
|
// Set invokes each provider, setting the host on the first one to return a nil error
|
|
func (h *ProviderList) Set(domain string, host *Host) (err error) {
|
|
for _, provider := range h.providers {
|
|
if writer, ok := provider.(Writer); ok {
|
|
err = writer.Set(domain, host)
|
|
|
|
if err == nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
err = errUnsupportedOperation
|
|
return
|
|
}
|
|
|
|
// Delete invokes each provider, removing the host on the first one to return a nil error
|
|
func (h *ProviderList) Delete(domain string) (err error) {
|
|
for _, provider := range h.providers {
|
|
if writer, ok := provider.(Writer); ok {
|
|
err = writer.Delete(domain)
|
|
|
|
if err == nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
err = errUnsupportedOperation
|
|
return
|
|
} |