abra/cli/record/new.go

257 lines
5.7 KiB
Go
Raw Normal View History

package record
2021-10-19 22:05:57 +00:00
import (
"context"
2021-10-19 22:05:57 +00:00
"fmt"
"strconv"
"coopcloud.tech/abra/cli/internal"
2021-12-22 19:46:50 +00:00
"coopcloud.tech/abra/pkg/dns"
2021-10-19 22:05:57 +00:00
gandiPkg "coopcloud.tech/abra/pkg/dns/gandi"
2021-12-28 00:24:23 +00:00
"coopcloud.tech/abra/pkg/formatter"
2021-10-19 22:05:57 +00:00
"github.com/libdns/gandi"
"github.com/libdns/libdns"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
2021-10-19 22:05:57 +00:00
)
// RecordNewCommand creates a new domain name record.
var RecordNewCommand = cli.Command{
Name: "new",
2021-10-19 22:05:57 +00:00
Usage: "Create a new domain record",
Aliases: []string{"n"},
ArgsUsage: "<zone>",
2021-10-19 22:05:57 +00:00
Flags: []cli.Flag{
internal.DebugFlag,
internal.NoInputFlag,
2021-10-19 22:05:57 +00:00
internal.DNSProviderFlag,
internal.DNSTypeFlag,
internal.DNSNameFlag,
internal.DNSValueFlag,
internal.DNSTTLFlag,
internal.DNSPriorityFlag,
2021-12-22 19:46:50 +00:00
internal.AutoDNSRecordFlag,
2021-10-19 22:05:57 +00:00
},
Before: internal.SubCommandBefore,
2021-10-19 22:05:57 +00:00
Description: `
This command creates a new domain name record for a specific zone.
You must specify a zone (e.g. example.com) under which your domain name records
are listed. This zone must already be created on your provider account.
Example:
2021-10-19 22:05:57 +00:00
abra record new foo.com -p gandi -t A -n myapp -v 192.168.178.44
2021-10-19 22:05:57 +00:00
2021-12-22 19:46:50 +00:00
Typically, you need two records, an A record which points at the zone (@.) and
a wildcard record for your apps (*.). Pass "--auto" to have Abra automatically
set this up.
2022-01-01 20:34:33 +00:00
abra record new --auto foo.com -p gandi -v 192.168.178.44
2021-12-22 19:46:50 +00:00
You may also invoke this command in "wizard" mode and be prompted for input
abra record new
2022-01-01 20:34:33 +00:00
2021-10-19 22:05:57 +00:00
`,
Action: func(c *cli.Context) error {
zone, err := internal.EnsureZoneArgument(c)
if err != nil {
logrus.Fatal(err)
2021-10-19 22:05:57 +00:00
}
if err := internal.EnsureDNSProvider(); err != nil {
logrus.Fatal(err)
2021-10-19 22:05:57 +00:00
}
var provider gandi.Provider
switch internal.DNSProvider {
case "gandi":
provider, err = gandiPkg.New()
if err != nil {
logrus.Fatal(err)
}
default:
2021-12-23 00:41:29 +00:00
logrus.Fatalf("%s is not a supported DNS provider", internal.DNSProvider)
2021-10-19 22:05:57 +00:00
}
2021-12-22 19:46:50 +00:00
if internal.AutoDNSRecord {
2022-01-01 20:34:49 +00:00
ipv4, err := dns.EnsureIPv4(zone)
if err != nil {
logrus.Debugf("no ipv4 associated with %s, prompting for input", zone)
if err := internal.EnsureDNSValueFlag(c); err != nil {
logrus.Fatal(err)
}
ipv4 = internal.DNSValue
}
logrus.Infof("automatically configuring @./*. A records for %s for %s (--auto)", zone, ipv4)
if err := autoConfigure(c, &provider, zone, ipv4); err != nil {
2021-12-22 19:46:50 +00:00
logrus.Fatal(err)
}
2022-01-01 20:34:49 +00:00
2021-12-22 19:46:50 +00:00
return nil
}
if err := internal.EnsureDNSTypeFlag(c); err != nil {
logrus.Fatal(err)
}
if err := internal.EnsureDNSNameFlag(c); err != nil {
logrus.Fatal(err)
}
if err := internal.EnsureDNSValueFlag(c); err != nil {
2021-10-19 22:05:57 +00:00
logrus.Fatal(err)
}
2021-12-23 00:41:12 +00:00
ttl, err := dns.GetTTL(internal.DNSTTL)
if err != nil {
return err
}
2021-10-19 22:05:57 +00:00
record := libdns.Record{
Type: internal.DNSType,
Name: internal.DNSName,
Value: internal.DNSValue,
2021-12-23 00:41:12 +00:00
TTL: ttl,
2021-10-19 22:05:57 +00:00
}
if internal.DNSType == "MX" || internal.DNSType == "SRV" || internal.DNSType == "URI" {
record.Priority = internal.DNSPriority
2021-10-19 22:05:57 +00:00
}
records, err := provider.GetRecords(context.Background(), zone)
2021-10-20 14:56:34 +00:00
if err != nil {
logrus.Fatal(err)
}
for _, existingRecord := range records {
if existingRecord.Type == record.Type &&
existingRecord.Name == record.Name &&
existingRecord.Value == record.Value {
2021-12-22 19:46:50 +00:00
logrus.Fatalf("%s record for %s already exists?", record.Type, zone)
2021-10-20 14:56:34 +00:00
}
}
2021-10-19 22:05:57 +00:00
createdRecords, err := provider.SetRecords(
context.Background(),
2021-10-19 22:05:57 +00:00
zone,
[]libdns.Record{record},
)
2021-12-22 19:46:50 +00:00
if err != nil {
logrus.Fatal(err)
}
2021-10-19 22:05:57 +00:00
if len(createdRecords) == 0 {
logrus.Fatal("provider library reports that no record was created?")
2021-10-19 22:05:57 +00:00
}
createdRecord := createdRecords[0]
tableCol := []string{"type", "name", "value", "TTL", "priority"}
2021-12-28 00:24:23 +00:00
table := formatter.CreateTable(tableCol)
2021-10-19 22:05:57 +00:00
value := createdRecord.Value
if len(createdRecord.Value) > 30 {
value = fmt.Sprintf("%s...", createdRecord.Value[:30])
}
table.Append([]string{
createdRecord.Type,
createdRecord.Name,
value,
createdRecord.TTL.String(),
strconv.Itoa(createdRecord.Priority),
})
table.Render()
2021-10-20 14:56:34 +00:00
logrus.Info("record created")
2021-10-19 22:05:57 +00:00
return nil
},
}
2021-12-22 19:46:50 +00:00
2022-01-01 20:34:49 +00:00
func autoConfigure(c *cli.Context, provider *gandi.Provider, zone, ipv4 string) error {
2021-12-23 00:41:12 +00:00
ttl, err := dns.GetTTL(internal.DNSTTL)
if err != nil {
return err
}
2021-12-22 19:46:50 +00:00
atRecord := libdns.Record{
Type: "A",
Name: "@",
Value: ipv4,
2021-12-23 00:41:12 +00:00
TTL: ttl,
2021-12-22 19:46:50 +00:00
}
wildcardRecord := libdns.Record{
Type: "A",
Name: "*",
Value: ipv4,
2021-12-23 00:41:12 +00:00
TTL: ttl,
2021-12-22 19:46:50 +00:00
}
records := []libdns.Record{atRecord, wildcardRecord}
tableCol := []string{"type", "name", "value", "TTL", "priority"}
2021-12-28 00:24:23 +00:00
table := formatter.CreateTable(tableCol)
2021-12-22 19:46:50 +00:00
for _, record := range records {
existingRecords, err := provider.GetRecords(context.Background(), zone)
2021-12-22 19:46:50 +00:00
if err != nil {
return err
}
2021-12-23 00:46:57 +00:00
discovered := false
2021-12-22 19:46:50 +00:00
for _, existingRecord := range existingRecords {
if existingRecord.Type == record.Type &&
existingRecord.Name == record.Name &&
existingRecord.Value == record.Value {
2021-12-23 00:46:57 +00:00
logrus.Warnf("%s record: %s %s for %s already exists?", record.Type, record.Name, record.Value, zone)
discovered = true
2021-12-22 19:46:50 +00:00
}
}
2021-12-23 00:46:57 +00:00
if discovered {
continue
}
2021-12-22 19:46:50 +00:00
createdRecords, err := provider.SetRecords(
context.Background(),
2021-12-22 19:46:50 +00:00
zone,
[]libdns.Record{record},
)
if err != nil {
return err
}
if len(createdRecords) == 0 {
return fmt.Errorf("provider library reports that no record was created?")
}
createdRecord := createdRecords[0]
value := createdRecord.Value
if len(createdRecord.Value) > 30 {
value = fmt.Sprintf("%s...", createdRecord.Value[:30])
}
table.Append([]string{
createdRecord.Type,
createdRecord.Name,
value,
createdRecord.TTL.String(),
strconv.Itoa(createdRecord.Priority),
})
}
if table.NumLines() > 0 {
table.Render()
}
return nil
}