-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initialize Configuration Management Using Viper #447
Open
window9u
wants to merge
26
commits into
main
Choose a base branch
from
init-config
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 19 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
b481a5b
Add config file
window9u bed0469
Add config.go files
window9u c0ab8aa
Add env map for viper parsing
window9u ed8bf2c
implement viper parsing
window9u 6ce643f
add empty test
window9u b035f49
fix time `1d` -> `24h`
window9u ef8c399
Replace `yaml` structure tag to `mapstructure`
window9u f0268a9
Remove logger in config
window9u eecb561
Fix error condition
window9u 8d8b24e
Fix port env var name
window9u 8f8a8ac
Remove default value for S3
window9u 80406f6
Implement `LoadConfig` test
window9u 36964b9
Refactor test code
window9u 232b463
fix path
window9u a918969
fix test comments
window9u 9b1220d
lint
window9u ec9d3e1
go mod tidy
window9u f50da7f
apply code rabbit's comments
window9u 0157de9
lint
window9u 3938a0b
fix test
window9u ed314ab
import validator
window9u db9c4d9
Refactor validator by library
window9u 186034e
refactor test
window9u 352280c
refactor auth config
window9u 9765f88
refactor GitHub config
window9u 2951bc8
remove `mapstructure`
window9u File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,60 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
|
||
"github.com/labstack/echo/v4" | ||
"github.com/labstack/gommon/log" | ||
|
||
"github.com/yorkie-team/codepair/backend/internal/config" | ||
"github.com/yorkie-team/codepair/backend/internal/server" | ||
) | ||
|
||
func main() { | ||
configPath, loglevel := parseFlag() | ||
|
||
e := echo.New() | ||
conf := config.LoadConfig() | ||
if err := setLogLevel(e, loglevel); err != nil { | ||
e.Logger.Fatal(err) | ||
} | ||
|
||
conf, err := config.LoadConfig(configPath) | ||
if err != nil { | ||
e.Logger.Fatal(err) | ||
} | ||
|
||
cp := server.New(e, conf) | ||
|
||
if err := cp.Start(); err != nil { | ||
e.Logger.Fatal(err) | ||
} | ||
} | ||
|
||
func parseFlag() (string, string) { | ||
var configPath string | ||
var loglevel string | ||
flag.StringVar(&configPath, "config", "", "Path to the configuration file") | ||
flag.StringVar(&loglevel, "loglevel", "error", "Log level") | ||
flag.Parse() | ||
|
||
return configPath, loglevel | ||
} | ||
|
||
func setLogLevel(e *echo.Echo, level string) error { | ||
switch level { | ||
case "debug": | ||
e.Logger.SetLevel(log.DEBUG) | ||
case "info": | ||
e.Logger.SetLevel(log.INFO) | ||
case "warn": | ||
e.Logger.SetLevel(log.WARN) | ||
case "error": | ||
e.Logger.SetLevel(log.ERROR) | ||
case "off": | ||
e.Logger.SetLevel(log.OFF) | ||
default: | ||
return fmt.Errorf("invalid log level %s", level) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
Server: | ||
Port: 3001 | ||
|
||
OAuth: | ||
Github: | ||
# WARNING: Replace these values with your GitHub OAuth credentials | ||
ClientID: "<GITHUB_CLIENT_ID>" | ||
ClientSecret: "<GITHUB_CLIENT_SECRET>" | ||
CallbackURL: "http://localhost:3000/auth/login/github" | ||
AuthorizationURL: "https://github.com/login/oauth/authorize" | ||
TokenURL: "https://github.com/login/oauth/access_token" | ||
UserProfileURL: "https://api.github.com/user" | ||
|
||
FrontendBaseURL: "http://localhost:5173" | ||
|
||
JWT: | ||
# WARNING: Use strong, unique secrets in production | ||
AccessTokenSecret: "<STRONG_RANDOM_SECRET>" | ||
AccessTokenExpirationTime: "24h" | ||
RefreshTokenSecret: "<STRONG_RANDOM_SECRET>" | ||
RefreshTokenExpirationTime: "168h" | ||
|
||
Yorkie: | ||
APIAddr: "http://localhost:8080" | ||
ProjectName: "default" | ||
ProjectSecretKey: "" | ||
|
||
Mongo: | ||
ConnectionTimeout: "10s" | ||
ConnectionURI: "mongodb://localhost:27017/codepair" | ||
PingTimeout: "5s" | ||
DatabaseName: "codepair" | ||
|
||
Storage: | ||
Provider: "minio" # or "s3" | ||
|
||
Minio: | ||
Bucket: "default-storage" | ||
Endpoint: "http://localhost:9000" | ||
AccessKey: "minioadmin" | ||
SecretKey: "minioadmin" | ||
|
||
S3: | ||
Bucket: "default-storage" | ||
Region: "us-east-1" | ||
AccessKey: "aws_access_key" | ||
SecretKey: "aws_secret_key" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,109 @@ | ||
package config | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/spf13/viper" | ||
) | ||
|
||
// Config holds the application configuration. | ||
type Config struct { | ||
Server *Server | ||
Server Server `mapstructure:"Server"` | ||
OAuth OAuth `mapstructure:"OAuth"` | ||
JWT JWT `mapstructure:"JWT"` | ||
Yorkie Yorkie `mapstructure:"Yorkie"` | ||
Mongo Mongo `mapstructure:"Mongo"` | ||
Storage Storage `mapstructure:"Storage"` | ||
} | ||
|
||
// LoadConfig loads configuration settings from a file (if provided) and from environment variables. | ||
// It returns the populated Config, a status message describing which sources were used, and an error if any. | ||
func LoadConfig(filePath string) (*Config, error) { | ||
if err := bindEnvironmentVariables(); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := readConfigFile(filePath); err != nil { | ||
return nil, err | ||
} | ||
|
||
cfg := &Config{} | ||
if err := viper.Unmarshal(cfg); err != nil { | ||
return nil, fmt.Errorf("unable to decode configuration into struct: %w", err) | ||
} | ||
|
||
cfg.ensureDefaultValue() | ||
|
||
if err := cfg.validate(); err != nil { | ||
return nil, fmt.Errorf("failed to validate config: %w", err) | ||
} | ||
|
||
return cfg, nil | ||
} | ||
|
||
func LoadConfig() *Config { | ||
return &Config{ | ||
Server: &Server{ | ||
Port: DefaultServerPort, | ||
}, | ||
// bindEnvironmentVariables binds each configuration key to its corresponding environment variable. | ||
func bindEnvironmentVariables() error { | ||
for key, env := range EnvVarMap { | ||
if err := viper.BindEnv(key, env); err != nil { | ||
return fmt.Errorf("failed to bind environment variable %s to key %s: %w", env, key, err) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func readConfigFile(filePath string) error { | ||
if filePath != "" { | ||
viper.SetConfigFile(filePath) | ||
} else { | ||
viper.SetConfigName("config") | ||
viper.SetConfigType("yaml") | ||
viper.AddConfigPath(".") | ||
} | ||
|
||
if err := viper.ReadInConfig(); err != nil { | ||
var nf viper.ConfigFileNotFoundError | ||
if errors.As(err, &nf) { | ||
if filePath != "" { | ||
return fmt.Errorf("file path given but not found: %w", err) | ||
} | ||
return nil | ||
} | ||
return fmt.Errorf("failed to read config file: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *Config) ensureDefaultValue() { | ||
c.Server.ensureDefaultValue() | ||
c.OAuth.ensureDefaultValue() | ||
c.JWT.ensureDefaultValue() | ||
c.Yorkie.ensureDefaultValue() | ||
c.Mongo.ensureDefaultValue() | ||
c.Storage.ensureDefaultValue() | ||
} | ||
|
||
func (c *Config) validate() error { | ||
if err := c.Server.validate(); err != nil { | ||
return fmt.Errorf("server config invalid: %w", err) | ||
} | ||
if err := c.OAuth.validate(); err != nil { | ||
return fmt.Errorf("oauth config invalid: %w", err) | ||
} | ||
if err := c.JWT.validate(); err != nil { | ||
return fmt.Errorf("jwt config invalid: %w", err) | ||
} | ||
if err := c.Yorkie.validate(); err != nil { | ||
return fmt.Errorf("yorkie config invalid: %w", err) | ||
} | ||
if err := c.Mongo.validate(); err != nil { | ||
return fmt.Errorf("mongo config invalid: %w", err) | ||
} | ||
if err := c.Storage.validate(); err != nil { | ||
return fmt.Errorf("storage config invalid: %w", err) | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add config file path validation
The
parseFlag
function should validate that the config file exists when a path is provided.📝 Committable suggestion