-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
127 lines (98 loc) · 2.85 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package config
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"github.com/kenplix/url-shrtnr/pkg/log"
"github.com/kenplix/url-shrtnr/internal/service"
"github.com/kenplix/url-shrtnr/pkg/cache/redis"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
"github.com/spf13/viper"
"github.com/kenplix/url-shrtnr/internal/repository"
"github.com/kenplix/url-shrtnr/pkg/hash"
"github.com/kenplix/url-shrtnr/pkg/httpserver"
)
const EnvPrefix = "URL_SHRTNR"
type Environment string
const (
OmitEnvironment Environment = ""
TestingEnvironment Environment = "testing"
DevelopmentEnvironment Environment = "development"
ProductionEnvironment Environment = "production"
)
func (env Environment) Validate() error {
switch env {
case DevelopmentEnvironment:
case ProductionEnvironment:
case OmitEnvironment:
case TestingEnvironment:
default:
return fmt.Errorf("unknown environment %q", env)
}
return nil
}
func (env Environment) ConfigName() string {
if env == OmitEnvironment {
return string(DevelopmentEnvironment)
}
return string(env)
}
// Config -.
type Config struct {
Environment Environment `mapstructure:"environment"`
HTTP httpserver.Config `mapstructure:"http"`
Database repository.Config `mapstructure:"database"`
Logger log.Config `mapstructure:"logger"`
Redis redis.Config `mapstructure:"redis"`
Hasher hash.Config `mapstructure:"hasher"`
JWT service.JWTServiceConfig `mapstructure:"jwt"`
}
// Read -.
func Read(dir string) (Config, error) {
viper.AutomaticEnv()
viper.SetEnvPrefix(EnvPrefix)
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
var cfg Config
if err := load(&cfg); err != nil {
return Config{}, errors.Wrap(err, "failed to load config")
}
if err := read(dir); err != nil {
return Config{}, errors.Wrap(err, "failed to read config")
}
if err := viper.Unmarshal(&cfg); err != nil {
return Config{}, errors.Wrap(err, "failed to unmarshall config")
}
return cfg, nil
}
func load(cfg *Config) error {
keys := map[string]any{}
if err := mapstructure.Decode(cfg, &keys); err != nil {
return errors.Wrap(err, "failed to decode config keys")
}
buf, err := json.Marshal(keys)
if err != nil {
return errors.Wrap(err, "failed to marshall config keys")
}
viper.SetConfigType("json")
err = viper.ReadConfig(bytes.NewReader(buf))
if err != nil {
return errors.Wrap(err, "failed to read config")
}
return nil
}
func read(dir string) error {
viper.AddConfigPath(dir)
viper.SetConfigType("yaml")
env := Environment(viper.GetString("ENVIRONMENT"))
if err := env.Validate(); err != nil {
return err
}
viper.SetConfigName(env.ConfigName())
err := viper.MergeInConfig()
if err != nil {
return errors.Wrapf(err, "failed to merge with %q config file", viper.ConfigFileUsed())
}
return nil
}