From ae87e25e165eca3b5766e281c42062db4be268c1 Mon Sep 17 00:00:00 2001 From: Tomasz Janiszewski Date: Wed, 9 Dec 2015 15:16:50 +0100 Subject: [PATCH] Read config from file --- config/config.go | 37 +++++++++++++++++++-------- config/config.json | 15 +++++++++++ config/config_test.go | 58 +++++++++++++++++++++++++++++++++++++++++++ consul/config.go | 1 - main.go | 14 ++++++++--- 5 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 config/config.json create mode 100644 config/config_test.go diff --git a/config/config.go b/config/config.go index c26893c..11448d3 100644 --- a/config/config.go +++ b/config/config.go @@ -1,12 +1,14 @@ package config import ( + "encoding/json" log "github.com/Sirupsen/logrus" "github.com/allegro/marathon-consul/consul" "github.com/allegro/marathon-consul/marathon" "github.com/allegro/marathon-consul/metrics" "github.com/allegro/marathon-consul/sync" flag "github.com/ogier/pflag" + "io/ioutil" "time" ) @@ -15,25 +17,28 @@ type Config struct { Web struct { Listen string } - Sync sync.Config - Marathon marathon.Config - Metrics metrics.Config - LogLevel string + Sync sync.Config + Marathon marathon.Config + Metrics metrics.Config + LogLevel string + configFile string } -func New() (config *Config) { - config = &Config{ - Marathon: marathon.Config{}, +var config = &Config{Marathon: marathon.Config{}} + +func New() (*Config, error) { + if !flag.Parsed() { + config.parseFlags() } - config.parseFlags() + flag.Parse() + err := config.loadConfigFromFile() config.setLogLevel() - return config + return config, err } func (config *Config) parseFlags() { // Consul - flag.BoolVar(&config.Consul.Enabled, "consul", true, "Use Consul backend") flag.StringVar(&config.Consul.Port, "consul-port", "8500", "Consul port") flag.BoolVar(&config.Consul.Auth.Enabled, "consul-auth", false, "Use Consul with authentication") flag.StringVar(&config.Consul.Auth.Username, "consul-auth-username", "", "The basic authentication username") @@ -65,8 +70,18 @@ func (config *Config) parseFlags() { // General flag.StringVar(&config.LogLevel, "log-level", "info", "Log level: panic, fatal, error, warn, info, or debug") + flag.StringVar(&config.configFile, "config-file", "", "Path to a JSON file to read configuration from. Note: Will override options set earlier on the command line") +} - flag.Parse() +func (config *Config) loadConfigFromFile() error { + if config.configFile == "" { + return nil + } + jsonBlob, err := ioutil.ReadFile(config.configFile) + if err != nil { + return err + } + return json.Unmarshal(jsonBlob, config) } func (config *Config) setLogLevel() { diff --git a/config/config.json b/config/config.json new file mode 100644 index 0000000..0128f72 --- /dev/null +++ b/config/config.json @@ -0,0 +1,15 @@ +{ + "Sync":{ + "Interval":91 + }, + "Marathon":{ + "Location":"marathon.host:8080", + "Protocol":"https", + "Username":"user", + "Password":"pass", + "VerifySsl":false + }, + "Metrics":{ + "Interval":31 + } +} \ No newline at end of file diff --git a/config/config_test.go b/config/config_test.go new file mode 100644 index 0000000..02dfe6c --- /dev/null +++ b/config/config_test.go @@ -0,0 +1,58 @@ +package config + +import ( + "github.com/allegro/marathon-consul/consul" + "github.com/allegro/marathon-consul/marathon" + "github.com/allegro/marathon-consul/metrics" + "github.com/allegro/marathon-consul/sync" + "github.com/stretchr/testify/assert" + "os" + "testing" +) + +func TestConfig_NewReturnsErrorWhenFileNotExist(t *testing.T) { + os.Args = []string{"./marathon-consul", "--config-file=unknown.json"} + _, err := New() + assert.Error(t, err) +} + +func TestConfig_NewReturnsErrorWhenFileIsNotJson(t *testing.T) { + os.Args = []string{"./marathon-consul", "--config-file=config.go"} + _, err := New() + assert.Error(t, err) +} + +func TestConfig_ShouldBeMergedWithFileDefaultsAndFlags(t *testing.T) { + + expected := &Config{ + Consul: consul.ConsulConfig{ + Auth: consul.Auth{Enabled: false, + Username: "", + Password: ""}, + Port: "8500", + SslEnabled: false, + SslVerify: true, + SslCert: "", + SslCaCert: "", + Token: ""}, + Web: struct{ Listen string }{Listen: ":4000"}, + Sync: sync.Config{Interval: 91}, + Marathon: marathon.Config{Location: "marathon.host:8080", + Protocol: "https", + Username: "user", + Password: "pass", + VerifySsl: false}, + Metrics: metrics.Config{Target: "stdout", + Prefix: "default", + Interval: 31, + Addr: ""}, + LogLevel: "debug", + configFile: "config.json", + } + + os.Args = []string{"./marathon-consul", "--log-level=debug", "--config-file=config.json", "--marathon-location=localhost:8080"} + actual, err := New() + + assert.NoError(t, err) + assert.Equal(t, expected, actual) +} diff --git a/consul/config.go b/consul/config.go index d6883d9..81f6ccb 100644 --- a/consul/config.go +++ b/consul/config.go @@ -1,7 +1,6 @@ package consul type ConsulConfig struct { - Enabled bool Auth Auth Port string SslEnabled bool diff --git a/main.go b/main.go index ad9c74f..4eb8731 100644 --- a/main.go +++ b/main.go @@ -11,20 +11,26 @@ import ( ) const Name = "marathon-consul" -const Version = "0.2.0" +const Version = "0.2.1" func main() { - config := config.New() + config, err := config.New() + if err != nil { + log.Fatal(err.Error()) + } - err := metrics.Init(config.Metrics) + err = metrics.Init(config.Metrics) + if err != nil { + log.Fatal(err.Error()) + } service := service.New(config.Consul) remote, err := marathon.New(config.Marathon) - if err != nil { log.Fatal(err.Error()) } + sync := sync.New(remote, service) go sync.StartSyncServicesJob(config.Sync.Interval)