-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
139 lines (122 loc) · 4.06 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
128
129
130
131
132
133
134
135
136
137
138
139
package config
import (
"fmt"
"log/slog"
"github.com/fsnotify/fsnotify"
"github.com/jasonsites/gosk/internal/app"
"github.com/spf13/viper"
)
// Configuration defines application configuration
type Configuration struct {
External External `validate:"required"`
HTTP HTTP `validate:"required"`
Logger Logger `validate:"required"`
Metadata Metadata `validate:"required"`
Postgres Postgres `validate:"required"`
}
// External defines external service configuration
type External struct {
Example struct {
Host string
Timeout uint
}
}
// HTTP defines HTTP Server configuration
type HTTP struct {
Router struct {
Namespace string `validate:"required"`
Paging struct {
DefaultLimit uint `validate:"required"`
}
Sorting struct {
DefaultAttr string `validate:"required"`
DefaultOrder string `validate:"required"`
} `validate:"required"`
} `validate:"required"`
Server struct {
Host string
Port uint `validate:"required,max=65535"`
} `validate:"required"`
}
// Logger defines the primary logger configuration
type Logger struct {
Enabled bool
Level string `validate:"oneof=debug info warn error"`
Verbose bool
}
// Metadata defines application metadata
type Metadata struct {
Environment string `validate:"oneof=development production"`
Name string
Version string
}
// Postgres defines the postgres connection parameters
type Postgres struct {
Database string `validate:"required"`
Host string `validate:"required"`
Password string `validate:"required"`
Port uint `validate:"required,max=65535"`
User string `validate:"required"`
}
// LoadConfiguration loads config parameters on startup
func LoadConfiguration() (*Configuration, error) {
var conf Configuration
viper.SetConfigName("config")
viper.AddConfigPath("/app/config")
viper.AllowEmptyEnv(true)
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("config file changed:", e.Name)
})
viper.WatchConfig()
// default values
viper.SetDefault("external.example.baseURL", "http://www.example.com")
viper.SetDefault("external.example.timeout", 25000)
viper.SetDefault("http.router.namespace", "domain")
viper.SetDefault("http.router.paging.defaultLimit", 20)
viper.SetDefault("http.router.sorting.defaultAttr", "created_on")
viper.SetDefault("http.router.sorting.defaultOrder", "desc")
viper.SetDefault("http.server.host", "localhost")
viper.SetDefault("http.server.port", 9202)
viper.SetDefault("logger.enabled", true)
viper.SetDefault("logger.level", "info")
viper.SetDefault("logger.verbose", false)
viper.SetDefault("metadata.environment", "production")
viper.SetDefault("postgres.database", "svcdb")
viper.SetDefault("postgres.host", "postgres")
viper.SetDefault("postgres.password", "postgres")
viper.SetDefault("postgres.port", 5432)
viper.SetDefault("postgres.user", "postgres")
// environment variables
viper.BindEnv("http.server.host", "HTTP_SERVER_HOST")
viper.BindEnv("http.server.port", "HTTP_SERVER_PORT")
viper.BindEnv("logger.enabled", "LOG_ENABLED")
viper.BindEnv("logger.level", "LOG_LEVEL")
viper.BindEnv("logger.verbose", "LOG_VERBOSE")
viper.BindEnv("metadata.environment", "APP_ENV")
viper.BindEnv("metadata.version", "APP_VERSION")
viper.BindEnv("postgres.database", "POSTGRES_DB")
viper.BindEnv("postgres.host", "POSTGRES_HOST")
viper.BindEnv("postgres.password", "POSTGRES_PASSWORD")
viper.BindEnv("postgres.port", "POSTGRES_PORT")
viper.BindEnv("postgres.user", "POSTGRES_USER")
// read, unmarshal, and validate configuration
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
slog.Info("config file bypassed")
} else {
err := fmt.Errorf("configuration read error: %w", err)
slog.Error(err.Error())
return &conf, err
}
}
if err := viper.Unmarshal(&conf); err != nil {
err := fmt.Errorf("configuration unmarshal error: %w", err)
slog.Error(err.Error())
return &conf, err
}
if err := app.Validator.Validate.Struct(&conf); err != nil {
return &conf, fmt.Errorf("invalid configuration: %v", err)
}
// fmt.Printf("%+v\n", conf)
return &conf, nil
}