Skip to content

Commit

Permalink
🐛 Fix config environment loading
Browse files Browse the repository at this point in the history
  • Loading branch information
0x46616c6b committed Oct 28, 2023
1 parent 6b06a9e commit 9938f12
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 46 deletions.
4 changes: 2 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ var (

func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&configPath, "config", "config.yml", "path to config.yml")
rootCmd.PersistentFlags().StringVar(&configPath, "config", "", "path to config.yml")
}

func initConfig() {
Expand All @@ -48,7 +48,7 @@ func initConfig() {
log = logger.NewLogrus(cfg.LogLevel, cfg.LogFormat)

var err error
db, err = storage.OpenGormDB(cfg.Database.Type, cfg.Database.DSN, log)
db, err = storage.OpenGormDB(cfg.DatabaseType, cfg.DatabaseDSN, log)
if err != nil {
log.WithError(err).Fatal("could not connect to database")
}
Expand Down
35 changes: 19 additions & 16 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,42 @@ import (

tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/sethvargo/go-password/password"
log "github.com/sirupsen/logrus"
"github.com/sirupsen/logrus"
"github.com/spf13/afero"
"github.com/spf13/viper"
)

var log = logrus.WithField("package", "config")

type Config struct {
Listen string `mapstructure:"listen"`
LogLevel string `mapstructure:"log_level"`
LogFormat string `mapstructure:"log_format"`
Secret string `mapstructure:"secret"`
Database Database `mapstructure:"database"`
TelegramBotToken string `mapstructure:"telegram_bot_token"`
Listen string `mapstructure:"listen"`
LogLevel string `mapstructure:"log_level"`
LogFormat string `mapstructure:"log_format"`
Secret string `mapstructure:"secret"`
DatabaseType string `mapstructure:"database_type"`
DatabaseDSN string `mapstructure:"database_dsn"`
TelegramBotToken string `mapstructure:"telegram_bot_token"`
TelegramBotUser tgbotapi.User
MetricsListen string `mapstructure:"metrics_listen"`
UploadPath string `mapstructure:"upload_path"`
UploadURL string `mapstructure:"upload_url"`
FileBackend afero.Fs
}

type Database struct {
Type string `mapstructure:"type"`
DSN string `mapstructure:"dsn"`
}

// NewConfig returns config with default values.
func NewConfig() Config {
secret, _ := password.Generate(64, 12, 12, false, false)
secret, err := password.Generate(64, 12, 12, false, true)
if err != nil {
log.WithError(err).Error("Unable to generate secret")
}

Check warning on line 36 in internal/config/config.go

View check run for this annotation

Codecov / codecov/patch

internal/config/config.go#L35-L36

Added lines #L35 - L36 were not covered by tests

return Config{
Listen: ":8080",
LogLevel: "debug",
LogFormat: "json",
Secret: secret,
Database: Database{Type: "sqlite", DSN: "ticker.db"},
DatabaseType: "sqlite",
DatabaseDSN: "ticker.db",
MetricsListen: ":8181",
UploadPath: "uploads",
UploadURL: "http://localhost:8080",
Expand All @@ -62,7 +64,8 @@ func LoadConfig(path string) Config {
viper.SetDefault("log_level", c.LogLevel)
viper.SetDefault("log_format", c.LogFormat)
viper.SetDefault("secret", c.Secret)
viper.SetDefault("database", c.Database)
viper.SetDefault("database_type", c.DatabaseType)
viper.SetDefault("database_dsn", c.DatabaseDSN)
viper.SetDefault("metrics_listen", c.MetricsListen)
viper.SetDefault("telegram_bot_token", "")
viper.SetDefault("upload_path", c.UploadPath)
Expand Down Expand Up @@ -94,7 +97,7 @@ func LoadConfig(path string) Config {

err := viper.Unmarshal(&c)
if err != nil {
log.WithError(err).Panic("Unable to decode config into struct")
log.WithError(err).Error("Unable to decode config into struct")

Check warning on line 100 in internal/config/config.go

View check run for this annotation

Codecov / codecov/patch

internal/config/config.go#L100

Added line #L100 was not covered by tests
}

return c
Expand Down
109 changes: 81 additions & 28 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,96 @@ import (
"os"
"testing"

"github.com/stretchr/testify/assert"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestLoadConfigWithoutPath(t *testing.T) {
err := os.Setenv("TICKER_LISTEN", ":7070")
if err != nil {
t.Fail()
}
func TestConfig(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Config Suite")
}

c := LoadConfig("")
assert.Equal(t, ":7070", c.Listen)
var _ = Describe("Config", func() {
log.Logger.SetOutput(GinkgoWriter)

err = os.Unsetenv("TICKER_LISTEN")
if err != nil {
t.Fail()
var envs map[string]string = map[string]string{
"TICKER_LISTEN": ":7070",
"TICKER_LOG_LEVEL": "trace",
"TICKER_LOG_FORMAT": "text",
"TICKER_SECRET": "secret",
"TICKER_DATABASE_TYPE": "mysql",
"TICKER_DATABASE_DSN": "user:password@tcp(localhost:3306)/ticker?charset=utf8mb4&parseTime=True&loc=Local",
"TICKER_METRICS_LISTEN": ":9191",
"TICKER_UPLOAD_PATH": "/data/uploads",
"TICKER_UPLOAD_URL": "https://example.com",
"TICKER_TELEGRAM_BOT_TOKEN": "token",
}
}

func TestLoadConfigWithPath(t *testing.T) {
c := LoadConfig("../../config.yml")
assert.Equal(t, ":8080", c.Listen)
Describe("LoadConfig", func() {
BeforeEach(func() {
for key := range envs {
os.Unsetenv(key)
}
})

c = LoadConfig("config.yml")
assert.Equal(t, ":8080", c.Listen)
}
Context("when path is empty", func() {
It("loads config with default values", func() {
c := LoadConfig("")
Expect(c.Listen).To(Equal(":8080"))
Expect(c.LogLevel).To(Equal("debug"))
Expect(c.LogFormat).To(Equal("json"))
Expect(c.Secret).ToNot(BeEmpty())
Expect(c.DatabaseType).To(Equal("sqlite"))
Expect(c.DatabaseDSN).To(Equal("ticker.db"))
Expect(c.MetricsListen).To(Equal(":8181"))
Expect(c.UploadPath).To(Equal("uploads"))
Expect(c.UploadURL).To(Equal("http://localhost:8080"))
Expect(c.TelegramBotToken).To(BeEmpty())
Expect(c.TelegramEnabled()).To(BeFalse())
})

func TestLoadConfigWithFallback(t *testing.T) {
c := LoadConfig("/x/y/z")
assert.Equal(t, ":8080", c.Listen)
}
It("loads config from env", func() {
for key, value := range envs {
err := os.Setenv(key, value)
Expect(err).ToNot(HaveOccurred())
}

func TestConfig_TelegramEnabled(t *testing.T) {
c := NewConfig()
c := LoadConfig("")
Expect(c.Listen).To(Equal(envs["TICKER_LISTEN"]))
Expect(c.LogLevel).To(Equal(envs["TICKER_LOG_LEVEL"]))
Expect(c.LogFormat).To(Equal(envs["TICKER_LOG_FORMAT"]))
Expect(c.Secret).To(Equal(envs["TICKER_SECRET"]))
Expect(c.DatabaseType).To(Equal(envs["TICKER_DATABASE_TYPE"]))
Expect(c.DatabaseDSN).To(Equal(envs["TICKER_DATABASE_DSN"]))
Expect(c.MetricsListen).To(Equal(envs["TICKER_METRICS_LISTEN"]))
Expect(c.UploadPath).To(Equal(envs["TICKER_UPLOAD_PATH"]))
Expect(c.UploadURL).To(Equal(envs["TICKER_UPLOAD_URL"]))
Expect(c.TelegramBotToken).To(Equal(envs["TICKER_TELEGRAM_BOT_TOKEN"]))
Expect(c.TelegramEnabled()).To(BeTrue())
})
})

assert.False(t, c.TelegramEnabled())
Context("when path is not empty", func() {
Context("when path is absolute", func() {
It("loads config from file", func() {
c := LoadConfig("../../config.yml")
Expect(c.Listen).To(Equal(":8080"))
})
})

c.TelegramBotToken = "a"
Context("when path is relative", func() {
It("loads config from file", func() {
c := LoadConfig("config.yml")
Expect(c.Listen).To(Equal(":8080"))
})
})
})

assert.True(t, c.TelegramEnabled())
}
Context("when path is invalid", func() {
It("loads config with default values", func() {
c := LoadConfig("/x/y/z")
Expect(c.Listen).To(Equal(":8080"))
})
})
})
})
1 change: 1 addition & 0 deletions internal/storage/sql_storage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func TestSqlStorage(t *testing.T) {
}

var _ = Describe("SqlStorage", func() {
log.Logger.SetOutput(GinkgoWriter)
db, err := gorm.Open(sqlite.Open("file:testdatabase?mode=memory&cache=shared"), &gorm.Config{})
Expect(err).ToNot(HaveOccurred())

Expand Down

0 comments on commit 9938f12

Please sign in to comment.