feat: implement configuration loading from file, env vars and flags
This commit is contained in:
parent
0299e2891c
commit
46cecdc007
1 changed files with 83 additions and 19 deletions
102
main.go
102
main.go
|
@ -5,18 +5,21 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"embed"
|
"embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/num30/config"
|
|
||||||
"github.com/pressly/goose/v3"
|
"github.com/pressly/goose/v3"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/labstack/echo/v4/middleware"
|
"github.com/labstack/echo/v4/middleware"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed static/*
|
//go:embed static/*
|
||||||
|
@ -30,7 +33,7 @@ type OAuthConfig struct {
|
||||||
ClientSecret string `config:"client_secret" yaml:"client_secret"`
|
ClientSecret string `config:"client_secret" yaml:"client_secret"`
|
||||||
AuthURL string `config:"auth_url" yaml:"auth_url"`
|
AuthURL string `config:"auth_url" yaml:"auth_url"`
|
||||||
TokenURL string `config:"token_url" yaml:"token_url"`
|
TokenURL string `config:"token_url" yaml:"token_url"`
|
||||||
UserInfoURL string `config:"userinfo_url" yaml:"userinfo_url"`
|
UserInfoURL string `config:"user_info_url" yaml:"user_info_url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DBConfig struct {
|
type DBConfig struct {
|
||||||
|
@ -61,34 +64,95 @@ var (
|
||||||
var db *sql.DB
|
var db *sql.DB
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Use the global cfg variable instead of declaring a new one
|
// Load configuration from YAML file, environment variables, and flags
|
||||||
cfgReader := config.NewConfReader("config").WithSearchDirs("./", ".", "../", "../../")
|
configFile := flag.String("config", "config.yaml", "Path to config file")
|
||||||
cfgErr := cfgReader.Read(&cfg)
|
serverPort := flag.Int("port", 0, "Server port (overrides config file)")
|
||||||
|
oauthClientID := flag.String("oauth-client-id", "", "OAuth Client ID (overrides config file)")
|
||||||
|
oauthClientSecret := flag.String("oauth-client-secret", "", "OAuth Client Secret (overrides config file)")
|
||||||
|
oauthAuthURL := flag.String("oauth-auth-url", "", "OAuth Auth URL (overrides config file)")
|
||||||
|
oauthTokenURL := flag.String("oauth-token-url", "", "OAuth Token URL (overrides config file)")
|
||||||
|
oauthUserInfoURL := flag.String("oauth-user-info-url", "", "OAuth User Info URL (overrides config file)")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
// Set default values
|
||||||
|
cfg = Config{
|
||||||
|
Env: "dev",
|
||||||
|
Server: struct {
|
||||||
|
Port int `config:"port"`
|
||||||
|
}{Port: 8088},
|
||||||
|
OAuth: OAuthConfig{},
|
||||||
|
DB: DBConfig{
|
||||||
|
Driver: "sqlite3",
|
||||||
|
DBName: "./inventor.sqlite",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
yamlData, err := os.ReadFile(*configFile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Warning: Could not read config file: %v\n", err)
|
||||||
|
} else {
|
||||||
|
if err := yaml.Unmarshal(yamlData, &cfg); err != nil {
|
||||||
|
fmt.Printf("Warning: Could not parse config file: %v\n", err)
|
||||||
|
} else {
|
||||||
|
fmt.Println("Successfully loaded configuration from", *configFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if envPort := os.Getenv("INVENTOR_SERVER_PORT"); envPort != "" {
|
||||||
|
if port, err := strconv.Atoi(envPort); err == nil {
|
||||||
|
cfg.Server.Port = port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if envClientID := os.Getenv("INVENTOR_OAUTH_CLIENT_ID"); envClientID != "" {
|
||||||
|
cfg.OAuth.ClientID = envClientID
|
||||||
|
}
|
||||||
|
if envClientSecret := os.Getenv("INVENTOR_OAUTH_CLIENT_SECRET"); envClientSecret != "" {
|
||||||
|
cfg.OAuth.ClientSecret = envClientSecret
|
||||||
|
}
|
||||||
|
if envAuthURL := os.Getenv("INVENTOR_OAUTH_AUTH_URL"); envAuthURL != "" {
|
||||||
|
cfg.OAuth.AuthURL = envAuthURL
|
||||||
|
}
|
||||||
|
if envTokenURL := os.Getenv("INVENTOR_OAUTH_TOKEN_URL"); envTokenURL != "" {
|
||||||
|
cfg.OAuth.TokenURL = envTokenURL
|
||||||
|
}
|
||||||
|
if envUserInfoURL := os.Getenv("INVENTOR_OAUTH_USER_INFO_URL"); envUserInfoURL != "" {
|
||||||
|
cfg.OAuth.UserInfoURL = envUserInfoURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Override with command line flags (highest priority)
|
||||||
|
if *serverPort != 0 {
|
||||||
|
cfg.Server.Port = *serverPort
|
||||||
|
}
|
||||||
|
if *oauthClientID != "" {
|
||||||
|
cfg.OAuth.ClientID = *oauthClientID
|
||||||
|
}
|
||||||
|
if *oauthClientSecret != "" {
|
||||||
|
cfg.OAuth.ClientSecret = *oauthClientSecret
|
||||||
|
}
|
||||||
|
if *oauthAuthURL != "" {
|
||||||
|
cfg.OAuth.AuthURL = *oauthAuthURL
|
||||||
|
}
|
||||||
|
if *oauthTokenURL != "" {
|
||||||
|
cfg.OAuth.TokenURL = *oauthTokenURL
|
||||||
|
}
|
||||||
|
if *oauthUserInfoURL != "" {
|
||||||
|
cfg.OAuth.UserInfoURL = *oauthUserInfoURL
|
||||||
|
}
|
||||||
|
|
||||||
zapcfg := zap.NewProductionConfig()
|
zapcfg := zap.NewProductionConfig()
|
||||||
if cfg.Env == "dev" {
|
if cfg.Env == "dev" {
|
||||||
zapcfg = zap.NewDevelopmentConfig()
|
zapcfg = zap.NewDevelopmentConfig()
|
||||||
}
|
}
|
||||||
logger, err := zapcfg.Build()
|
logger, err = zapcfg.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("Failed to initialize logger: %v", err))
|
panic(fmt.Sprintf("Failed to initialize logger: %v", err))
|
||||||
}
|
}
|
||||||
defer logger.Sync()
|
defer logger.Sync()
|
||||||
|
|
||||||
if cfgErr != nil {
|
// Configuration errors are now handled inline during loading
|
||||||
logger.Fatal("Failed to load config", zap.Error(cfgErr))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print the raw config to see what's actually loaded
|
// Print the raw config to see what's actually loaded
|
||||||
logger.Info("Raw config loaded", zap.Any("config", cfg))
|
logger.Debug("Raw config loaded", zap.Any("config", cfg))
|
||||||
|
|
||||||
// Add detailed logging of the OAuth config
|
|
||||||
logger.Info("OAuth Configuration",
|
|
||||||
zap.String("ClientID", cfg.OAuth.ClientID),
|
|
||||||
zap.String("ClientSecret", cfg.OAuth.ClientSecret),
|
|
||||||
zap.String("AuthURL", cfg.OAuth.AuthURL),
|
|
||||||
zap.String("TokenURL", cfg.OAuth.TokenURL),
|
|
||||||
zap.String("UserInfoURL", cfg.OAuth.UserInfoURL))
|
|
||||||
|
|
||||||
// Initialize OAuth2
|
// Initialize OAuth2
|
||||||
oauthConfig = &oauth2.Config{
|
oauthConfig = &oauth2.Config{
|
||||||
|
@ -98,7 +162,7 @@ func main() {
|
||||||
AuthURL: cfg.OAuth.AuthURL,
|
AuthURL: cfg.OAuth.AuthURL,
|
||||||
TokenURL: cfg.OAuth.TokenURL,
|
TokenURL: cfg.OAuth.TokenURL,
|
||||||
},
|
},
|
||||||
RedirectURL: fmt.Sprintf("http://localhost:%d/oauth/callback", cfg.Server.Port),
|
RedirectURL: fmt.Sprintf("http://localhost:3000/oauth/callback"),
|
||||||
Scopes: []string{"profile", "email"},
|
Scopes: []string{"profile", "email"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue