summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Gerus <rgerus@dpd.com.pl>2015-12-14 14:58:42 +0100
committerRobert Gerus <rgerus@dpd.com.pl>2015-12-14 14:58:42 +0100
commitacad1ec1cb0f650e8d8966511e3b06ed299cf37c (patch)
treea8a1d2fbb6b8f330b03f9f0917b25b9e5eb5c734
parent58239223169b9a94ce579e2ee7fe495646187579 (diff)
downloadgorepost-acad1ec1cb0f650e8d8966511e3b06ed299cf37c.tar.gz
gorepost-acad1ec1cb0f650e8d8966511e3b06ed299cf37c.tar.bz2
gorepost-acad1ec1cb0f650e8d8966511e3b06ed299cf37c.tar.xz
gorepost-acad1ec1cb0f650e8d8966511e3b06ed299cf37c.zip
Use external dyncfg.
-rw-r--r--.travis.yml1
-rw-r--r--bot/bot.go6
-rw-r--r--config/.testconfig.json7
-rw-r--r--config/config.go192
-rw-r--r--config/config_test.go246
-rw-r--r--config/doc.go6
-rw-r--r--gorepost.go4
-rw-r--r--irc/irc.go6
8 files changed, 8 insertions, 460 deletions
diff --git a/.travis.yml b/.travis.yml
index cd0f0fd..2add50e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,7 +10,6 @@ notifications:
before_install:
- go get github.com/arachnist/gorepost/bot
- go get github.com/arachnist/gorepost/irc
- - go get github.com/arachnist/gorepost/config
- go get github.com/axw/gocov/gocov
- go get github.com/mattn/goveralls
- go get github.com/go-playground/overalls
diff --git a/bot/bot.go b/bot/bot.go
index e5c1d50..19fc6a9 100644
--- a/bot/bot.go
+++ b/bot/bot.go
@@ -1,14 +1,14 @@
package bot
import (
- "github.com/arachnist/gorepost/config"
+ "github.com/arachnist/dyncfg"
"sync"
)
-var cfg *config.Config
+var cfg *dyncfg.Dyncfg
var cfgLock sync.Mutex
-func Initialize(config *config.Config) {
+func Initialize(config *dyncfg.Dyncfg) {
cfg = config
cfgLock.Unlock()
}
diff --git a/config/.testconfig.json b/config/.testconfig.json
deleted file mode 100644
index 657940a..0000000
--- a/config/.testconfig.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "TestLookup":"this can be anything you can imagine, but now it's just a string",
- "TestLookupString":"this should be a string",
- "TestLookupStringSlice":["i", "am", "going", "to", "be", "a", "slice"],
- "TestLookupStringMap":["I", "want", "to", "be", "a", "map[string]bool"],
- "ThisWillBeAnInt":42
-}
diff --git a/config/config.go b/config/config.go
deleted file mode 100644
index 388436d..0000000
--- a/config/config.go
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2015 Robert S. Gerus. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package config
-
-import (
- "encoding/json"
- "io/ioutil"
- "log"
- "os"
- "sort"
- "sync"
- "time"
-)
-
-type cacheEntry struct {
- modTime time.Time
- contents interface{}
-}
-
-// A Config is a dynamic configuration key lookup mechanism.
-type Config struct {
- cache map[string]cacheEntry
- buildFileList func(map[string]string) []string
- l sync.Mutex
-}
-
-// New takes a file list builder and returns a new instance of Config.
-//
-// The instance is ready to use.
-func New(f func(map[string]string) []string) *Config {
- var c Config
- c.cache = make(map[string]cacheEntry)
- c.buildFileList = f
- return &c
-}
-
-func (c *Config) lookupvar(key, path string) interface{} {
- var f interface{}
- i, err := os.Stat(path)
- _, ok := c.cache[path]
- if os.IsNotExist(err) {
- log.Println("Config does not exist", path)
- if ok {
- log.Println("Purging", path, "from cache")
- delete(c.cache, path)
- }
- }
- if err != nil {
- return nil
- }
-
- if c.cache[path].modTime.Before(i.ModTime()) || !ok {
- log.Println("Stale cache for", path)
- data, err := ioutil.ReadFile(path)
- if err != nil {
- log.Println("Purging", path, "from cache:", err)
- delete(c.cache, path)
- return nil
- }
-
- err = json.Unmarshal(data, &f)
- if err != nil {
- log.Println("Cannot parse", path)
- log.Println("Purging", path, "from cache:", err)
- delete(c.cache, path)
- return nil
- }
-
- log.Println("Updating cache for", path)
- c.cache[path] = cacheEntry{
- modTime: i.ModTime(),
- contents: f,
- }
-
- return f.(map[string]interface{})[key]
- }
-
- log.Println("Found cache for", path)
- return c.cache[path].contents.(map[string]interface{})[key]
-}
-
-// Lookup searches for requested configuration key in file list built using
-// context.
-func (c *Config) Lookup(context map[string]string, key string) interface{} {
- var value interface{}
-
- c.l.Lock()
- defer c.l.Unlock()
-
- for _, fpath := range c.buildFileList(context) {
- log.Println("Context:", context, "Looking up", key, "in", fpath)
- value = c.lookupvar(key, fpath)
- if value != nil {
- log.Println("Context:", context, "Found", key, value)
- return value
- }
- }
-
- log.Println("Context:", context, "Key", key, "not found")
- return nil
-}
-
-// LookupString is analogous to Lookup(), but does the cast to string.
-func (c *Config) LookupString(context map[string]string, key string) string {
- var value interface{}
-
- c.l.Lock()
- defer c.l.Unlock()
-
- for _, fpath := range c.buildFileList(context) {
- log.Println("Context:", context, "Looking up", key, "in", fpath)
- value = c.lookupvar(key, fpath)
- if value != nil {
- log.Println("Context:", context, "Found", key, value)
- return value.(string)
- }
- }
-
- log.Println("Context:", context, "Key", key, "not found")
- return ""
-}
-
-// LookupInt is analogous to Lookup(), but does the cast to int.
-func (c *Config) LookupInt(context map[string]string, key string) int {
- var value interface{}
-
- c.l.Lock()
- defer c.l.Unlock()
-
- for _, fpath := range c.buildFileList(context) {
- log.Println("Context:", context, "Looking up", key, "in", fpath)
- value = c.lookupvar(key, fpath)
- if value != nil {
- log.Println("Context:", context, "Found", key, value)
- return int(value.(float64))
- }
- }
-
- log.Println("Context:", context, "Key", key, "not found")
- return -1
-}
-
-// LookupStringSlice is analogous to Lookup(), but does the cast to []string
-func (c *Config) LookupStringSlice(context map[string]string, key string) (retval []string) {
- var value interface{}
-
- c.l.Lock()
- defer c.l.Unlock()
-
- for _, fpath := range c.buildFileList(context) {
- log.Println("Context:", context, "Looking up", key, "in", fpath)
- value = c.lookupvar(key, fpath)
- if value != nil {
- log.Println("Context:", context, "Found", key, value)
- for _, s := range value.([]interface{}) {
- retval = append(retval, s.(string))
- }
- sort.Strings(retval)
- return retval
- }
- }
-
- log.Println("Context:", context, "Key", key, "not found")
- return []string{""}
-}
-
-// LookupStringMap is analogous to Lookup(), but does the cast to
-// map[string]bool for optimised lookups.
-func (c *Config) LookupStringMap(context map[string]string, key string) (retval map[string]bool) {
- var value interface{}
- retval = make(map[string]bool)
-
- c.l.Lock()
- defer c.l.Unlock()
-
- for _, fpath := range c.buildFileList(context) {
- log.Println("Context:", context, "Looking up", key, "in", fpath)
- value = c.lookupvar(key, fpath)
- if value != nil {
- log.Println("Context:", context, "Found", key, value)
- for _, s := range value.([]interface{}) {
- retval[s.(string)] = true
- }
- return retval
- }
- }
-
- log.Println("Context:", context, "Key", key, "not found")
- return retval
-}
diff --git a/config/config_test.go b/config/config_test.go
deleted file mode 100644
index 91ce934..0000000
--- a/config/config_test.go
+++ /dev/null
@@ -1,246 +0,0 @@
-// +build go1.4
-
-// Copyright 2015 Robert S. Gerus. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-package config
-
-import (
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "reflect"
- "testing"
- "time"
-)
-
-var emptyContext map[string]string
-
-// func Lookup(context map[string]string, key string) interface{}
-var testsLookup = []struct {
- key string
- expectedValue string
-}{
- {
- key: "TestLookup",
- expectedValue: "this can be anything you can imagine, but now it's just a string",
- },
- {
- key: "NotExisting",
- expectedValue: "<nil>",
- },
-}
-
-func TestLookup(t *testing.T) {
- for i, e := range testsLookup {
- v := c.Lookup(emptyContext, e.key)
- if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
- t.Log("test#", i, "Lookup key", e.key)
- t.Logf("expected: %+v\n", e.expectedValue)
- t.Logf("result : %+v\n", v)
- t.Fail()
- }
- }
-}
-
-// func LookupString(context map[string]string, key string) string
-var testsLookupString = []struct {
- key string
- expectedValue string
-}{
- {
- key: "TestLookupString",
- expectedValue: "this should be a string",
- },
- {
- key: "NotExisting",
- expectedValue: "",
- },
-}
-
-func TestLookupString(t *testing.T) {
- for i, e := range testsLookupString {
- v := c.LookupString(emptyContext, e.key)
- if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
- t.Log("test#", i+1, "Lookup key", e.key)
- t.Logf("expected: %+v\n", e.expectedValue)
- t.Logf("result : %+v\n", v)
- t.Fail()
- }
- }
-}
-
-// func LookupInt(context map[string]string, key string) int
-var testsLookupInt = []struct {
- key string
- expectedValue int
-}{
- {
- key: "ThisWillBeAnInt",
- expectedValue: 42,
- },
- {
- key: "NotExisting",
- expectedValue: -1,
- },
-}
-
-func TestLookupInt(t *testing.T) {
- for i, e := range testsLookupInt {
- v := c.LookupInt(emptyContext, e.key)
- if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
- t.Log("test#", i+1, "Lookup key", e.key)
- t.Logf("expected: %+v\n", e.expectedValue)
- t.Logf("result : %+v\n", v)
- t.Fail()
- }
- }
-}
-
-// func LookupStringSlice(context map[string]string, key string) []string
-var testsLookupStringSlice = []struct {
- key string
- expectedValue []string
-}{
- {
- // TestLookupStringSlice return slice is ordered
- key: "TestLookupStringSlice",
- expectedValue: []string{"a", "am", "be", "going", "i", "slice", "to"},
- },
- {
- key: "NotExisting",
- expectedValue: []string{""},
- },
-}
-
-func TestLookupStringSlice(t *testing.T) {
- for i, e := range testsLookupStringSlice {
- v := c.LookupStringSlice(emptyContext, e.key)
- if fmt.Sprintf("%+v", v) != fmt.Sprintf("%+v", e.expectedValue) {
- t.Log("test#", i+1, "Lookup key", e.key)
- t.Logf("expected: %+v\n", e.expectedValue)
- t.Logf("result : %+v\n", v)
- t.Fail()
- }
- }
-}
-
-// func LookupStringMap(context map[string]string, key string) map[string]bool
-var testsLookupStringMap = []struct {
- key string
- expectedValue map[string]bool
-}{
- {
- key: "TestLookupStringMap",
- expectedValue: map[string]bool{
- "to": true,
- "be": true,
- "a": true,
- "map[string]bool": true,
- "I": true,
- "want": true,
- },
- },
- {
- key: "NotExisting",
- expectedValue: map[string]bool{},
- },
-}
-
-func TestLookupStringMap(t *testing.T) {
- for i, e := range testsLookupStringMap {
- v := c.LookupStringMap(emptyContext, e.key)
- if !reflect.DeepEqual(v, e.expectedValue) {
- t.Log("test#", i+1, "Lookup key", e.key)
- t.Logf("expected: %+v\n", e.expectedValue)
- t.Logf("result : %+v\n", v)
- t.Fail()
- }
- }
-}
-
-func configLookupHelper(map[string]string) []string {
- return []string{"this/thing/does/not/exist.json", ".testconfig.json"}
-}
-
-func complicatedLookupHelper(map[string]string) []string {
- return []string{
- ".to-be-removed.json",
- ".to-be-replaced-with-gibberish.json",
- ".to-be-chmoded-000.json",
- ".to-be-replaced.json",
- }
-}
-
-var testEvents = []struct {
- desc string
- action func()
- ev int
-}{
- {
- desc: "remove file",
- action: func() { _ = os.Remove(".to-be-removed.json") },
- ev: 1,
- },
- {
- desc: "replace with gibberish",
- action: func() {
- _ = ioutil.WriteFile(".to-be-replaced-with-gibberish.json", []byte("!@#%^&!%@$&*#@@%*@^#$^&*@&(!"), 0644)
- },
- ev: 2,
- },
- {
- desc: "chmod 000",
- action: func() {
- _ = os.Chmod(".to-be-chmoded-000.json", 0000)
- _ = os.Chtimes(".to-be-chmoded-000.json", time.Now().Local(), time.Now().Local())
- },
- ev: 3,
- },
- {
- desc: "replace",
- action: func() { _ = ioutil.WriteFile(".to-be-replaced.json", []byte("{\"testkey\":99}"), 0644) },
- ev: 99,
- },
-}
-
-func TestLookupvarConditions(t *testing.T) {
- // create files and put their parsed contents in cache
- for i := len(complicatedLookupHelper(emptyContext)) - 1; i >= 0; i-- {
- path := complicatedLookupHelper(emptyContext)[i]
- err := ioutil.WriteFile(path, []byte(fmt.Sprintf("{\"testkey\":%d}", i)), 0644)
- if err != nil {
- t.Log("file write failed")
- }
-
- if i != c2.LookupInt(emptyContext, "testkey") {
- t.Log("LookupInt did not return correct value", i)
- t.Fail()
- }
- }
-
- time.Sleep(time.Second) // make sure we get to update cache
-
- for _, e := range testEvents {
- e.action()
- v := c2.LookupInt(emptyContext, "testkey")
- if e.ev != v {
- t.Log("Test failed:", e.desc, "expected:", e.ev, "got:", v)
- t.Fail()
- }
- }
-
- for _, p := range complicatedLookupHelper(emptyContext) {
- _ = os.Remove(p)
- }
-}
-
-var c *Config = New(configLookupHelper)
-var c2 *Config = New(complicatedLookupHelper)
-
-func TestMain(m *testing.M) {
- log.SetOutput(ioutil.Discard)
- os.Exit(m.Run())
-}
diff --git a/config/doc.go b/config/doc.go
deleted file mode 100644
index 464f2a7..0000000
--- a/config/doc.go
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright 2015 Robert S. Gerus. All rights reserved.
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file.
-
-// Package config is a hiera-inspired configuration library.
-package config
diff --git a/gorepost.go b/gorepost.go
index b153203..0775fec 100644
--- a/gorepost.go
+++ b/gorepost.go
@@ -10,8 +10,8 @@ import (
"os"
"path"
+ "github.com/arachnist/dyncfg"
"github.com/arachnist/gorepost/bot"
- "github.com/arachnist/gorepost/config"
"github.com/arachnist/gorepost/irc"
)
@@ -50,7 +50,7 @@ func main() {
log.Fatalln("Not a directory:", os.Args[1])
}
- cfg := config.New(fileListFuncBuilder(os.Args[1], "common.json"))
+ cfg := dyncfg.New(fileListFuncBuilder(os.Args[1], "common.json"))
logfile, err := os.OpenFile(cfg.LookupString(context, "Logpath"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
diff --git a/irc/irc.go b/irc/irc.go
index c3049e7..24f9d3d 100644
--- a/irc/irc.go
+++ b/irc/irc.go
@@ -12,7 +12,7 @@ import (
"sync"
"time"
- "github.com/arachnist/gorepost/config"
+ "github.com/arachnist/dyncfg"
)
const delim byte = '\n'
@@ -32,7 +32,7 @@ type Connection struct {
quitrecv chan struct{}
quitkeeper chan struct{}
l sync.Mutex
- cfg *config.Config
+ cfg *dyncfg.Dyncfg
}
// Sender sends IRC messages to server and logs their contents.
@@ -179,7 +179,7 @@ func (c *Connection) Keeper() {
}
// Setup performs initialization tasks.
-func (c *Connection) Setup(dispatcher func(func(Message), Message), network string, config *config.Config) {
+func (c *Connection) Setup(dispatcher func(func(Message), Message), network string, config *dyncfg.Dyncfg) {
rand.Seed(time.Now().UnixNano())
c.reconnect = make(chan struct{}, 1)