From 7789b4dbdc21922388ed42267189750c37a1d6fb Mon Sep 17 00:00:00 2001 From: Tom Limoncelli Date: Tue, 25 Feb 2020 07:23:40 -0500 Subject: [PATCH] get-zones: Implement --ttl flag for pretty and dsl (#654) --- commands/getZones.go | 23 ++++++++++++++++------- docs/get-zones.md | 5 ++++- pkg/prettyzone/prettyzone.go | 16 ++++++++++------ providers/bind/bindProvider.go | 2 +- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/commands/getZones.go b/commands/getZones.go index acf8d0465..eba26818d 100644 --- a/commands/getZones.go +++ b/commands/getZones.go @@ -79,8 +79,7 @@ func (args *GetZoneArgs) flags() []cli.Flag { flags = append(flags, &cli.IntFlag{ Name: "ttl", Destination: &args.DefaultTTL, - Usage: `Default TTL`, - Value: 300, + Usage: `Default TTL (0 picks the zone's most common TTL)`, }) return flags } @@ -153,24 +152,34 @@ func GetZone(args GetZoneArgs) error { z := prettyzone.PrettySort(recs, zoneName, 0, nil) switch args.OutputFormat { + case "pretty": fmt.Fprintf(w, "$ORIGIN %s.\n", zoneName) - prettyzone.WriteZoneFileRC(w, z.Records, zoneName, nil) + prettyzone.WriteZoneFileRC(w, z.Records, zoneName, uint32(args.DefaultTTL), nil) fmt.Fprintln(w) - case "dsl": - fmt.Fprintf(w, `D("%s", REG_CHANGEME,`+"\n", zoneName) - fmt.Fprintf(w, "\tDnsProvider(%s)", args.CredName) + case "dsl": + fmt.Fprintf(w, `D("%s", REG_CHANGEME,`, zoneName) + fmt.Fprintf(w, "\n\tDnsProvider(%s)", args.CredName) + defaultTTL := uint32(args.DefaultTTL) + if defaultTTL == 0 { + defaultTTL = prettyzone.MostCommonTTL(recs) + } + if defaultTTL != models.DefaultTTL { + fmt.Fprintf(w, "\n\tDefaultTTL(%d)", defaultTTL) + } for _, rec := range recs { - fmt.Fprint(w, formatDsl(zoneName, rec, uint32(args.DefaultTTL))) + fmt.Fprint(w, formatDsl(zoneName, rec, defaultTTL)) } fmt.Fprint(w, "\n)\n") + case "tsv": for _, rec := range recs { fmt.Fprintf(w, fmt.Sprintf("%s\t%s\t%d\tIN\t%s\t%s\n", rec.NameFQDN, rec.Name, rec.TTL, rec.Type, rec.GetTargetCombined())) } + default: return fmt.Errorf("format %q unknown", args.OutputFile) } diff --git a/docs/get-zones.md b/docs/get-zones.md index 424112929..3d7bb1b6e 100644 --- a/docs/get-zones.md +++ b/docs/get-zones.md @@ -19,8 +19,9 @@ Syntax: dnscontrol get-zones [command options] credkey provider zone [...] --creds value Provider credentials JSON file (default: "creds.json") - --format value Output format: pretty dsl tsv nameonly (default: "pretty") + --format value Output format: dsl pretty tsv nameonly (default: "pretty") --out value Instead of stdout, write to this file + --ttl value Default TTL (0 picks the zone's most common TTL) (default: 0) ARGUMENTS: credkey: The name used in creds.json (first parameter to NewDnsProvider() in dnsconfig.js) @@ -40,6 +41,8 @@ When using `tsv`, the columns are: Record Type (A, AAAA, CNAME, etc.) Target and arguments (quoted like in a zonefile) +The --ttl flag applies to pretty and dsl formats. + EXAMPLES: dnscontrol get-zones myr53 ROUTE53 example.com dnscontrol get-zones gmain GANDI_V5 example.comn other.com diff --git a/pkg/prettyzone/prettyzone.go b/pkg/prettyzone/prettyzone.go index 4ad751ccd..062022c9c 100644 --- a/pkg/prettyzone/prettyzone.go +++ b/pkg/prettyzone/prettyzone.go @@ -13,10 +13,10 @@ import ( "github.com/miekg/dns" ) -// mostCommonTTL returns the most common TTL in a set of records. If there is +// MostCommonTTL returns the most common TTL in a set of records. If there is // a tie, the highest TTL is selected. This makes the results consistent. // NS records are not included in the analysis because Tom said so. -func mostCommonTTL(records models.Records) uint32 { +func MostCommonTTL(records models.Records) uint32 { // Index the TTLs in use: d := make(map[uint32]int) for _, r := range records { @@ -45,11 +45,11 @@ func mostCommonTTL(records models.Records) uint32 { // WriteZoneFileRR is a helper for when you have []dns.RR instead of models.Records func WriteZoneFileRR(w io.Writer, records []dns.RR, origin string) error { - return WriteZoneFileRC(w, models.RRstoRCs(records, origin), origin, nil) + return WriteZoneFileRC(w, models.RRstoRCs(records, origin), origin, 0, nil) } // WriteZoneFileRC writes a beautifully formatted zone file. -func WriteZoneFileRC(w io.Writer, records models.Records, origin string, comments []string) error { +func WriteZoneFileRC(w io.Writer, records models.Records, origin string, defaultTTL uint32, comments []string) error { // This function prioritizes beauty over output size. // * The zone records are sorted by label, grouped by subzones to // be easy to read and pleasant to the eye. @@ -61,14 +61,18 @@ func WriteZoneFileRC(w io.Writer, records models.Records, origin string, comment // * $TTL is used to eliminate clutter. The most common TTL value is used. // * "@" is used instead of the apex domain name. - z := PrettySort(records, origin, mostCommonTTL(records), comments) + if defaultTTL == 0 { + defaultTTL = MostCommonTTL(records) + } + + z := PrettySort(records, origin, defaultTTL, comments) return z.generateZoneFileHelper(w) } func PrettySort(records models.Records, origin string, defaultTTL uint32, comments []string) *zoneGenData { if defaultTTL == 0 { - defaultTTL = mostCommonTTL(records) + defaultTTL = MostCommonTTL(records) } z := &zoneGenData{ Origin: origin + ".", diff --git a/providers/bind/bindProvider.go b/providers/bind/bindProvider.go index 999d984bd..d7f8554c2 100644 --- a/providers/bind/bindProvider.go +++ b/providers/bind/bindProvider.go @@ -250,7 +250,7 @@ func (c *Bind) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correcti // Beware that if there are any fake types, then they will // be commented out on write, but we don't reverse that when // reading, so there will be a diff on every invocation. - err = prettyzone.WriteZoneFileRC(zf, dc.Records, dc.Name, comments) + err = prettyzone.WriteZoneFileRC(zf, dc.Records, dc.Name, 0, comments) if err != nil { return fmt.Errorf("failed WriteZoneFile: %w", err)