diff --git a/bird/bird.go b/bird/bird.go index 85a9d6a..f498cd7 100644 --- a/bird/bird.go +++ b/bird/bird.go @@ -7,7 +7,8 @@ import ( "time" ) -var Conf BirdConfig +var ClientConf BirdConfig +var StatusConf StatusConfig var Cache = struct { sync.RWMutex @@ -31,7 +32,7 @@ func toCache(key string, val Parsed) { func Run(args string) ([]byte, error) { args = "show " + args argsList := strings.Split(args, " ") - return exec.Command(Conf.BirdCmd, argsList...).Output() + return exec.Command(ClientConf.BirdCmd, argsList...).Output() } func RunAndParse(cmd string, parser func([]byte) Parsed) (Parsed, bool) { @@ -52,7 +53,30 @@ func RunAndParse(cmd string, parser func([]byte) Parsed) (Parsed, bool) { } func Status() (Parsed, bool) { - return RunAndParse("status", parseStatus) + birdStatus, ok := RunAndParse("status", parseStatus) + + // Last Reconfig Timestamp source: + var lastReconfig string + switch StatusConf.ReconfigTimestampSource { + case "bird": + lastReconfig = birdStatus["last_reconfig"].(string) + break + case "config_modified": + lastReconfig = lastReconfigTimestampFromFileStat( + ClientConf.ConfigFilename, + ) + case "config_regex": + lastReconfig = lastReconfigTimestampFromFileContent( + ClientConf.ConfigFilename, + StatusConf.ReconfigTimestampMatch, + ) + } + + birdStatus["lastReconfig"] = lastReconfig + + // Filter fields + + return birdStatus, ok } func Protocols() (Parsed, bool) { diff --git a/bird/status.go b/bird/status.go new file mode 100644 index 0000000..609b357 --- /dev/null +++ b/bird/status.go @@ -0,0 +1,47 @@ +package bird + +import ( + "bufio" + "fmt" + "os" + "regexp" +) + +// Get last reconfig timestamp from file modification date +func lastReconfigTimestampFromFileStat(filename string) string { + info, err := os.Stat(filename) + if err != nil { + return fmt.Sprintf("Could not fetch file modified timestamp: %s", err) + } + + modTime := info.ModTime().UTC() + buf, _ := modTime.MarshalJSON() + + return string(buf) +} + +// Parse config file linewise, find matching line and extract date +func lastReconfigTimestampFromFileContent(filename string, regex string) string { + rx := regexp.MustCompile(regex) + + // Read config file linewise + file, err := os.Open(filename) + if err != nil { + return fmt.Sprintf("Could not read: %s", err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + matches := rx.FindStringSubmatch(scanner.Text()) + if len(matches) > 0 { + return matches[1] + } + } + + if err := scanner.Err(); err != nil { + return fmt.Sprintf("Error reading config: %s", err) + } + + return "" +} diff --git a/bird/status_test.go b/bird/status_test.go new file mode 100644 index 0000000..da98c52 --- /dev/null +++ b/bird/status_test.go @@ -0,0 +1,23 @@ +package bird + +// Created: 2016-12-01 14:15:00 + +import ( + "testing" +) + +func TestReconfigTimestampFromStat(t *testing.T) { + + // Just get the modification date of this file + ts := lastReconfigTimestampFromFileStat("./status_test.go") + t.Log(ts) + + ts = lastReconfigTimestampFromFileStat("./___i_do_not_exist___") + t.Log(ts) +} + +func TestReconfigTimestampFromContent(t *testing.T) { + + ts := lastReconfigTimestampFromFileContent("./status_test.go", "// Created: (.*)") + t.Log(ts) +} diff --git a/birdwatcher.go b/birdwatcher.go index 759c4ad..1b99b2b 100644 --- a/birdwatcher.go +++ b/birdwatcher.go @@ -69,7 +69,8 @@ func main() { PrintServiceInfo(conf, birdConf) // Configuration - bird.Conf = birdConf + bird.ClientConf = birdConf + bird.StatusConf = conf.Status endpoints.Conf = conf.Server // Make server