package main import ( "flag" "fmt" "os" "path/filepath" "sort" "time" ) func main() { configPath := flag.String("config", "", "path to YAML config (default: catz.yaml next to input file)") outputDir := flag.String("output-dir", "", "directory for output zone files (default: same as input file)") bindConf := flag.String("bind-conf", "", "path to write BIND domains.conf") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: catalog-zone-gen [--config path] [--output-dir path] [--bind-conf path] \n") flag.PrintDefaults() } flag.Parse() if flag.NArg() != 1 { flag.Usage() os.Exit(1) } inputFile := flag.Arg(0) inputDir := filepath.Dir(inputFile) if *configPath == "" { *configPath = filepath.Join(inputDir, "catz.yaml") } if *outputDir == "" { *outputDir = inputDir } cfg, err := loadConfig(*configPath) if err != nil { fmt.Fprintf(os.Stderr, "error: %s\n", err) os.Exit(1) } entries, members, err := parseInput(inputFile, cfg) if err != nil { fmt.Fprintf(os.Stderr, "error: %s\n", err) os.Exit(1) } now := time.Now().UTC() // Process catalogs in sorted order for deterministic output catNames := make([]string, 0, len(members)) for name := range members { catNames = append(catNames, name) } sort.Strings(catNames) hasErrors := false for _, catName := range catNames { changed, err := processCatalog(catName, cfg, members[catName], *outputDir, now) if err != nil { fmt.Fprintf(os.Stderr, "error: %s\n", err) hasErrors = true continue } zoneFile := cfg.Catalogs[catName].Zone + "zone" if changed { fmt.Fprintf(os.Stderr, "%s: updated\n", zoneFile) } else { fmt.Fprintf(os.Stderr, "%s: unchanged\n", zoneFile) } } if *bindConf != "" { if err := writeBindConf(*bindConf, entries); err != nil { fmt.Fprintf(os.Stderr, "error: %s\n", err) hasErrors = true } else { fmt.Fprintf(os.Stderr, "%s: written\n", *bindConf) } } if hasErrors { os.Exit(1) } }