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.
193 lines
3.9 KiB
193 lines
3.9 KiB
package main |
|
|
|
import ( |
|
"context" |
|
"net/netip" |
|
"os" |
|
"time" |
|
|
|
"darvaza.org/core" |
|
"github.com/spf13/cobra" |
|
|
|
"git.jpi.io/amery/jpictl/pkg/cluster" |
|
"git.jpi.io/amery/jpictl/pkg/dns" |
|
) |
|
|
|
const ( |
|
// DNSSyncTimeout specifies how long are we willing to wait for a DNS |
|
// synchronization |
|
DNSSyncTimeout = 10 * time.Second |
|
) |
|
|
|
func newDNSManager(m *cluster.Cluster, provider dns.Provider) (*dns.Manager, error) { |
|
domain := m.Domain |
|
if m.Name != "" { |
|
domain = m.Name + "." + domain |
|
} |
|
|
|
mgr, err := dns.NewManager(dns.WithDomain(domain), dns.WithLogger(log)) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
if provider != nil { |
|
// set provider only if specified |
|
err = dns.WithProvider(provider)(mgr) |
|
if err != nil { |
|
return nil, err |
|
} |
|
} |
|
|
|
if err := populateDNSManager(mgr, m); err != nil { |
|
return nil, err |
|
} |
|
|
|
return mgr, nil |
|
} |
|
|
|
func populateDNSManager(mgr *dns.Manager, m *cluster.Cluster) error { |
|
var err error |
|
|
|
ctx := context.TODO() |
|
|
|
m.ForEachZone(func(z *cluster.Zone) bool { |
|
z.ForEachMachine(func(p *cluster.Machine) bool { |
|
err = mgr.AddHost(ctx, z.Name, int(p.ID), p.IsActive(), p.PublicAddresses...) |
|
return err != nil |
|
}) |
|
|
|
return err != nil |
|
}) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
m.ForEachRegion(func(r *cluster.Region) bool { |
|
r.ForEachZone(func(z *cluster.Zone) bool { |
|
err = mgr.AddRegion(ctx, r.Name, z.Name) |
|
return err != nil |
|
}) |
|
|
|
return err != nil |
|
}) |
|
|
|
return err |
|
} |
|
|
|
// revive:disable:flag-parameter |
|
func newDNSManagerCommand(_ *cobra.Command, |
|
resolve bool, withCredentials bool) (*dns.Manager, error) { |
|
// revive:enable:flag-parameter |
|
var cred dns.Provider |
|
|
|
if withCredentials { |
|
var err error |
|
|
|
cred, err = dns.DefaultDNSProvider() |
|
if err != nil { |
|
return nil, err |
|
} |
|
} |
|
|
|
m, err := cfg.LoadZones(resolve) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
return newDNSManager(m, cred) |
|
} |
|
|
|
// Command |
|
var dnsCmd = &cobra.Command{ |
|
Use: "dns", |
|
} |
|
|
|
var dnsWriteCmd = &cobra.Command{ |
|
Use: "write", |
|
Short: "dns write generates public DNS records", |
|
PreRun: setVerbosity, |
|
RunE: func(cmd *cobra.Command, _ []string) error { |
|
mgr, err := newDNSManagerCommand(cmd, true, false) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
_, err = mgr.WriteTo(os.Stdout) |
|
return err |
|
}, |
|
} |
|
|
|
var dnsSyncCmd = &cobra.Command{ |
|
Use: "sync", |
|
Short: "dns sync updates public DNS records", |
|
PreRun: setVerbosity, |
|
RunE: func(cmd *cobra.Command, _ []string) error { |
|
mgr, err := newDNSManagerCommand(cmd, true, true) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), DNSSyncTimeout) |
|
defer cancel() |
|
|
|
return mgr.Sync(ctx) |
|
}, |
|
} |
|
|
|
var dnsShowCmd = &cobra.Command{ |
|
Use: "show [<name>...]", |
|
Short: "dns show lists entries on DNS for our domain", |
|
PreRun: setVerbosity, |
|
RunE: func(cmd *cobra.Command, args []string) error { |
|
mgr, err := newDNSManagerCommand(cmd, true, true) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), DNSSyncTimeout) |
|
defer cancel() |
|
|
|
return mgr.Show(ctx, args...) |
|
}, |
|
} |
|
|
|
var dnsAddCmd = &cobra.Command{ |
|
Use: "add <name> <address..>", |
|
Short: "dns add registers a new machine on the public DNS", |
|
Args: cobra.MinimumNArgs(2), |
|
PreRun: setVerbosity, |
|
RunE: func(cmd *cobra.Command, args []string) error { |
|
var addrs []netip.Addr |
|
|
|
for _, s := range args[1:] { |
|
addr, err := core.ParseAddr(s) |
|
switch { |
|
case err != nil: |
|
return core.Wrap(err, s) |
|
case !addr.IsValid(), addr.IsUnspecified(), addr.IsPrivate(), addr.IsMulticast(): |
|
return core.Wrap(core.ErrInvalid, s) |
|
default: |
|
addrs = append(addrs, addr) |
|
} |
|
} |
|
|
|
mgr, err := newDNSManagerCommand(cmd, true, true) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), DNSSyncTimeout) |
|
defer cancel() |
|
|
|
return mgr.Add(ctx, args[0], addrs...) |
|
}, |
|
} |
|
|
|
func init() { |
|
rootCmd.AddCommand(dnsCmd) |
|
|
|
dnsCmd.AddCommand(dnsWriteCmd) |
|
dnsCmd.AddCommand(dnsSyncCmd) |
|
dnsCmd.AddCommand(dnsShowCmd) |
|
dnsCmd.AddCommand(dnsAddCmd) |
|
}
|
|
|