diff --git a/cli/internal/common.go b/cli/internal/common.go index 26480110..213361ad 100644 --- a/cli/internal/common.go +++ b/cli/internal/common.go @@ -410,6 +410,15 @@ var StdErrOnlyFlag = &cli.BoolFlag{ Destination: &StdErrOnly, } +var AutoDNSRecord bool +var AutoDNSRecordFlag = &cli.BoolFlag{ + Name: "auto", + Aliases: []string{"a"}, + Value: false, + Usage: "Automatically configure DNS records", + Destination: &StdErrOnly, +} + // SSHFailMsg is a hopefully helpful SSH failure message var SSHFailMsg = ` Woops, Abra is unable to connect to connect to %s. @@ -432,6 +441,10 @@ If your SSH private key loaded? You can check by running the following command: ssh-add -L +If, you can add it with: + + ssh-add ~/.ssh/ + If you are using a non-default public/private key, you can configure this in your ~/.ssh/config file which Abra will read in order to figure out connection details: diff --git a/cli/record/new.go b/cli/record/new.go index b9d77b82..02e4c0e5 100644 --- a/cli/record/new.go +++ b/cli/record/new.go @@ -7,6 +7,7 @@ import ( abraFormatter "coopcloud.tech/abra/cli/formatter" "coopcloud.tech/abra/cli/internal" + "coopcloud.tech/abra/pkg/dns" gandiPkg "coopcloud.tech/abra/pkg/dns/gandi" "github.com/libdns/gandi" "github.com/libdns/libdns" @@ -27,6 +28,7 @@ var RecordNewCommand = &cli.Command{ internal.DNSValueFlag, internal.DNSTTLFlag, internal.DNSPriorityFlag, + internal.AutoDNSRecordFlag, }, Description: ` This command creates a new domain name record for a specific zone. @@ -38,6 +40,12 @@ Example: abra record new foo.com -p gandi -t A -n myapp -v 192.168.178.44 +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. + + abra record new --auto + You may also invoke this command in "wizard" mode and be prompted for input abra record new @@ -63,6 +71,14 @@ You may also invoke this command in "wizard" mode and be prompted for input logrus.Fatalf("'%s' is not a supported DNS provider", internal.DNSProvider) } + if internal.AutoDNSRecord { + logrus.Infof("automatically configuring @./*. A records for %s (--auto)", zone) + if err := autoConfigure(c, &provider, zone); err != nil { + logrus.Fatal(err) + } + return nil + } + if err := internal.EnsureDNSTypeFlag(c); err != nil { logrus.Fatal(err) } @@ -95,7 +111,7 @@ You may also invoke this command in "wizard" mode and be prompted for input if existingRecord.Type == record.Type && existingRecord.Name == record.Name && existingRecord.Value == record.Value { - logrus.Fatal("provider library reports that this record already exists?") + logrus.Fatalf("%s record for %s already exists?", record.Type, zone) } } @@ -104,6 +120,9 @@ You may also invoke this command in "wizard" mode and be prompted for input zone, []libdns.Record{record}, ) + if err != nil { + logrus.Fatal(err) + } if len(createdRecords) == 0 { logrus.Fatal("provider library reports that no record was created?") @@ -134,3 +153,79 @@ You may also invoke this command in "wizard" mode and be prompted for input return nil }, } + +func autoConfigure(c *cli.Context, provider *gandi.Provider, zone string) error { + ipv4, err := dns.EnsureIPv4(zone) + if err != nil { + return err + } + + atRecord := libdns.Record{ + Type: "A", + Name: "@", + Value: ipv4, + TTL: time.Duration(internal.DNSTTL), + } + + wildcardRecord := libdns.Record{ + Type: "A", + Name: "*", + Value: ipv4, + TTL: time.Duration(internal.DNSTTL), + } + + records := []libdns.Record{atRecord, wildcardRecord} + + tableCol := []string{"type", "name", "value", "TTL", "priority"} + table := abraFormatter.CreateTable(tableCol) + + for _, record := range records { + existingRecords, err := provider.GetRecords(c.Context, zone) + if err != nil { + return err + } + + for _, existingRecord := range existingRecords { + if existingRecord.Type == record.Type && + existingRecord.Name == record.Name && + existingRecord.Value == record.Value { + logrus.Warnf("%s record for %s already exists?", record.Type, zone) + continue + } + } + + createdRecords, err := provider.SetRecords( + c.Context, + 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 +} diff --git a/cli/server/new.go b/cli/server/new.go index 0faf40ab..3aa9c3e8 100644 --- a/cli/server/new.go +++ b/cli/server/new.go @@ -105,6 +105,9 @@ bar.example.com). @ 1800 IN A %s * 1800 IN A %s +"abra record new --auto" can help you do this quickly if you use a supported +DNS provider. + `, internal.HetznerCloudName, ip, rootPassword, ip, ip, ip,