Skip to content

Commit

Permalink
add new way to load variables like flags library
Browse files Browse the repository at this point in the history
add consul layer
  • Loading branch information
fzerorubigd committed May 6, 2017
1 parent 0789309 commit 13a2dee
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 28 deletions.
17 changes: 8 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
language: go
dist: trusty
go:
- 1.1
- 1.2
- 1.3
- 1.4
- 1.5
- 1.7
- 1.8
- tip
before_install:
- go get -v github.com/smartystreets/goconvey
- go get -v github.com/axw/gocov/gocov
- go get -v github.com/mattn/goveralls
- go get -v github.com/hashicorp/consul/testutil
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
- go get -v github.com/hashicorp/consul
- go get -v ./...
script:
- goveralls -v -service travis-ci -repotoken $COVERALLS_TOKEN || go test -v
matrix:
allow_failures:
- go: 1.1
- goveralls -v -service travis-ci -repotoken $COVERALLS_TOKEN || go test -v ./...

60 changes: 60 additions & 0 deletions consulloader/consul_layer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package consulloader

import (
"testing"

"fmt"

"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/testutil"
. "github.com/smartystreets/goconvey/convey"
. "gopkg.in/fzerorubigd/onion.v3"
)

func TestConsulLoader(t *testing.T) {
// Create a test Consul server
srv1, err := testutil.NewTestServer()
if err != nil {
t.Fatal(err)
}
defer srv1.Stop()

//// Create a secondary server, passing in configuration
//// to avoid bootstrapping as we are forming a cluster.
//srv2, err := testutil.NewTestServerConfig(func(c *testutil.TestServerConfig) {
// c.Bootstrap = false
//})
//if err != nil {
// t.Fatal(err)
//}
//defer srv2.Stop()

// Join the servers together
//srv1.JoinLAN(t, srv2.LANAddr)

client, err := api.NewClient(
&api.Config{
HttpClient: srv1.HTTPClient,
Address: srv1.HTTPAddr,
},
)

Convey("Extra env in config", t, func() {

o := New()
layer := NewConsulLayer(client, "prefix")
o.AddLazyLayer(layer)
Convey("check data from env", func() {
srv1.SetKV(t, "prefix/data/nested", []byte("TDN"))
fmt.Println(string(srv1.GetKV(t, "prefix/data/nested")))
So(o.GetString("data.nested"), ShouldEqual, "TDN")
})

Convey("check data not in env", func() {
So(o.GetString("not.valid.data"), ShouldEqual, "")
So(o.GetString(""), ShouldEqual, "")
})

})

}
36 changes: 36 additions & 0 deletions consulloader/consule_layer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Package consulloader is a simple loader to handle Reading from consul.
// its a simple read only functionality.
package consulloader

import (
"path/filepath"

"github.com/hashicorp/consul/api"
"gopkg.in/fzerorubigd/onion.v3"
)

type layer struct {
client *api.KV
prefix string
}

func (l layer) Get(path ...string) (interface{}, bool) {
p := filepath.Join(l.prefix, filepath.Join(path...))
kv, _, err := l.client.Get(p, nil)
if err != nil {
// I don't think this is correct. may be panic?
return nil, false
}
if kv == nil {
return nil, false
}
return string(kv.Value), true
}

// NewConsulLayer create a new lazy layer from a consul client
func NewConsulLayer(c *api.Client, prefix string) onion.LazyLayer {
return &layer{
client: c.KV(),
prefix: prefix,
}
}
2 changes: 1 addition & 1 deletion example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"os"
"path/filepath"

"gopkg.in/fzerorubigd/onion.v2"
"gopkg.in/fzerorubigd/onion.v3"
)

func pwd() string {
Expand Down
3 changes: 1 addition & 2 deletions extraenv/env_layer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ package extraenv
import (
"os"
"strings"

"gopkg.in/fzerorubigd/onion.v2"
"gopkg.in/fzerorubigd/onion.v3"
)

type envLoader struct {
Expand Down
2 changes: 1 addition & 1 deletion extraenv/env_layer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"

. "github.com/smartystreets/goconvey/convey"
. "gopkg.in/fzerorubigd/onion.v2"
. "gopkg.in/fzerorubigd/onion.v3"
)

func TestExtraEnvLoader(t *testing.T) {
Expand Down
3 changes: 1 addition & 2 deletions flagslayer/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ import (
"flag"
"os"
"time"

"gopkg.in/fzerorubigd/onion.v2"
"gopkg.in/fzerorubigd/onion.v3"
)

// FlagLayer is for handling the layer
Expand Down
2 changes: 1 addition & 1 deletion flagslayer/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"testing"
"time"

. "gopkg.in/fzerorubigd/onion.v2"
. "github.com/smartystreets/goconvey/convey"
. "gopkg.in/fzerorubigd/onion.v3"
)

func TestFlagsLoader(t *testing.T) {
Expand Down
131 changes: 123 additions & 8 deletions onion.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import (
// DefaultDelimiter is the default delimiter for the config scope
const DefaultDelimiter = "."

var lock = &sync.RWMutex{}

// Layer is an interface to handle the load phase.
type Layer interface {
// Load a layer into the Onion. the call is only done in the
Expand All @@ -36,10 +34,19 @@ type singleLayer struct {

type layerList []singleLayer

type variable struct {
key string
ref interface{}
}

// Onion is a layer base configuration system
type Onion struct {
delimiter string
ll layerList
llock sync.RWMutex

references []variable
refLock sync.RWMutex
}

func (sl singleLayer) getData(d string, path ...string) (interface{}, bool) {
Expand All @@ -52,8 +59,8 @@ func (sl singleLayer) getData(d string, path ...string) (interface{}, bool) {
// AddLayer add a new layer to the end of config layers. last layer is loaded after all other
// layer
func (o *Onion) AddLayer(l Layer) error {
lock.Lock()
defer lock.Unlock()
o.llock.Lock()
defer o.llock.Unlock()

data, err := l.Load()
if err != nil {
Expand All @@ -75,8 +82,8 @@ func (o *Onion) AddLayer(l Layer) error {
// AddLazyLayer add a new lazy layer to the end of config layers. last layer is loaded after
// all other layer
func (o *Onion) AddLazyLayer(l LazyLayer) {
lock.Lock()
defer lock.Unlock()
o.llock.Lock()
defer o.llock.Unlock()

o.ll = append(
o.ll,
Expand Down Expand Up @@ -104,8 +111,9 @@ func (o *Onion) SetDelimiter(d string) {

// Get try to get the key from config layers
func (o *Onion) Get(key string) (interface{}, bool) {
lock.RLock()
defer lock.RUnlock()
o.llock.RLock()
defer o.llock.RUnlock()

key = strings.Trim(key, " ")
if len(key) == 0 {
return nil, false
Expand Down Expand Up @@ -419,6 +427,113 @@ func (o *Onion) GetStringSlice(key string) []string {
return nil
}

func (o *Onion) addRef(key string, ref interface{}) {
o.refLock.Lock()
defer o.refLock.Unlock()

o.references = append(o.references, variable{key: key, ref: ref})
}

// RegisterInt return an int variable and set the value when the config is loaded
func (o *Onion) RegisterInt(key string, def int) *int {
var v = def
o.addRef(key, &v)

return &v
}

// RegisterInt64 return an int64 variable and set the value when the config is loaded
func (o *Onion) RegisterInt64(key string, def int64) *int64 {
var v = def
o.addRef(key, &v)

return &v
}

// RegisterString return an string variable and set the value when the config is loaded
func (o *Onion) RegisterString(key string, def string) *string {
var v = def
o.addRef(key, &v)

return &v
}

// RegisterFloat64 return an float64 variable and set the value when the config is loaded
func (o *Onion) RegisterFloat64(key string, def float64) *float64 {
var v = def
o.addRef(key, &v)

return &v
}

// RegisterFloat32 return an float32 variable and set the value when the config is loaded
func (o *Onion) RegisterFloat32(key string, def float32) *float32 {
var v = def
o.addRef(key, &v)

return &v
}

// RegisterBool return an float32 variable and set the value when the config is loaded
func (o *Onion) RegisterBool(key string, def bool) *bool {
var v = def
o.addRef(key, &v)

return &v
}

// RegisterBool return an float32 variable and set the value when the config is loaded
func (o *Onion) RegisterDuration(key string, def time.Duration) *time.Duration {
var v = def
o.addRef(key, &v)

return &v
}

// Load function is the new behavior of onion after version 3. after calling this all variables
// registered with Registered* function are loaded.
func (o *Onion) Load() {
o.refLock.RLock()
defer o.refLock.RUnlock()

for i := range o.references {
switch t := o.references[i].ref.(type) {
case *int:
v := o.GetIntDefault(o.references[i].key, *t)
*t = v
case *int64:
v := o.GetInt64Default(o.references[i].key, *t)
*t = v
case *string:
v := o.GetStringDefault(o.references[i].key, *t)
*t = v
case *float64:
v := o.GetFloat64Default(o.references[i].key, *t)
*t = v
case *float32:
v := o.GetFloat32Default(o.references[i].key, *t)
*t = v
case *bool:
v := o.GetBoolDefault(o.references[i].key, *t)
*t = v
case *time.Duration:
v := o.GetDurationDefault(o.references[i].key, *t)
*t = v
default:
panic("why? :/")
}
}
}

// Reset clear all layers, but not registered variables
func (o *Onion) Reset() {
o.llock.Lock()
defer o.llock.Unlock()

// Delete al layers
o.ll = nil
}

// New return a new Onion
func New() *Onion {
return &Onion{
Expand Down
2 changes: 1 addition & 1 deletion tomlloader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

"github.com/BurntSushi/toml"

"gopkg.in/fzerorubigd/onion.v2"
"gopkg.in/fzerorubigd/onion.v3"
)

type tomlLoader struct {
Expand Down
2 changes: 1 addition & 1 deletion tomlloader/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"os"
"testing"

. "gopkg.in/fzerorubigd/onion.v2"
. "github.com/smartystreets/goconvey/convey"
. "gopkg.in/fzerorubigd/onion.v3"
)

func TestYamlLoader(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion yamlloader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

"gopkg.in/yaml.v2"

"gopkg.in/fzerorubigd/onion.v2"
"gopkg.in/fzerorubigd/onion.v3"
)

type yamlLoader struct {
Expand Down
2 changes: 1 addition & 1 deletion yamlloader/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"testing"

. "github.com/smartystreets/goconvey/convey"
. "gopkg.in/fzerorubigd/onion.v2"
. "gopkg.in/fzerorubigd/onion.v3"
)

func TestYamlLoader(t *testing.T) {
Expand Down

0 comments on commit 13a2dee

Please sign in to comment.