online mapping configuration
This commit is contained in:
parent
05b8981cea
commit
5a486ea48e
103
config/config.go
103
config/config.go
|
@ -1,6 +1,8 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
@ -9,6 +11,8 @@ import (
|
|||
"github.com/boltdb/bolt"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"code.chrissexton.org/cws/lameralert/mapping"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -24,10 +28,29 @@ func (value configValue) getBytes() ([]byte, error) {
|
|||
return json.Marshal(value)
|
||||
}
|
||||
|
||||
func decodeConfig(in []byte) (configValue, error) {
|
||||
var out configValue
|
||||
err := json.Unmarshal(in, &out)
|
||||
return out, err
|
||||
func decodeConfig(in []byte, target *configValue) error {
|
||||
err := json.Unmarshal(in, target)
|
||||
return err
|
||||
}
|
||||
|
||||
func encodeMapping(in mapping.Mapping) ([]byte, error) {
|
||||
var out []byte
|
||||
buf := bytes.NewBuffer(out)
|
||||
enc := gob.NewEncoder(buf)
|
||||
err := enc.Encode(in)
|
||||
return buf.Bytes(), err
|
||||
}
|
||||
|
||||
func decodeMapping(in []byte) (mapping.Mapping, error) {
|
||||
var target mapping.Mapping
|
||||
dec := gob.NewDecoder(bytes.NewBuffer(in))
|
||||
err := dec.Decode(&target)
|
||||
log.Debug().
|
||||
Interface("err", err).
|
||||
Str("in", string(in)).
|
||||
Interface("target", target).
|
||||
Msg("decodeMapping")
|
||||
return target, err
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
@ -65,7 +88,8 @@ func (c *Config) getAll() (map[string]configValue, error) {
|
|||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucket)
|
||||
err := b.ForEach(func(k, v []byte) error {
|
||||
value, err := decodeConfig(v)
|
||||
var value configValue
|
||||
err := decodeConfig(v, &value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert value: %w", err)
|
||||
}
|
||||
|
@ -80,6 +104,31 @@ func (c *Config) getAll() (map[string]configValue, error) {
|
|||
return vals, err
|
||||
}
|
||||
|
||||
func (c *Config) getMapping(key string) (mapping.Mapping, error) {
|
||||
log.Debug().Msgf("getMapping(%s)", key)
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
db := c.db()
|
||||
defer db.Close()
|
||||
var err error
|
||||
var out mapping.Mapping
|
||||
err = db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucket)
|
||||
out, err = decodeMapping(b.Get([]byte(key)))
|
||||
log.Debug().AnErr("err", err).Interface("out", out).Msgf("decode %s", key)
|
||||
if err != nil {
|
||||
log.Error().Msgf("Error decoding: %w", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Error().Msgf("Error getting: %w", err)
|
||||
return mapping.Mapping{}, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *Config) get(key string) (configValue, error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
@ -88,11 +137,10 @@ func (c *Config) get(key string) (configValue, error) {
|
|||
var out configValue
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucket)
|
||||
value, err := decodeConfig(b.Get([]byte(key)))
|
||||
err := decodeConfig(b.Get([]byte(key)), &out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out = value
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -101,6 +149,26 @@ func (c *Config) get(key string) (configValue, error) {
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *Config) setMapping(key string, value mapping.Mapping) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
db := c.db()
|
||||
defer db.Close()
|
||||
err := db.Update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(bucket)
|
||||
v, err := encodeMapping(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = b.Put([]byte(key), v)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
log.Error().Msgf("Error setting key: %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Config) set(key string, value configValue) error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
@ -192,6 +260,27 @@ func (c *Config) GetString(key, defaultValue string) string {
|
|||
return v.Value.(string)
|
||||
}
|
||||
|
||||
func (c *Config) GetMapping(key string, defaultValue mapping.Mapping) mapping.Mapping {
|
||||
m, err := c.getMapping(key)
|
||||
if err != nil {
|
||||
log.Error().Msgf("Error: %w", err)
|
||||
return defaultValue
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func (c *Config) GetGeneric(key string, defaultValue interface{}) interface{} {
|
||||
v, err := c.get(key)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
return v.Value
|
||||
}
|
||||
|
||||
func (c *Config) SetMapping(key string, value mapping.Mapping) error {
|
||||
return c.setMapping(key, value)
|
||||
}
|
||||
|
||||
func (c *Config) Set(key string, value interface{}) error {
|
||||
return c.set(key, configValue{key, value})
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
|
||||
"code.chrissexton.org/cws/lameralert/config"
|
||||
"code.chrissexton.org/cws/lameralert/event"
|
||||
"code.chrissexton.org/cws/lameralert/mapping"
|
||||
"code.chrissexton.org/cws/lameralert/sinks"
|
||||
"code.chrissexton.org/cws/lameralert/sources"
|
||||
)
|
||||
|
@ -28,8 +28,6 @@ func NewConnection(from sources.Source, to sinks.Sink) Connection {
|
|||
}
|
||||
}
|
||||
|
||||
var mapping = map[chan event.Event][]chan event.Event{}
|
||||
|
||||
func logger(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Do stuff here
|
||||
|
@ -38,22 +36,55 @@ func logger(next http.Handler) http.Handler {
|
|||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func Setup() chan bool {
|
||||
r := mux.NewRouter()
|
||||
r.Use(logger)
|
||||
c := config.New(r.PathPrefix("/config").Subrouter())
|
||||
ch := make(chan bool)
|
||||
|
||||
h := sources.NewGenericRest(r.PathPrefix("/rest").Subrouter())
|
||||
NewConnection(h, sinks.NewConsoleID(c, "00"))
|
||||
NewConnection(h, sinks.NewConsoleID(c, "01"))
|
||||
mappings := c.GetMapping("mappings", mapping.Example())
|
||||
|
||||
rss := sources.NewRSS(c, r.PathPrefix("/rss/webshit").Subrouter(), "webshit", "http://n-gate.com/hackernews/index.rss")
|
||||
NewConnection(rss, sinks.NewConsoleID(c, "webshit-sink"))
|
||||
if push, err := sinks.NewPushover(c, "webshit-push"); err != nil {
|
||||
log.Fatal().Msgf("error: %s", err)
|
||||
} else {
|
||||
NewConnection(rss, push)
|
||||
//mappings := mapping.Example()
|
||||
//c.SetMapping("mappings", mappings)
|
||||
|
||||
srcs := map[string]sources.Source{}
|
||||
snks := map[string]sinks.Sink{}
|
||||
for _, source := range mappings.Sources {
|
||||
var src sources.Source
|
||||
// TODO: Move this logic out to the sources package
|
||||
switch source.Type {
|
||||
case "GenericRest":
|
||||
path := source.Config["prefix"]
|
||||
src = sources.NewGenericRest(r.PathPrefix(path).Subrouter())
|
||||
case "RSS":
|
||||
path := source.Config["prefix"]
|
||||
url := source.Config["URL"]
|
||||
src = sources.NewRSS(c, r.PathPrefix(path).Subrouter(), source.Name, url)
|
||||
}
|
||||
srcs[source.Name] = src
|
||||
}
|
||||
|
||||
for _, sink := range mappings.Sinks {
|
||||
var snk sinks.Sink
|
||||
// TODO: Move this logic out to the sinks package
|
||||
switch sink.Type {
|
||||
case "Console":
|
||||
snk = sinks.NewConsoleID(c, sink.Config["ID"])
|
||||
case "Pushover":
|
||||
var err error
|
||||
snk, err = sinks.NewPushover(c, sink.Name)
|
||||
if err != nil {
|
||||
log.Fatal().Msgf("Error setting up pushover: %w", err)
|
||||
}
|
||||
}
|
||||
snks[sink.Name] = snk
|
||||
}
|
||||
|
||||
for _, m := range mappings.Mappings {
|
||||
src := srcs[m.From]
|
||||
snk := snks[m.To]
|
||||
NewConnection(src, snk)
|
||||
}
|
||||
|
||||
http.ListenAndServe(":9090", r)
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package mapping
|
||||
|
||||
type Mapping struct {
|
||||
Sources []MapItem
|
||||
Sinks []MapItem
|
||||
Mappings []MapPair
|
||||
}
|
||||
|
||||
type MapPair struct {
|
||||
From string
|
||||
To string
|
||||
}
|
||||
|
||||
type MapItem struct {
|
||||
Name string
|
||||
Type string
|
||||
Config map[string]string
|
||||
}
|
||||
|
||||
// TODO: Make a web interface to configure these horrible structures
|
||||
func Example() Mapping {
|
||||
mappings := Mapping{}
|
||||
|
||||
webshit := MapItem{
|
||||
Name: "webshit",
|
||||
Type: "RSS",
|
||||
Config: map[string]string{
|
||||
"prefix": "/rss/webshit",
|
||||
"URL": "http://n-gate.com/hackernews/index.rss",
|
||||
},
|
||||
}
|
||||
mappings.Sources = append(mappings.Sources, webshit)
|
||||
genericRest := MapItem{
|
||||
Name: "GenericRest",
|
||||
Type: "GenericRest",
|
||||
Config: map[string]string{
|
||||
"prefix": "/rest",
|
||||
"name": "GenericRest",
|
||||
},
|
||||
}
|
||||
mappings.Sources = append(mappings.Sources, genericRest)
|
||||
consoleZero := MapItem{
|
||||
Name: "Console-00",
|
||||
Type: "Console",
|
||||
Config: map[string]string{
|
||||
"ID": "00",
|
||||
},
|
||||
}
|
||||
mappings.Sinks = append(mappings.Sinks, consoleZero)
|
||||
consoleOne := MapItem{
|
||||
Name: "Console-01",
|
||||
Type: "Console",
|
||||
Config: map[string]string{
|
||||
"ID": "01",
|
||||
},
|
||||
}
|
||||
mappings.Sinks = append(mappings.Sinks, consoleOne)
|
||||
|
||||
pushOver := MapItem{
|
||||
Name: "Pushover",
|
||||
Type: "Pushover",
|
||||
Config: map[string]string{},
|
||||
}
|
||||
mappings.Sinks = append(mappings.Sinks, pushOver)
|
||||
|
||||
mappings.Mappings = append(mappings.Mappings, MapPair{"GenericRest", "Console-00"})
|
||||
mappings.Mappings = append(mappings.Mappings, MapPair{"GenericRest", "Console-01"})
|
||||
mappings.Mappings = append(mappings.Mappings, MapPair{"webshit", "Pushover"})
|
||||
|
||||
return mappings
|
||||
}
|
Loading…
Reference in New Issue