mirror of
https://github.com/alice-lg/birdwatcher.git
synced 2025-03-09 00:00:05 +01:00
A configuration file describing a small state machine with chaining
regexps. We currently don't do anything with the matching fields, though.
This commit is contained in:
parent
f331b7c350
commit
74cf806e6c
4 changed files with 187 additions and 2 deletions
105
birdwatcher.go
105
birdwatcher.go
|
@ -1,12 +1,115 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"log/syslog"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var debug int = 0
|
||||
var slog *syslog.Writer // Our syslog connection
|
||||
var conf Config
|
||||
|
||||
type Match struct {
|
||||
Expr string // The regular expression as a string.
|
||||
Fields []string // The named fields for grouped expressions.
|
||||
Next string // The next regular expression in the flow.
|
||||
}
|
||||
|
||||
// Compiled regular expression and it's corresponding match data.
|
||||
type RE struct {
|
||||
RE *regexp.Regexp
|
||||
Match Match
|
||||
}
|
||||
|
||||
// The configuration found in the configuration file.
|
||||
type FileConfig struct {
|
||||
Matches map[string]Match // All our regular expressions and related data.
|
||||
Listen string // Listen to this address:port for HTTP.
|
||||
FileName string // File to look for patterns
|
||||
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Conf FileConfig
|
||||
Res map[string]RE
|
||||
}
|
||||
|
||||
// Parse the configuration file. Returns the configuration.
|
||||
func parseconfig(filename string) (conf *Config, err error) {
|
||||
conf = new(Config)
|
||||
|
||||
contents, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fileconf := new(FileConfig)
|
||||
if err = yaml.Unmarshal(contents, &fileconf); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
conf.Res = make(map[string]RE)
|
||||
|
||||
// Build the regexps from the configuration.
|
||||
for key, match := range fileconf.Matches {
|
||||
var err error
|
||||
var re RE
|
||||
|
||||
re.Match = match
|
||||
re.RE, err = regexp.Compile(match.Expr)
|
||||
if err != nil {
|
||||
slog.Err("Couldn't compile re: " + match.Expr)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
// Check that the number of capturing groups matches the number of expected fields.
|
||||
lengroups := len(re.RE.SubexpNames()) - 1
|
||||
lenfields := len(re.Match.Fields)
|
||||
|
||||
if lengroups != lenfields {
|
||||
line := fmt.Sprintf("Number of capturing groups (%v) not equal to number of fields (%v): %s", lengroups, lenfields, re.Match.Expr)
|
||||
slog.Err(line)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
conf.Res[key] = re
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
var configfile = flag.String("config", "birdwatcher.yaml", "Path to configuration file")
|
||||
var flagdebug = flag.Int("debug", 0, "Be more verbose")
|
||||
flag.Parse()
|
||||
|
||||
debug = *flagdebug
|
||||
|
||||
slog, err := syslog.New(syslog.LOG_ERR, "birdwatcher")
|
||||
if err != nil {
|
||||
fmt.Printf("Couldn't open syslog")
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
slog.Debug("birdwatcher starting")
|
||||
|
||||
conf, err := parseconfig(*configfile)
|
||||
if err != nil {
|
||||
slog.Err("Couldn't parse configuration file: " + err.Error())
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
fmt.Printf("%v\n", conf)
|
||||
|
||||
r := httprouter.New()
|
||||
r.GET("/status", Status)
|
||||
r.GET("/routes", Routes)
|
||||
|
|
28
birdwatcher.yaml
Normal file
28
birdwatcher.yaml
Normal file
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
filename: v4-show-protocols-all.txt
|
||||
|
||||
# A map of all the expected patterns.
|
||||
# fields: A list of variables to set from the grouped patterns.
|
||||
# expr: The regular expression.
|
||||
# next: The next regexp to go to after the current one has a match. ""
|
||||
# if we are finished.
|
||||
# action: What to do with the stored values.
|
||||
|
||||
matches:
|
||||
|
||||
# pp_0236_as10310 Pipe master up 2016-07-22 => t_0236_as10310
|
||||
getprotocol:
|
||||
fields:
|
||||
- name
|
||||
- prot
|
||||
- date
|
||||
- status
|
||||
expr: "^([A-Z][a-z][0-9]*) (.*) .* (.*) (.*)"
|
||||
next: "protdescription"
|
||||
|
||||
# Description: Pipe for AS10310 - Yahoo! - VLAN Interface 236
|
||||
protdescription:
|
||||
fields:
|
||||
- desc
|
||||
expr: " Description: (.*)"
|
||||
next: ""
|
46
patterns.go
Normal file
46
patterns.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// readLines reads a whole file into memory
|
||||
// and returns a slice of its lines.
|
||||
func readLines(path string) ([]string, error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
var lines []string
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
}
|
||||
return lines, scanner.Err()
|
||||
}
|
||||
|
||||
// pattern looks for pattern matching regular expression re in the
|
||||
// lines buffer. Returns the name of our next regular expression to
|
||||
// look for.
|
||||
func pattern(re RE, lines []string) (next string) {
|
||||
for _, line := range lines {
|
||||
if debug > 1 {
|
||||
slog.Debug("Looking at: " + line)
|
||||
}
|
||||
|
||||
fields := re.RE.FindStringSubmatch(line)
|
||||
|
||||
if len(fields)-1 == len(re.Match.Fields) {
|
||||
if debug > 0 {
|
||||
line := fmt.Sprintf("Found match for a message of type '%v'", re.Match)
|
||||
slog.Debug(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return re.Match.Next
|
||||
}
|
10
routes.go
10
routes.go
|
@ -2,10 +2,18 @@ package main
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"net/http"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
)
|
||||
|
||||
func Protocols(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||
fmt.Fprint(w, "protocols\n")
|
||||
|
||||
lines, err := readLines(conf.Conf.FileName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
pattern(conf.Res["getprotocol"], lines)
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue