예제 #1
0
// 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
}
예제 #2
0
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
}