Skip to content

Commit 3d76a26

Browse files
committed
Load config from config file or environment
1 parent 614edad commit 3d76a26

File tree

5 files changed

+102
-53
lines changed

5 files changed

+102
-53
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ A Cloud Infrastructure Management Tool to stop, resume, clean and destroy resour
88

99
### TODO
1010
- [x] Bootstrap application architecture
11-
- [x] get resources with specified tags for destruction
12-
- [ ] Schedule resource refreshing
11+
- [x] Schedule resource refreshing
1312
- [ ] Create Web Dashboard
13+
- [ ] generate Sample Yaml config and load config
1414
- [ ] Allow users to specify tags/resources to track from reka UI with reaping Details
1515
- [ ] Support Manual Trigger of resources reaping from Dashboard/CLI
1616
- [ ] Allow authentication username and password set in config file

config/config.example.yaml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Config variables for the Reka application. These variables can also be set from environment with
2+
# the reka namespace
3+
# Example:
4+
# name => REKA_NAME
5+
# refreshInterval => REKA_REFRESHINTERVAL
6+
# auth.username => REKA_AUTH_USERNAME
7+
8+
name: reka
9+
# Providers to be enabled for reka
10+
providers:
11+
- aws
12+
# logPath: logs/
13+
refreshInterval: 1
14+
# auth:
15+
# username: blank # Can
16+
# password: blank
17+
database:
18+
type: sqlite

config/config.go

+74-51
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package config
22

33
import (
44
"fmt"
5-
"log"
65
"os"
76
"path"
7+
"path/filepath"
8+
"strings"
89

910
"github.com/aws/aws-sdk-go-v2/aws"
11+
log "github.com/sirupsen/logrus"
1012
"github.com/spf13/viper"
1113
)
1214

@@ -20,25 +22,27 @@ const (
2022
appName = "REKA"
2123
)
2224

23-
// AWSConfig Related Configurations
24-
type AWSConfig struct {
25+
// AwsConfig Related Configurations
26+
type AwsConfig struct {
2527
// AWS Configs
26-
Config aws.Config
27-
DefaultRegion string
28+
Config aws.Config
29+
AccessKey string `yaml:"accessKey"`
30+
SecretAccessKey string `yaml:"secretAccessKey"`
31+
DefaultRegion string `yaml:"defaultRegion"`
2832
}
2933

3034
// DatabaseConfig Config for Dabatabase
3135
type DatabaseConfig struct {
32-
Host string
33-
Name string //database name
34-
User string
35-
Password string
36-
Type string
36+
Type string `yaml:"type"`
37+
Name string `yaml:"name"`
38+
Host string `yaml:"host"`
39+
User string `yaml:"user"`
40+
Password string `yaml:"password"`
3741
}
3842

3943
// GetConnectionString the connection string for database
4044
func (db *DatabaseConfig) GetConnectionString() string {
41-
return fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable", config.db.Host, config.db.User, config.db.Password, config.db.Name)
45+
return fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable", db.Host, db.User, db.Password, db.Name)
4246
}
4347

4448
// SqliteDefaultPath the default database path to use for sqlite
@@ -48,21 +52,19 @@ func (db *DatabaseConfig) SqliteDefaultPath() string {
4852

4953
// Config : The Config values passed to application
5054
type Config struct {
51-
// A list of supported providers to be enabled
52-
Providers []string
53-
staticPath string
54-
55-
Aws *AWSConfig
56-
db *DatabaseConfig
57-
58-
// Authentication details set from config
59-
Username string
60-
Password string
61-
62-
// RefreshInterval in hours
63-
RefreshInterval int32
64-
// LogPath
65-
LogPath string
55+
Name string `yaml:"name"`
56+
Providers []string `yaml:"providers"`
57+
Database *DatabaseConfig `yaml:"database"`
58+
Aws *AwsConfig `yaml:"aws"`
59+
RefreshInterval int32 `yaml:"refreshInterval"`
60+
LogPath string `yaml:"logPath"`
61+
62+
Auth struct {
63+
Username string `yaml:"username"`
64+
Password string `yaml:"password"`
65+
} `yaml:"auth"`
66+
67+
staticPath string // Path to Static File
6668
}
6769

6870
// LoadConfig load all passed configs and defaults
@@ -72,51 +74,72 @@ func LoadConfig() *Config {
7274
panic(err)
7375
}
7476

75-
viper.SetEnvPrefix(appName) // will be uppercased automatically
76-
viper.SetConfigName("reka") // name of config file (without extension)
77-
viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
78-
79-
// If REKA_CONFIG_FILE is set load config from that
80-
viper.AddConfigPath(viper.GetString("ConfigFile"))
81-
err = viper.ReadInConfig() // Find and read the config file
82-
if err != nil {
83-
// panic(fmt.Errorf("Fatal error config file: %s", err))
84-
fmt.Errorf("Fatal error config file: %s", err)
85-
}
86-
77+
viper.SetEnvPrefix(appName)
78+
viper.AutomaticEnv() // Load Variables from Environment with REKA prefix
79+
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
8780
// Defaults
8881
viper.SetDefault("StaticPath", "web/static")
89-
viper.SetDefault("DbType", "sqlite") // Default Database type is sqlite
82+
// viper.SetDefault("DbType", "sqlite") // Default Database type is sqlite
9083
viper.SetDefault("LogPath", path.Join(workingDir, "logs"))
9184
viper.SetDefault("RefreshInterval", 4) // interval between running refresh and checking for resources to updates
9285

93-
staticPath := viper.GetString("StaticPath")
86+
// Load Config file
87+
if configPath := viper.GetString("Config"); configPath != "" {
88+
dir, file := filepath.Split(configPath)
89+
viper.SetConfigName(file) // name of config file (without extension)
90+
viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
91+
// If REKA_CONFIG_FILE is set load config from that
92+
viper.AddConfigPath(dir)
93+
if err := viper.ReadInConfig(); err != nil {
94+
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
95+
// Config file not found; ignore error if desired
96+
log.Fatalf("error: %s. Consider passing the `--config` variable or settings %s_CONFIG environment", err, appName)
97+
98+
} else {
99+
// Config file was found but another error was produced
100+
log.Fatalf("Error: %s", err)
101+
}
102+
}
103+
}
94104

95105
config = &Config{}
96106

107+
staticPath := viper.GetString("StaticPath")
97108
if !path.IsAbs(staticPath) {
98109
config.staticPath = path.Join(workingDir, staticPath)
99110
}
100111

101-
// Load Configuration
102-
config.Providers = []string{"aws"} // TODO Remove Test providers init with aws
112+
config.Providers = viper.GetStringSlice("Providers")
113+
if len(config.Providers) < 1 {
114+
log.Fatal("No providers specified. Reka needs atleast one provider to track")
115+
}
116+
117+
config.Auth.Username = viper.GetString("Auth.Username")
118+
config.Auth.Password = viper.GetString("Auth.Password")
103119

104-
config.db = &DatabaseConfig{
105-
Type: viper.GetString("DBType"),
106-
Host: viper.GetString("DbHost"),
107-
Name: viper.GetString("DbName"),
108-
User: viper.GetString("DbUser"),
109-
Password: viper.GetString("DbPassword"),
120+
config.Database = &DatabaseConfig{
121+
Type: viper.GetString("Database.Type"),
122+
Host: viper.GetString("Database.Host"),
123+
Name: viper.GetString("Database.Name"),
124+
User: viper.GetString("Database.User"),
125+
Password: viper.GetString("Database.Password"),
110126
}
111-
config.Aws = &AWSConfig{}
127+
config.Aws = &AwsConfig{}
112128
config.RefreshInterval = viper.GetInt32("RefreshInterval")
129+
113130
config.LogPath = viper.GetString("LogPath")
131+
if !path.IsAbs(config.LogPath) {
132+
config.LogPath = path.Join(workingDir, staticPath)
133+
}
134+
// Create the Logs directory if it does not exists
114135
if _, err := os.Stat(config.LogPath); os.IsNotExist(err) {
115136
err = os.Mkdir(config.LogPath, os.ModePerm)
116137
if err != nil {
117138
log.Fatal("Could not create log path: ", err)
118139
}
119140
}
141+
142+
fmt.Println(config.Auth)
120143
return config
121144
}
122145

@@ -127,11 +150,11 @@ func GetConfig() *Config {
127150

128151
// GetDB Return database config
129152
func GetDB() *DatabaseConfig {
130-
return config.db
153+
return config.Database
131154
}
132155

133156
// GetAWS Return database config
134-
func GetAWS() *AWSConfig {
157+
func GetAWS() *AwsConfig {
135158
return config.Aws
136159
}
137160

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ require (
1111
github.com/labstack/gommon v0.3.0
1212
github.com/pelletier/go-toml v1.8.1 // indirect
1313
github.com/sirupsen/logrus v1.4.2
14+
github.com/spf13/pflag v1.0.3
1415
github.com/spf13/viper v1.7.0
1516
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff // indirect
1617
gopkg.in/yaml.v2 v2.3.0 // indirect

web/main.go

+7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"github.com/gin-gonic/gin"
2323
"github.com/go-co-op/gocron"
2424
log "github.com/sirupsen/logrus"
25+
"github.com/spf13/pflag"
26+
"github.com/spf13/viper"
2527

2628
"github.com/mensaah/reka/config"
2729
"github.com/mensaah/reka/provider/aws"
@@ -36,7 +38,12 @@ var (
3638
)
3739

3840
func main() {
41+
// Parse Command Line Arguments
42+
pflag.String("config", "", "Path to config file")
43+
pflag.Parse()
44+
viper.BindPFlags(pflag.CommandLine)
3945

46+
// Load Config and Defaults
4047
config.LoadConfig()
4148
models.SetDB(config.GetDB())
4249

0 commit comments

Comments
 (0)