Skip to content
Open
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
6025dd8
Merge branch 'release/0.0.1'
chazuka Feb 19, 2019
d0d3ad9
Merge pull request #1 from ndv6/develop
chazuka May 3, 2019
bb3e7eb
Merge pull request #3 from ndv6/develop
dididwinovianto Aug 7, 2019
8d93e73
add slice string
edwinlab Apr 17, 2020
4458f53
Merge pull request #4 from ndv6/feature/slice-string
burungbangkai Apr 17, 2020
c5b61ce
Implement feature reconnecting to remote config
purwandi Sep 22, 2020
6385960
Swap to use exponential backoff
purwandi Sep 23, 2020
cfbfa35
Merge pull request #6 from ndv6/feat/reconnect-remote
burungbangkai Sep 24, 2020
b3213da
add const for token consul
Lazycious Dec 15, 2022
18c1715
Merge pull request #8 from ndv6/feature/implement-migration
Lazycious Dec 15, 2022
6a27e27
change method remote secure
Lazycious Dec 27, 2022
88e5a81
Merge pull request #9 from ndv6/feature/implement-migration
Lazycious Dec 27, 2022
5dcbe3d
add new config for goconf with token
Lazycious Dec 28, 2022
cb3c7a0
Merge pull request #10 from ndv6/feature/implement-migration
Lazycious Dec 28, 2022
e6254af
add parameter token to switch
Lazycious Dec 28, 2022
91b3126
Merge pull request #11 from ndv6/feature/implement-migration
Lazycious Dec 28, 2022
674b988
change variabel name
Lazycious Dec 29, 2022
e2fc0fa
Merge pull request #12 from ndv6/feature/implement-migration
Lazycious Dec 29, 2022
d4b9c1a
handle new variabel name addr
Lazycious Dec 29, 2022
409327b
Merge pull request #13 from ndv6/feature/implement-migration
Lazycious Dec 29, 2022
f96c294
add path file config
Lazycious Dec 30, 2022
ba66275
Merge pull request #14 from ndv6/feature/implement-migration
Lazycious Dec 30, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 82 additions & 18 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package goconf

import (
"fmt"
"bytes"
"io/ioutil"
"log"
"os"
"time"

"github.com/cenkalti/backoff/v4"
capi "github.com/hashicorp/consul/api"
"github.com/joho/godotenv"
"github.com/pkg/errors"
"github.com/spf13/viper"
_ "github.com/spf13/viper/remote"
"log"
)

type Source string
Expand All @@ -23,6 +27,11 @@ const (
EnvTypeKey = "GOCONF_TYPE"
EnvFileNameKey = "GOCONF_FILENAME"
EnvPrefixKey = "GOCONF_ENV_PREFIX"
EnvPath = "GOCONF_PATH"

EnvHttpAddr = "CONSUL_HTTP_ADDR"
EnvHttpToken = "CONSUL_HTTP_TOKEN"
EnvHttpTokenFile = "CONSUL_HTTP_TOKEN_FILE"

//configuration sources
SourceEnv Source = "env"
Expand All @@ -31,11 +40,12 @@ const (
)

var (
typ = DefaultType
fname = DefaultFilename
prefix string
typ = DefaultType
fname = DefaultFilename
prefix, token, addr, path string

c *viper.Viper
pair *capi.KVPair
dirs = []string{
".",
"$HOME",
Expand All @@ -60,12 +70,32 @@ func Configure() {
if v := os.Getenv(EnvTypeKey); len(v) > 0 {
typ = v
}
if v := os.Getenv(EnvPath); len(v) > 0 {
path = v
}
if v := os.Getenv(EnvFileNameKey); len(v) > 0 {
fname = v
fname = path + v
}
if v := os.Getenv(EnvPrefixKey); len(v) > 0 {
prefix = v
}
if v := os.Getenv(EnvPrefixKey); len(v) > 0 {
prefix = v
}
if v := os.Getenv(EnvHttpToken); len(v) > 0 {
token = v
} else if v := os.Getenv(EnvHttpTokenFile); len(v) > 0 {
fileContent, err := ioutil.ReadFile(v)
if err != nil {
log.Fatal(err)
}
token = string(fileContent)
}
if v := os.Getenv(EnvConsulHostKey); len(v) > 0 {
addr = v
} else if v := os.Getenv(EnvHttpAddr); len(v) > 0 {
addr = v
}

// setup and configure viper instance
c = viper.New()
Expand All @@ -74,28 +104,58 @@ func Configure() {
if len(prefix) > 0 {
c.SetEnvPrefix(prefix)
}

c.AutomaticEnv()

// next we load from consul; only if consul host defined
if ch := os.Getenv(EnvConsulHostKey); ch != "" {
if err := c.AddRemoteProvider("consul", ch, fmt.Sprintf("/%s", fname)); err != nil {
errConsul = errors.Cause(err)
if addr != "" {
if token == "" {
if err := c.AddRemoteProvider("consul", addr, fname); err != nil {
errConsul = errors.Cause(err)
}
} else {
if err := c.ReadRemoteConfig(); err != nil {
client, err := capi.NewClient(&capi.Config{
Address: addr,
Token: token,
})
if err != nil {
errConsul = errors.Cause(err)
}

// Lookup the pair
pair, _, err = client.KV().Get(fname, nil)
if err != nil {
errConsul = errors.Cause(err)
}
}

connect := func() error {
if token != "" {
return c.ReadConfig(bytes.NewBuffer(pair.Value))
} else {
return c.ReadRemoteConfig()
}
}
notify := func(err error, t time.Duration) { log.Println("[goconf]", err.Error(), t) }
b := backoff.NewExponentialBackOff()
b.MaxElapsedTime = 2 * time.Minute

err := backoff.RetryNotify(connect, b, notify)
if err != nil {
log.Printf("[goconf] giving up connecting to remote config ")
errConsul = errors.Cause(err)
}

// last, we attempt to load from file in configured dir
for _, d := range dirs {
c.AddConfigPath(d)
}
if err := c.ReadInConfig(); err != nil {
errFile = errors.Cause(err)
}
} else {
errConsul = errors.New("failed loading remote source; ENV not defined")
}

// last, we attempt to load from file in configured dir
for _, d := range dirs {
c.AddConfigPath(d)
}
if err := c.ReadInConfig(); err != nil {
errFile = errors.Cause(err)
}
}

func MustSource(s ...Source) {
Expand Down Expand Up @@ -151,3 +211,7 @@ func GetInt(k string) int {
func GetFloat64(k string) float64 {
return c.GetFloat64(k)
}

func GetStringSlice(k string) []string {
return c.GetStringSlice(k)
}