// Decodes and evaluates a json config file, watching for include cycles. func (c *ConfigParser) recursiveReadJSON(configPath string) (decodedObject map[string]interface{}, err error) { if configPath != "" { absConfigPath, err := filepath.Abs(configPath) if err != nil { return nil, fmt.Errorf("Failed to expand absolute path for %s", configPath) } if c.touchedFiles[absConfigPath] { return nil, fmt.Errorf("ConfigParser include cycle detected reading config: %v", absConfigPath) } c.touchedFiles[absConfigPath] = true c.includeStack.Push(absConfigPath) defer c.includeStack.Pop() } var f File if f, err = c.open(configPath); err != nil { return nil, fmt.Errorf("Failed to open config: %v", err) } defer f.Close() decodedObject = make(map[string]interface{}) dj := json.NewDecoder(f) if err = dj.Decode(&decodedObject); err != nil { extra := "" if serr, ok := err.(*json.SyntaxError); ok { if _, serr := f.Seek(0, os.SEEK_SET); serr != nil { log.Fatalf("seek error: %v", serr) } line, col, highlight := errorutil.HighlightBytePosition(f, serr.Offset) extra = fmt.Sprintf(":\nError at line %d, column %d (file offset %d):\n%s", line, col, serr.Offset, highlight) } return nil, fmt.Errorf("error parsing JSON object in config file %s%s\n%v", f.Name(), extra, err) } if err = c.evaluateExpressions(decodedObject, nil, false); err != nil { return nil, fmt.Errorf("error expanding JSON config expressions in %s:\n%v", f.Name(), err) } return decodedObject, nil }
func readZoneFile(zoneName, fileName string) (zone *Zone, zerr error) { defer func() { if r := recover(); r != nil { log.Printf("reading %s failed: %s", zoneName, r) debug.PrintStack() zerr = fmt.Errorf("reading %s failed: %s", zoneName, r) } }() fh, err := os.Open(fileName) if err != nil { log.Printf("Could not read '%s': %s", fileName, err) panic(err) } zone = NewZone(zoneName) fileInfo, err := fh.Stat() if err != nil { log.Printf("Could not stat '%s': %s", fileName, err) } else { zone.Options.Serial = int(fileInfo.ModTime().Unix()) } var objmap map[string]interface{} decoder := json.NewDecoder(fh) if err = decoder.Decode(&objmap); err != nil { extra := "" if serr, ok := err.(*json.SyntaxError); ok { if _, serr := fh.Seek(0, os.SEEK_SET); serr != nil { log.Fatalf("seek error: %v", serr) } line, col, highlight := errorutil.HighlightBytePosition(fh, serr.Offset) extra = fmt.Sprintf(":\nError at line %d, column %d (file offset %d):\n%s", line, col, serr.Offset, highlight) } return nil, fmt.Errorf("error parsing JSON object in config file %s%s\n%v", fh.Name(), extra, err) } if err != nil { panic(err) } //log.Println(objmap) var data map[string]interface{} for k, v := range objmap { //log.Printf("k: %s v: %#v, T: %T\n", k, v, v) switch k { case "ttl", "serial", "max_hosts", "contact": switch option := k; option { case "ttl": zone.Options.Ttl = valueToInt(v) case "serial": zone.Options.Serial = valueToInt(v) case "contact": zone.Options.Contact = v.(string) case "max_hosts": zone.Options.MaxHosts = valueToInt(v) case "targeting": zone.Options.Targeting, err = parseTargets(v.(string)) if err != nil { log.Printf("Could not parse targeting '%s': %s", v, err) return nil, err } } case "logging": { logging := new(ZoneLogging) for logger, v := range v.(map[string]interface{}) { switch logger { case "stathat": logging.StatHat = valueToBool(v) case "stathat_api": logging.StatHatAPI = valueToString(v) logging.StatHat = true default: log.Println("Unknown logger option", logger) } } zone.Logging = logging // log.Printf("logging options: %#v", logging) } continue case "data": data = v.(map[string]interface{}) } } setupZoneData(data, zone) //log.Printf("ZO T: %T %s\n", Zones["0.us"], Zones["0.us"]) //log.Println("IP", string(Zone.Regions["0.us"].IPv4[0].ip)) switch { case zone.Options.Targeting >= TargetRegionGroup: geoIP.setupGeoIPCity() case zone.Options.Targeting >= TargetContinent: geoIP.setupGeoIPCountry() } return zone, nil }