mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-09-20 06:46:19 +08:00
NEW FEATURE: Added "push --report" flag which generates JSON report of changes made (#2543)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
This commit is contained in:
parent
f1fd723c80
commit
1d825be67a
|
@ -1,6 +1,7 @@
|
||||||
package commands
|
package commands
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -45,6 +46,13 @@ type PreviewArgs struct {
|
||||||
Full bool
|
Full bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ReportItem struct {
|
||||||
|
Domain string `json:"domain"`
|
||||||
|
Corrections int `json:"corrections"`
|
||||||
|
Provider string `json:"provider,omitempty"`
|
||||||
|
Registrar string `json:"registrar,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
func (args *PreviewArgs) flags() []cli.Flag {
|
func (args *PreviewArgs) flags() []cli.Flag {
|
||||||
flags := args.GetDNSConfigArgs.flags()
|
flags := args.GetDNSConfigArgs.flags()
|
||||||
flags = append(flags, args.GetCredentialsArgs.flags()...)
|
flags = append(flags, args.GetCredentialsArgs.flags()...)
|
||||||
|
@ -93,6 +101,7 @@ var _ = cmd(catMain, func() *cli.Command {
|
||||||
type PushArgs struct {
|
type PushArgs struct {
|
||||||
PreviewArgs
|
PreviewArgs
|
||||||
Interactive bool
|
Interactive bool
|
||||||
|
Report string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (args *PushArgs) flags() []cli.Flag {
|
func (args *PushArgs) flags() []cli.Flag {
|
||||||
|
@ -102,21 +111,26 @@ func (args *PushArgs) flags() []cli.Flag {
|
||||||
Destination: &args.Interactive,
|
Destination: &args.Interactive,
|
||||||
Usage: "Interactive. Confirm or Exclude each correction before they run",
|
Usage: "Interactive. Confirm or Exclude each correction before they run",
|
||||||
})
|
})
|
||||||
|
flags = append(flags, &cli.StringFlag{
|
||||||
|
Name: "report",
|
||||||
|
Destination: &args.Report,
|
||||||
|
Usage: `Generate a machine-parseable report of performed corrections.`,
|
||||||
|
})
|
||||||
return flags
|
return flags
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preview implements the preview subcommand.
|
// Preview implements the preview subcommand.
|
||||||
func Preview(args PreviewArgs) error {
|
func Preview(args PreviewArgs) error {
|
||||||
return run(args, false, false, printer.DefaultPrinter)
|
return run(args, false, false, printer.DefaultPrinter, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push implements the push subcommand.
|
// Push implements the push subcommand.
|
||||||
func Push(args PushArgs) error {
|
func Push(args PushArgs) error {
|
||||||
return run(args.PreviewArgs, true, args.Interactive, printer.DefaultPrinter)
|
return run(args.PreviewArgs, true, args.Interactive, printer.DefaultPrinter, &args.Report)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run is the main routine common to preview/push
|
// run is the main routine common to preview/push
|
||||||
func run(args PreviewArgs, push bool, interactive bool, out printer.CLI) error {
|
func run(args PreviewArgs, push bool, interactive bool, out printer.CLI, report *string) error {
|
||||||
// TODO: make truly CLI independent. Perhaps return results on a channel as they occur
|
// TODO: make truly CLI independent. Perhaps return results on a channel as they occur
|
||||||
|
|
||||||
// This is a hack until we have the new printer replacement.
|
// This is a hack until we have the new printer replacement.
|
||||||
|
@ -151,7 +165,7 @@ func run(args PreviewArgs, push bool, interactive bool, out printer.CLI) error {
|
||||||
// create a WaitGroup with the length of domains for the anonymous functions (later goroutines) to wait for
|
// create a WaitGroup with the length of domains for the anonymous functions (later goroutines) to wait for
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
wg.Add(len(cfg.Domains))
|
wg.Add(len(cfg.Domains))
|
||||||
|
var reportItems []ReportItem
|
||||||
// For each domain in dnsconfig.js...
|
// For each domain in dnsconfig.js...
|
||||||
for _, domain := range cfg.Domains {
|
for _, domain := range cfg.Domains {
|
||||||
// Run preview or push operations per domain as anonymous function, in preparation for the later use of goroutines.
|
// Run preview or push operations per domain as anonymous function, in preparation for the later use of goroutines.
|
||||||
|
@ -232,6 +246,11 @@ func run(args PreviewArgs, push bool, interactive bool, out printer.CLI) error {
|
||||||
totalCorrections += len(corrections)
|
totalCorrections += len(corrections)
|
||||||
// When diff1 goes away, the call to printReports() should be moved to HERE.
|
// When diff1 goes away, the call to printReports() should be moved to HERE.
|
||||||
//printReports(domain.Name, provider.Name, reports, out, push, notifier)
|
//printReports(domain.Name, provider.Name, reports, out, push, notifier)
|
||||||
|
reportItems = append(reportItems, ReportItem{
|
||||||
|
Domain: domain.Name,
|
||||||
|
Corrections: len(corrections),
|
||||||
|
Provider: provider.Name,
|
||||||
|
})
|
||||||
anyErrors = printOrRunCorrections(domain.Name, provider.Name, corrections, out, push, interactive, notifier) || anyErrors
|
anyErrors = printOrRunCorrections(domain.Name, provider.Name, corrections, out, push, interactive, notifier) || anyErrors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +272,11 @@ func run(args PreviewArgs, push bool, interactive bool, out printer.CLI) error {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
totalCorrections += len(corrections)
|
totalCorrections += len(corrections)
|
||||||
|
reportItems = append(reportItems, ReportItem{
|
||||||
|
Domain: domain.Name,
|
||||||
|
Corrections: len(corrections),
|
||||||
|
Registrar: domain.RegistrarName,
|
||||||
|
})
|
||||||
anyErrors = printOrRunCorrections(domain.Name, domain.RegistrarName, corrections, out, push, interactive, notifier) || anyErrors
|
anyErrors = printOrRunCorrections(domain.Name, domain.RegistrarName, corrections, out, push, interactive, notifier) || anyErrors
|
||||||
}(domain)
|
}(domain)
|
||||||
}
|
}
|
||||||
|
@ -269,6 +293,20 @@ func run(args PreviewArgs, push bool, interactive bool, out printer.CLI) error {
|
||||||
if totalCorrections != 0 && args.WarnChanges {
|
if totalCorrections != 0 && args.WarnChanges {
|
||||||
return fmt.Errorf("there are pending changes")
|
return fmt.Errorf("there are pending changes")
|
||||||
}
|
}
|
||||||
|
if report != nil {
|
||||||
|
f, err := os.OpenFile(*report, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
b, err := json.MarshalIndent(reportItems, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := f.Write(b); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@
|
||||||
* [Nameservers and Delegations](nameservers.md)
|
* [Nameservers and Delegations](nameservers.md)
|
||||||
* [Notifications](notifications.md)
|
* [Notifications](notifications.md)
|
||||||
* [Useful code tricks](code-tricks.md)
|
* [Useful code tricks](code-tricks.md)
|
||||||
|
* [JSON Reports](json-reports.md)
|
||||||
|
|
||||||
## Developer info
|
## Developer info
|
||||||
|
|
||||||
|
|
34
documentation/json-reports.md
Normal file
34
documentation/json-reports.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# JSON Reports
|
||||||
|
|
||||||
|
DNSControl has build in functionality to generate a machine-parseable report after pushing changes. This report is JSON formated and contains the zonename, the provider or registrar name and the amount of performed changes.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To enable the report option you must use the `push` operation in combination with the `--report <filename>` option. This generates the json file.
|
||||||
|
|
||||||
|
{% code title="report.json" %}
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"domain": "private.example.com",
|
||||||
|
"corrections": 10,
|
||||||
|
"provider": "bind"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "private.example.com",
|
||||||
|
"corrections": 0,
|
||||||
|
"registrar": "none"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "admin.example.com",
|
||||||
|
"corrections": 5,
|
||||||
|
"provider": "bind"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "admin.example.com",
|
||||||
|
"corrections": 0,
|
||||||
|
"registrar": "none"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
{% endcode %}
|
Loading…
Reference in a new issue