github.com/philhug/dnscontrol@v0.2.4-0.20180625181521-921fa9849001/commands/printIR.go (about) 1 package commands 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "os" 8 9 "github.com/StackExchange/dnscontrol/models" 10 "github.com/StackExchange/dnscontrol/pkg/js" 11 "github.com/StackExchange/dnscontrol/pkg/normalize" 12 "github.com/pkg/errors" 13 "github.com/urfave/cli" 14 ) 15 16 var _ = cmd(catDebug, func() *cli.Command { 17 var args PrintIRArgs 18 return &cli.Command{ 19 Name: "print-ir", 20 Usage: "Output intermediate representation (IR) after running validation and normalization logic.", 21 Action: func(c *cli.Context) error { 22 return exit(PrintIR(args)) 23 }, 24 Flags: args.flags(), 25 } 26 }()) 27 28 var _ = cmd(catDebug, func() *cli.Command { 29 var args PrintIRArgs 30 // This is the same as print-ir with the following changes: 31 // - output defaults to /dev/null. 32 // - prints "No errors." if there were no errors. 33 return &cli.Command{ 34 Name: "check", 35 Usage: "Check and validate dnsconfig.js. Do not access providers.", 36 Action: func(c *cli.Context) error { 37 if args.Output == "" { 38 args.Output = os.DevNull 39 } 40 err := exit(PrintIR(args)) 41 if err == nil { 42 fmt.Fprintf(os.Stderr, "No errors.\n") 43 } 44 return err 45 }, 46 Flags: args.flags(), 47 } 48 }()) 49 50 // PrintIRArgs encapsulates the flags/arguments for the print-ir command. 51 type PrintIRArgs struct { 52 GetDNSConfigArgs 53 PrintJSONArgs 54 Raw bool 55 } 56 57 func (args *PrintIRArgs) flags() []cli.Flag { 58 flags := append(args.GetDNSConfigArgs.flags(), args.PrintJSONArgs.flags()...) 59 flags = append(flags, &cli.BoolFlag{ 60 Name: "raw", 61 Usage: "Skip validation and normalization. Just print js result.", 62 Destination: &args.Raw, 63 }) 64 return flags 65 } 66 67 // PrintIR implements the print-ir subcommand. 68 func PrintIR(args PrintIRArgs) error { 69 cfg, err := GetDNSConfig(args.GetDNSConfigArgs) 70 if err != nil { 71 return err 72 } 73 if !args.Raw { 74 errs := normalize.NormalizeAndValidateConfig(cfg) 75 if PrintValidationErrors(errs) { 76 return errors.Errorf("Exiting due to validation errors") 77 } 78 } 79 return PrintJSON(args.PrintJSONArgs, cfg) 80 } 81 82 // PrintValidationErrors formats and prints the validation errors and warnings. 83 func PrintValidationErrors(errs []error) (fatal bool) { 84 if len(errs) == 0 { 85 return false 86 } 87 fmt.Printf("%d Validation errors:\n", len(errs)) 88 for _, err := range errs { 89 if _, ok := err.(normalize.Warning); ok { 90 fmt.Printf("WARNING: %s\n", err) 91 } else { 92 fatal = true 93 fmt.Printf("ERROR: %s\n", err) 94 } 95 } 96 return 97 } 98 99 // ExecuteDSL executes the dnsconfig.js contents. 100 func ExecuteDSL(args ExecuteDSLArgs) (*models.DNSConfig, error) { 101 if args.JSFile == "" { 102 return nil, errors.Errorf("No config specified") 103 } 104 text, err := ioutil.ReadFile(args.JSFile) 105 if err != nil { 106 return nil, errors.Errorf("Reading js file %s: %s", args.JSFile, err) 107 } 108 dnsConfig, err := js.ExecuteJavascript(string(text), args.DevMode) 109 if err != nil { 110 return nil, errors.Errorf("Executing javascript in %s: %s", args.JSFile, err) 111 } 112 return dnsConfig, nil 113 } 114 115 // PrintJSON outputs/prettyprints the IR data. 116 func PrintJSON(args PrintJSONArgs, config *models.DNSConfig) (err error) { 117 var dat []byte 118 if args.Pretty { 119 dat, err = json.MarshalIndent(config, "", " ") 120 } else { 121 dat, err = json.Marshal(config) 122 } 123 if err != nil { 124 return err 125 } 126 if args.Output != "" { 127 f, err := os.Create(args.Output) 128 if err != nil { 129 return err 130 } 131 defer f.Close() 132 _, err = f.Write(dat) 133 return err 134 } 135 fmt.Println(string(dat)) 136 return nil 137 } 138 139 func exit(err error) error { 140 if err == nil { 141 return nil 142 } 143 return cli.NewExitError(err, 1) 144 }