1
0
Fork 0
mirror of https://github.com/alice-lg/birdwatcher.git synced 2025-03-09 00:00:05 +01:00

refactored endpoints

This commit is contained in:
hellerve 2016-11-11 14:14:38 +01:00
parent ce63916596
commit fc0ea09dc3
15 changed files with 127 additions and 3032 deletions

View file

@ -42,7 +42,7 @@ func ProtocolsBgp() Parsed {
}
}
return bgpProto
return Parsed{"protocols": bgpProto}
}
func Symbols() Parsed {

View file

@ -2,128 +2,39 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"log/syslog"
"net/http"
"os"
"regexp"
"strings"
"github.com/julienschmidt/httprouter"
yaml "gopkg.in/yaml.v2"
"github.com/mchackorg/birdwatcher/endpoints"
)
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.
Action string // What to do with the stored fields: "store" or "send".
}
// 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
}
if err = yaml.Unmarshal(contents, &conf.Conf); err != nil {
return
}
conf.Res = make(map[string]RE)
// Build the regexps from the configuration.
for key, match := range conf.Conf.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 makeRouter() *httprouter.Router {
r := httprouter.New()
r.GET("/status", endpoints.Endpoint(endpoints.Status))
r.GET("/protocols/bgp", endpoints.Endpoint(endpoints.Bgp))
r.GET("/symbols", endpoints.Endpoint(endpoints.Symbols))
r.GET("/symbols/tables", endpoints.Endpoint(endpoints.SymbolTables))
r.GET("/symbols/protocols", endpoints.Endpoint(endpoints.SymbolProtocols))
r.GET("/routes/protocol/:protocol", endpoints.Endpoint(endpoints.ProtoRoutes))
r.GET("/routes/table/:table", endpoints.Endpoint(endpoints.TableRoutes))
r.GET("/routes/count/protocol/:protocol", endpoints.Endpoint(endpoints.ProtoCount))
r.GET("/routes/count/table/:table", endpoints.Endpoint(endpoints.TableCount))
r.GET("/route/net/:net", endpoints.Endpoint(endpoints.RouteNet))
r.GET("/route/net/:net/table/:table", endpoints.Endpoint(endpoints.RouteNetTable))
r.GET("/protocols", endpoints.Endpoint(endpoints.Protocols))
return r
}
func main() {
var configfile = flag.String("config", "birdwatcher.yaml", "Path to configuration file")
var flagdebug = flag.Int("debug", 0, "Be more verbose")
port := flag.String("port",
"29184",
"The port the birdwatcher should run on")
flag.Parse()
debug = *flagdebug
r := makeRouter()
slog, err := syslog.New(syslog.LOG_ERR, "birdwatcher")
if err != nil {
fmt.Printf("Couldn't open syslog")
os.Exit(-1)
}
slog.Debug("birdwatcher starting")
config, err := parseconfig(*configfile)
if err != nil {
slog.Err("Couldn't parse configuration file: " + err.Error())
os.Exit(-1)
}
conf = config
fmt.Printf("%v\n", conf)
r := httprouter.New()
r.GET("/status", Status) // done
r.GET("/protocols/bgp", Bgp)
r.GET("/symbols", Symbols) // done
r.GET("/symbols/tables", SymbolTables) //done
r.GET("/symbols/protocols", SymbolProtocols) // done
r.GET("/routes/protocol/:protocol", ProtoRoutes) //done
r.GET("/routes/table/:table", TableRoutes) //done
r.GET("/routes/count/protocol/:protocol", ProtoCount) //done
r.GET("/routes/count/table/:table", TableCount) // done
r.GET("/route/net/:net", RouteNet) // done
r.GET("/route/net/:net/table/:table", RouteNetTable) // done
r.GET("/protocols", Protocols) // done
log.Fatal(http.ListenAndServe(":29184", r))
realPort :=strings.Join([]string{":", *port}, "")
log.Fatal(http.ListenAndServe(realPort, r))
}

View file

@ -1,31 +0,0 @@
---
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:
- protocol
- table
- state
- state_changed
- connection
expr: '^(\w+)\s+BGP\s+(\w+)\s+(\w+)\s+([0-9\-]+)\s+(\w+)\s*$'
next: "protdescription"
action: store
# Description: Pipe for AS10310 - Yahoo! - VLAN Interface 236
protdescription:
fields:
- description
expr: " Description: (.*)"
next: "getprotocol" # back again for more similar lines
action: send # Done here, send it back.

30
endpoints/endpoint.go Normal file
View file

@ -0,0 +1,30 @@
package endpoints
import (
"encoding/json"
"net/http"
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
)
func Endpoint(wrapped func(httprouter.Params) (bird.Parsed)) httprouter.Handle {
return func(w http.ResponseWriter,
r *http.Request,
ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
ret := wrapped(ps)
for k, v := range ret {
res[k] = v
}
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
}

14
endpoints/protocols.go Normal file
View file

@ -0,0 +1,14 @@
package endpoints
import (
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
)
func Protocols(ps httprouter.Params) bird.Parsed {
return bird.Protocols()
}
func Bgp(ps httprouter.Params) bird.Parsed {
return bird.ProtocolsBgp()
}

30
endpoints/routes.go Normal file
View file

@ -0,0 +1,30 @@
package endpoints
import (
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
)
func ProtoRoutes(ps httprouter.Params) bird.Parsed {
return bird.RoutesProto(ps.ByName("protocol"))
}
func TableRoutes(ps httprouter.Params) bird.Parsed {
return bird.RoutesTable(ps.ByName("table"))
}
func ProtoCount(ps httprouter.Params) bird.Parsed {
return bird.RoutesProtoCount(ps.ByName("protocol"))
}
func TableCount(ps httprouter.Params) bird.Parsed {
return bird.RoutesTable(ps.ByName("table"))
}
func RouteNet(ps httprouter.Params) bird.Parsed {
return bird.RoutesLookupTable(ps.ByName("net"), "master")
}
func RouteNetTable(ps httprouter.Params) bird.Parsed {
return bird.RoutesLookupTable(ps.ByName("net"), ps.ByName("table"))
}

10
endpoints/status.go Normal file
View file

@ -0,0 +1,10 @@
package endpoints
import (
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
)
func Status(ps httprouter.Params) bird.Parsed {
return bird.Status()
}

18
endpoints/symbols.go Normal file
View file

@ -0,0 +1,18 @@
package endpoints
import (
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
)
func Symbols(ps httprouter.Params) bird.Parsed {
return bird.Symbols()
}
func SymbolTables(ps httprouter.Params) bird.Parsed {
return bird.Parsed{"symbols": bird.Symbols()["routing table"]}
}
func SymbolProtocols(ps httprouter.Params) bird.Parsed {
return bird.Parsed{"symbols": bird.Symbols()["protocols"]}
}

View file

@ -1,4 +1,4 @@
package main
package endpoints
type TimeInfo struct {
Date string `json:"date"`

View file

@ -1,79 +0,0 @@
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(first string, lines []string) (maplist []map[string]string) {
var re RE
var fieldmap map[string]string
fmt.Printf("In pattern\n")
re, ok := conf.Res[first]
if !ok {
slog.Debug("Couldn't find first state.")
return
}
// Store away all the fields in a map.
fieldmap = make(map[string]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)
}
for key, name := range re.Match.Fields {
if debug > 0 {
slog.Debug("Got " + re.Match.Fields[key])
}
fieldmap[name] = fields[key+1]
}
if re.Match.Action == "send" {
// Finished for this item. Create a new field map and add this to the list.
maplist = append(maplist, fieldmap)
fieldmap = make(map[string]string)
}
// Go to the next state, if it exists. If it
// doesn't we're finished here.
re, ok = conf.Res[re.Match.Next]
if !ok {
break
}
}
}
return maplist
}

View file

@ -1,35 +0,0 @@
package main
import (
"encoding/json"
"net/http"
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
)
func Protocols(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["protocols"] = bird.Protocols()["protocols"]
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func Bgp(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["protocols"] = bird.ProtocolsBgp()
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}

View file

@ -1,83 +0,0 @@
package main
import (
"encoding/json"
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
"net/http"
)
func ProtoRoutes(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["routes"] = bird.RoutesProto(ps.ByName("protocol"))["routes"]
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func TableRoutes(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["routes"] = bird.RoutesTable(ps.ByName("table"))["routes"]
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func ProtoCount(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["count"] = bird.RoutesProtoCount(ps.ByName("protocol"))
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func TableCount(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["count"] = bird.RoutesTable(ps.ByName("table"))
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func RouteNet(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["routes"] = bird.RoutesLookupTable(ps.ByName("net"), "master")
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func RouteNetTable(w http.ResponseWriter,
r *http.Request,
ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["routes"] = bird.RoutesLookupTable(ps.ByName("net"),
ps.ByName("table"))
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}

View file

@ -1,21 +0,0 @@
package main
import (
"encoding/json"
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
"net/http"
)
func Status(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["status"] = bird.Status()
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}

View file

@ -1,51 +0,0 @@
package main
import (
"encoding/json"
"github.com/julienschmidt/httprouter"
"github.com/mchackorg/birdwatcher/bird"
"net/http"
)
func Symbols(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["symbols"] = bird.Symbols()
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func SymbolTables(w http.ResponseWriter,
r *http.Request,
ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["symbols"] = bird.Symbols()["routing table"]
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}
func SymbolProtocols(w http.ResponseWriter,
r *http.Request,
ps httprouter.Params) {
res := make(map[string]interface{})
res["api"] = GetApiInfo()
res["symbols"] = bird.Symbols()["protocol"]
js, _ := json.Marshal(res)
w.Header().Set("Content-Type", "application/json")
w.Write(js)
}

File diff suppressed because it is too large Load diff