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  }