Skip to content
Permalink
Browse files

Rework on configuration file

  • Loading branch information...
Depado committed Nov 12, 2017
1 parent bd47f47 commit f9e2b1ceac57ac4b4d69a059c1bb3f728c34b572
Showing with 251 additions and 0 deletions.
  1. +64 −0 conf/conf.go
  2. +29 −0 conf/conf_test.go
  3. +42 −0 conf/logger.go
  4. +81 −0 conf/logger_test.go
  5. +8 −0 conf/server.go
  6. +27 −0 conf/service.go
@@ -0,0 +1,64 @@
package conf

import (
"io/ioutil"
"time"

"github.com/Depado/conftags"
"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"
)

// C is the main exported conf
var C Conf

// Conf is a configuration struct intended to be filled from a yaml file and/or
// sane defaults
type Conf struct {
Server Server `yaml:"server"`
Logger Logger `yaml:"logger"`
GithubOAuthToken string `yaml:"github_oauth_token"`
rServiceInterval string `yaml:"service_interval" default:"10m"`
rRepoInterval string `yaml:"repo_interval" default:"10m"`

ServiceInterval time.Duration
RepoInterval time.Duration
Services []Service `yaml:"services"`
}

// Parse parses the tags and configures the logger associated
func (c *Conf) Parse() error {
var err error

if err = conftags.Parse(&c.Server); err != nil {
return err
}
if err = conftags.Parse(c); err != nil {
return err
}
c.Logger.Configure()

if c.ServiceInterval, err = time.ParseDuration(c.rServiceInterval); err != nil {
return errors.Wrapf(err, "configuration error : couldn't parse 'service_interval' (%s)", c.rServiceInterval)
}
if c.RepoInterval, err = time.ParseDuration(c.rRepoInterval); err != nil {
return errors.Wrapf(err, "configuration error: couldn't parse 'repo_interval' (%s)", c.rRepoInterval)
}

return nil
}

// Load loads the configuration file into C
func Load(fp string) error {
var err error
var c []byte

if c, err = ioutil.ReadFile(fp); err != nil {
return err
}
if err = yaml.Unmarshal(c, &C); err != nil {
return err
}

return C.Parse()
}
@@ -0,0 +1,29 @@
package conf

import "testing"

func TestConf_Parse(t *testing.T) {
type fields struct {
Server Server
Logger Logger
}
tests := []struct {
name string
fields fields
wantErr bool
}{
{"should not error", fields{Server: Server{Debug: true}}, false},
{"should not error", fields{}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &Conf{
Server: tt.fields.Server,
Logger: tt.fields.Logger,
}
if err := c.Parse(); (err != nil) != tt.wantErr {
t.Errorf("Conf.Parse() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
@@ -0,0 +1,42 @@
package conf

import (
"github.com/sirupsen/logrus"
)

// Logger is a configuration struct to define logger's behaviour
type Logger struct {
Level string `yaml:"level" default:"info"`
Format string `yaml:"format" default:"text"`
}

// Configure takes the configuration for the logger and translats it to
// logrus's usage
func (c Logger) Configure() {
SetFormatter(c.Format)
SetLogLevel(c.Level)
}

// SetLogLevel sets the logging level when possible, otherwise it fallbacks to
// the default logrus level and logs a warning
func SetLogLevel(lvl string) {
l, err := logrus.ParseLevel(lvl)
if err != nil {
logrus.WithField("provided", lvl).Warn("Invalid log level, fallback to Info level")
logrus.SetLevel(logrus.InfoLevel)
} else {
logrus.SetLevel(l)
}
}

// SetFormatter defines the way logs are formatted
func SetFormatter(format string) {
switch format {
case "json":
logrus.SetFormatter(&logrus.JSONFormatter{})
case "text":
logrus.SetFormatter(&logrus.TextFormatter{})
default:
logrus.SetFormatter(&logrus.TextFormatter{})
}
}
@@ -0,0 +1,81 @@
package conf

import (
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
)

func TestSetLogLevel(t *testing.T) {
type args struct {
lvl string
}
tests := []struct {
name string
lvl string
expected logrus.Level
}{
{"must set to debug", "debug", logrus.DebugLevel},
{"must set to info", "info", logrus.InfoLevel},
{"must set to warning", "warn", logrus.WarnLevel},
{"must set to error", "error", logrus.ErrorLevel},
{"must not fail and fallback", "random", logrus.InfoLevel},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
SetLogLevel(tt.lvl)
assert.Equal(t, logrus.GetLevel(), tt.expected)
})
}
}

func TestSetFormatter(t *testing.T) {
type args struct {
format string
}
tests := []struct {
name string
args args
want logrus.Formatter
}{
{"text format", args{"text"}, &logrus.TextFormatter{}},
{"json format", args{"json"}, &logrus.JSONFormatter{}},
{"invalid format", args{"invalid"}, &logrus.TextFormatter{}},
{"empty arg", args{""}, &logrus.TextFormatter{}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
SetFormatter(tt.args.format)
assert.Equal(t, tt.want, logrus.StandardLogger().Formatter)
})
}
}

func TestLogger_Configure(t *testing.T) {
type fields struct {
Level string
Format string
}
type want struct {
Formatter logrus.Formatter
Level logrus.Level
}
tests := []struct {
name string
fields fields
want want
}{
{"empty", fields{}, want{&logrus.TextFormatter{}, logrus.InfoLevel}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := Logger{
Level: tt.fields.Level,
Format: tt.fields.Format,
}
c.Configure()
assert.Equal(t, tt.want.Level, logrus.GetLevel())
})
}
}
@@ -0,0 +1,8 @@
package conf

// Server is the structure that holds the server configuration
type Server struct {
Host string `yaml:"host" default:"127.0.0.1"`
Port int `yaml:"port" default:"8080"`
Debug bool `yaml:"debug"`
}
@@ -0,0 +1,27 @@
package conf

// Repo is a configuration struct to access a repo
type Repo struct {
Type string `yaml:"type"`
Host string `yaml:"host"`
Token string `yaml:"token"`
Path string `yaml:"path"`
}

// CI is a configuration struct to access a CI
type CI struct {
Type string `yaml:"type"`
Host string `yaml:"host"`
}

// Service is a configuration struct describing a service
type Service struct {
Name string `yaml:"name"`
Host string `yaml:"host"`
URL string `yaml:"url"`
Icon string `yaml:"icon"`
Own bool `yaml:"own"`

CI *CI `yaml:"ci"`
Repo *Repo `yaml:"repo"`
}

0 comments on commit f9e2b1c

Please sign in to comment.
You can’t perform that action at this time.