From 0b0b7e5ff1b31bb04def253abc75fe432d2e3b46 Mon Sep 17 00:00:00 2001 From: zijiren233 Date: Fri, 17 May 2024 19:26:17 +0800 Subject: [PATCH] Feat: load flags form env --- cmd/conf.go | 28 ------------- cmd/flags/config.go | 27 ++++--------- cmd/flags/server.go | 14 ++++--- cmd/flags/vars.go | 15 +++++++ cmd/root.go | 74 +++++++++++++++++++++++++--------- cmd/self-update.go | 2 +- cmd/server.go | 12 +++--- internal/bootstrap/config.go | 8 ++-- internal/bootstrap/db.go | 4 +- internal/bootstrap/gin.go | 2 +- internal/bootstrap/log.go | 8 ++-- internal/bootstrap/provider.go | 2 +- internal/db/update.go | 2 +- internal/version/version.go | 4 +- script/entrypoint.sh | 6 ++- server/router.go | 2 +- server/static/static.go | 4 +- utils/utils.go | 4 +- 18 files changed, 117 insertions(+), 101 deletions(-) delete mode 100644 cmd/conf.go create mode 100644 cmd/flags/vars.go diff --git a/cmd/conf.go b/cmd/conf.go deleted file mode 100644 index 35c4e86..0000000 --- a/cmd/conf.go +++ /dev/null @@ -1,28 +0,0 @@ -package cmd - -import ( - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/synctv-org/synctv/internal/bootstrap" -) - -var ConfCmd = &cobra.Command{ - Use: "conf", - Short: "init or check", - Long: `Init or check config file for correctness`, - PreRunE: func(cmd *cobra.Command, args []string) error { - return bootstrap.New(bootstrap.WithContext(cmd.Context())).Add( - bootstrap.InitConfig, - ).Run() - }, - RunE: Conf, -} - -func Conf(cmd *cobra.Command, args []string) error { - logrus.Infof("success") - return nil -} - -func init() { - RootCmd.AddCommand(ConfCmd) -} diff --git a/cmd/flags/config.go b/cmd/flags/config.go index a5ea9c2..bd61c5f 100644 --- a/cmd/flags/config.go +++ b/cmd/flags/config.go @@ -1,22 +1,9 @@ package flags -// Global -var ( - Dev bool - - LogStd bool - - SkipEnv bool - - EnvFileOverload bool - - SkipConfig bool - - EnvNoPrefix bool - - GitHubBaseURL string - - DataDir string - - ForceAutoMigrate bool -) +type GlobalFlags struct { + Dev bool `env:"DEV"` + LogStd bool `env:"LOG_STD"` + GitHubBaseURL string `env:"GITHUB_BASE_URL"` + DataDir string `env:"DATA_DIR"` + ForceAutoMigrate bool `env:"FORCE_AUTO_MIGRATE"` +} diff --git a/cmd/flags/server.go b/cmd/flags/server.go index 4240366..11bf859 100644 --- a/cmd/flags/server.go +++ b/cmd/flags/server.go @@ -1,8 +1,10 @@ package flags -var ( - DisableUpdateCheck bool - DisableWeb bool - WebPath string - DisableLogColor bool -) +type ServerFlags struct { + SkipConfig bool `env:"SKIP_CONFIG"` + SkipEnvConfig bool `env:"SKIP_ENV_CONFIG"` + DisableUpdateCheck bool `env:"DISABLE_UPDATE_CHECK"` + DisableWeb bool `env:"DISABLE_WEB"` + WebPath string `env:"WEB_PATH"` + DisableLogColor bool `env:"DISABLE_LOG_COLOR"` +} diff --git a/cmd/flags/vars.go b/cmd/flags/vars.go new file mode 100644 index 0000000..016ce66 --- /dev/null +++ b/cmd/flags/vars.go @@ -0,0 +1,15 @@ +package flags + +var ( + // Global + EnvNoPrefix bool + SkipEnvFlag bool + Global GlobalFlags + + // Server + Server ServerFlags +) + +const ( + ENV_PREFIX = "SYNCTV_" +) diff --git a/cmd/root.go b/cmd/root.go index 1632484..622070a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,7 +4,9 @@ import ( "fmt" "os" "path/filepath" + "strings" + "github.com/caarlos0/env/v9" "github.com/go-kratos/kratos/v2/log" "github.com/joho/godotenv" "github.com/mitchellh/go-homedir" @@ -24,29 +26,63 @@ var RootCmd = &cobra.Command{ Short: "synctv", Long: `synctv https://github.com/synctv-org/synctv`, PersistentPreRun: func(cmd *cobra.Command, args []string) { - s, err := utils.GetEnvFiles(flags.DataDir) + prefix := flags.ENV_PREFIX + if !flags.SkipEnvFlag { + s, ok := os.LookupEnv("ENV_NO_PREFIX") + if ok { + if strings.ToLower(s) == "true" { + flags.EnvNoPrefix = true + } + } + if flags.EnvNoPrefix { + prefix = "" + log.Info("load flags from env without prefix") + } else { + log.Infof("load flags from env with prefix: %s", prefix) + } + } + if !flags.SkipEnvFlag { + dataDir, ok := os.LookupEnv(prefix + "DATA_DIR") + if ok { + flags.Global.DataDir = dataDir + } + dev, ok := os.LookupEnv(prefix + "DEV") + if ok { + if strings.ToLower(dev) == "true" { + flags.Global.Dev = true + } + } + } + + envFiles, err := utils.GetEnvFiles(flags.Global.DataDir) if err != nil { logrus.Warnf("get env files error: %v", err) } - if flags.Dev { - ss, err := utils.GetEnvFiles(".") + if flags.Global.Dev { + moreEnvFiles, err := utils.GetEnvFiles(".") if err != nil { logrus.Warnf("get env files error: %v", err) } - s = append(s, ss...) + envFiles = append(envFiles, moreEnvFiles...) } - if len(s) != 0 { - if flags.EnvFileOverload { - log.Infof("overload env from: %v", s) - err = godotenv.Overload(s...) - } else { - log.Infof("load env from: %v", s) - err = godotenv.Load(s...) - } + if len(envFiles) != 0 { + log.Infof("load env from: %v", envFiles) + err = godotenv.Load(envFiles...) if err != nil { logrus.Fatalf("load env error: %v", err) } } + + if !flags.SkipEnvFlag { + err := env.ParseWithOptions(&flags.Global, env.Options{Prefix: prefix}) + if err != nil { + logrus.Fatalf("parse env error: %v", err) + } + err = env.ParseWithOptions(&flags.Server, env.Options{Prefix: prefix}) + if err != nil { + logrus.Fatalf("parse env error: %v", err) + } + } }, } @@ -58,19 +94,17 @@ func Execute() { } func init() { - RootCmd.PersistentFlags().BoolVar(&flags.Dev, "dev", version.Version == "dev", "start with dev mode") - RootCmd.PersistentFlags().BoolVar(&flags.LogStd, "log-std", true, "log to std") + RootCmd.PersistentFlags().BoolVar(&flags.Global.Dev, "dev", version.Version == "dev", "start with dev mode") + RootCmd.PersistentFlags().BoolVar(&flags.Global.LogStd, "log-std", true, "log to std") RootCmd.PersistentFlags().BoolVar(&flags.EnvNoPrefix, "env-no-prefix", false, "env no SYNCTV_ prefix") - RootCmd.PersistentFlags().BoolVar(&flags.SkipConfig, "skip-config", false, "skip config") - RootCmd.PersistentFlags().BoolVar(&flags.SkipEnv, "skip-env", false, "skip env") - RootCmd.PersistentFlags().BoolVar(&flags.EnvFileOverload, "env-file-overload", false, "env file overload") - RootCmd.PersistentFlags().StringVar(&flags.GitHubBaseURL, "github-base-url", "https://api.github.com/", "github api base url") + RootCmd.PersistentFlags().BoolVar(&flags.SkipEnvFlag, "skip-env-flag", true, "skip env flag") + RootCmd.PersistentFlags().StringVar(&flags.Global.GitHubBaseURL, "github-base-url", "https://api.github.com/", "github api base url") home, err := homedir.Dir() if err != nil { home = "~" } - RootCmd.PersistentFlags().StringVar(&flags.DataDir, "data-dir", filepath.Join(home, ".synctv"), "data dir") - RootCmd.PersistentFlags().BoolVar(&flags.ForceAutoMigrate, "force-auto-migrate", version.Version == "dev", "force auto migrate") + RootCmd.PersistentFlags().StringVar(&flags.Global.DataDir, "data-dir", filepath.Join(home, ".synctv"), "data dir") + RootCmd.PersistentFlags().BoolVar(&flags.Global.ForceAutoMigrate, "force-auto-migrate", version.Version == "dev", "force auto migrate") } func init() { diff --git a/cmd/self-update.go b/cmd/self-update.go index 38b5dc2..26e92df 100644 --- a/cmd/self-update.go +++ b/cmd/self-update.go @@ -27,7 +27,7 @@ var SelfUpdateCmd = &cobra.Command{ } func SelfUpdate(cmd *cobra.Command, args []string) error { - v, err := version.NewVersionInfo(version.WithBaseURL(flags.GitHubBaseURL)) + v, err := version.NewVersionInfo(version.WithBaseURL(flags.Global.GitHubBaseURL)) if err != nil { log.Errorf("get version info error: %v", err) return err diff --git a/cmd/server.go b/cmd/server.go index cbbd771..dfd140f 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -35,7 +35,7 @@ var ServerCmd = &cobra.Command{ bootstrap.InitVendorBackend, bootstrap.InitSetting, ) - if !flags.DisableUpdateCheck { + if !flags.Server.DisableUpdateCheck { boot.Add(bootstrap.InitCheckUpdate) } return boot.Run() @@ -159,8 +159,10 @@ func Server(cmd *cobra.Command, args []string) { func init() { RootCmd.AddCommand(ServerCmd) - ServerCmd.PersistentFlags().BoolVar(&flags.DisableUpdateCheck, "disable-update-check", false, "disable update check") - ServerCmd.PersistentFlags().BoolVar(&flags.DisableWeb, "disable-web", false, "disable web") - ServerCmd.PersistentFlags().BoolVar(&flags.DisableLogColor, "disable-log-color", false, "disable log color") - ServerCmd.PersistentFlags().StringVar(&flags.WebPath, "web-path", "", "if not set, use embed web") + ServerCmd.PersistentFlags().BoolVar(&flags.Server.DisableUpdateCheck, "disable-update-check", false, "disable update check") + ServerCmd.PersistentFlags().BoolVar(&flags.Server.DisableWeb, "disable-web", false, "disable web") + ServerCmd.PersistentFlags().BoolVar(&flags.Server.DisableLogColor, "disable-log-color", false, "disable log color") + ServerCmd.PersistentFlags().StringVar(&flags.Server.WebPath, "web-path", "", "if not set, use embed web") + ServerCmd.PersistentFlags().BoolVar(&flags.Server.SkipConfig, "skip-config", false, "skip config") + ServerCmd.PersistentFlags().BoolVar(&flags.Server.SkipEnvConfig, "skip-env-config", false, "skip env config") } diff --git a/internal/bootstrap/config.go b/internal/bootstrap/config.go index 7988bf3..561b11e 100644 --- a/internal/bootstrap/config.go +++ b/internal/bootstrap/config.go @@ -19,13 +19,13 @@ func InitDefaultConfig(ctx context.Context) error { } func InitConfig(ctx context.Context) (err error) { - if flags.SkipConfig && flags.SkipEnv { + if flags.Server.SkipConfig && flags.Server.SkipEnvConfig { log.Fatal("skip config and skip env at the same time") return errors.New("skip config and skip env at the same time") } conf.Conf = conf.DefaultConfig() - if !flags.SkipConfig { - configFile, err := utils.OptFilePath(filepath.Join(flags.DataDir, "config.yaml")) + if !flags.Server.SkipConfig { + configFile, err := utils.OptFilePath(filepath.Join(flags.Global.DataDir, "config.yaml")) if err != nil { log.Fatalf("config file path error: %v", err) } @@ -40,7 +40,7 @@ func InitConfig(ctx context.Context) (err error) { log.Info("restore config success") } } - if !flags.SkipEnv { + if !flags.Server.SkipEnvConfig { prefix := "SYNCTV_" if flags.EnvNoPrefix { prefix = "" diff --git a/internal/bootstrap/db.go b/internal/bootstrap/db.go index c981af1..94e75c0 100644 --- a/internal/bootstrap/db.go +++ b/internal/bootstrap/db.go @@ -141,7 +141,7 @@ func createDialector(dbConf conf.DatabaseConfig) (dialector gorm.Dialector, err func newDBLogger() logger.Interface { var logLevel logger.LogLevel - if flags.Dev { + if flags.Global.Dev { logLevel = logger.Info } else { logLevel = logger.Warn @@ -152,7 +152,7 @@ func newDBLogger() logger.Interface { SlowThreshold: time.Second, LogLevel: logLevel, IgnoreRecordNotFoundError: true, - ParameterizedQueries: !flags.Dev && version.Version != "dev", + ParameterizedQueries: !flags.Global.Dev && version.Version != "dev", Colorful: utils.ForceColor(), }, ) diff --git a/internal/bootstrap/gin.go b/internal/bootstrap/gin.go index 9ad4db3..9fe1ef3 100644 --- a/internal/bootstrap/gin.go +++ b/internal/bootstrap/gin.go @@ -9,7 +9,7 @@ import ( ) func InitGinMode(ctx context.Context) error { - if flags.Dev { + if flags.Global.Dev { gin.SetMode(gin.DebugMode) } else { gin.SetMode(gin.ReleaseMode) diff --git a/internal/bootstrap/log.go b/internal/bootstrap/log.go index dfbd5e6..ef89686 100644 --- a/internal/bootstrap/log.go +++ b/internal/bootstrap/log.go @@ -18,7 +18,7 @@ import ( ) func setLog(l *logrus.Logger) { - if flags.Dev { + if flags.Global.Dev { l.SetLevel(logrus.DebugLevel) l.SetReportCaller(true) } else { @@ -55,7 +55,7 @@ func InitLog(ctx context.Context) (err error) { } else { w = l } - if flags.Dev || flags.LogStd { + if flags.Global.Dev || flags.Global.LogStd { logrus.SetOutput(io.MultiWriter(os.Stdout, w)) logrus.Infof("log: enable log to stdout and file: %s", conf.Conf.Log.FilePath) } else { @@ -81,8 +81,8 @@ func InitLog(ctx context.Context) (err error) { logrus.SetFormatter(&logrus.TextFormatter{ ForceColors: forceColor, DisableColors: !forceColor, - ForceQuote: flags.Dev, - DisableQuote: !flags.Dev, + ForceQuote: flags.Global.Dev, + DisableQuote: !flags.Global.Dev, DisableSorting: true, FullTimestamp: true, TimestampFormat: time.DateTime, diff --git a/internal/bootstrap/provider.go b/internal/bootstrap/provider.go index 4607d16..f43699f 100644 --- a/internal/bootstrap/provider.go +++ b/internal/bootstrap/provider.go @@ -60,7 +60,7 @@ var ( func InitProvider(ctx context.Context) (err error) { logOur := log.StandardLogger().Writer() logLevle := hclog.Info - if flags.Dev { + if flags.Global.Dev { logLevle = hclog.Debug } for _, op := range conf.Conf.Oauth2Plugins { diff --git a/internal/db/update.go b/internal/db/update.go index 97cda1a..c6bd342 100644 --- a/internal/db/update.go +++ b/internal/db/update.go @@ -92,7 +92,7 @@ func UpgradeDatabase() error { return err } currentVersion := setting.Value - if flags.ForceAutoMigrate || currentVersion != CurrentVersion { + if flags.Global.ForceAutoMigrate || currentVersion != CurrentVersion { err = autoMigrate(models...) if err != nil { log.Fatalf("failed to auto migrate: %s", err.Error()) diff --git a/internal/version/version.go b/internal/version/version.go index 8afb45b..f9c6a2b 100644 --- a/internal/version/version.go +++ b/internal/version/version.go @@ -156,7 +156,7 @@ func (v *VersionInfo) NeedUpdate(ctx context.Context) (bool, error) { } func (v *VersionInfo) SelfUpdate(ctx context.Context) (err error) { - if flags.Dev { + if flags.Global.Dev { log.Info("self update: dev mode, update to latest dev version") } else if v.Current() != "dev" { latest, err := v.Latest(ctx) @@ -182,7 +182,7 @@ func (v *VersionInfo) SelfUpdate(ctx context.Context) (err error) { } var url string - if flags.Dev { + if flags.Global.Dev { url, err = v.DevBinaryURL(ctx) } else { url, err = v.LatestBinaryURL(ctx) diff --git a/script/entrypoint.sh b/script/entrypoint.sh index 01dd9fb..14fdeb0 100644 --- a/script/entrypoint.sh +++ b/script/entrypoint.sh @@ -4,4 +4,8 @@ chown -R ${PUID}:${PGID} /root/.synctv umask ${UMASK} -exec su-exec ${PUID}:${PGID} synctv --env-no-prefix $@ +export ENV_NO_PREFIX=true + +export DATA_DIR=/root/.synctv + +exec su-exec ${PUID}:${PGID} synctv $@ --skip-env-flag=false diff --git a/server/router.go b/server/router.go index b220e50..282c91f 100644 --- a/server/router.go +++ b/server/router.go @@ -13,7 +13,7 @@ func Init(e *gin.Engine) { middlewares.Init(e) auth.Init(e) handlers.Init(e) - if !flags.DisableWeb { + if !flags.Server.DisableWeb { static.Init(e) } } diff --git a/server/static/static.go b/server/static/static.go index f47eb26..d539ea1 100644 --- a/server/static/static.go +++ b/server/static/static.go @@ -20,7 +20,7 @@ func Init(e *gin.Engine) { web := e.Group("/web") - if flags.WebPath == "" { + if flags.Server.WebPath == "" { err := SiglePageAppFS(web, public.Public, true) if err != nil { log.Fatalf("failed to init fs router: %v", err) @@ -38,7 +38,7 @@ func Init(e *gin.Engine) { // } // }) } else { - err := SiglePageAppFS(web, os.DirFS(flags.WebPath), false) + err := SiglePageAppFS(web, os.DirFS(flags.Server.WebPath), false) if err != nil { log.Fatalf("failed to init fs router: %v", err) } diff --git a/utils/utils.go b/utils/utils.go index 595a193..d83a294 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -300,7 +300,7 @@ func getLocalIPs() []net.IP { func OptFilePath(filePath string) (string, error) { if !filepath.IsAbs(filePath) { - return filepath.Abs(filepath.Join(flags.DataDir, filePath)) + return filepath.Abs(filepath.Join(flags.Global.DataDir, filePath)) } return filePath, nil } @@ -360,7 +360,7 @@ var ( func ForceColor() bool { needColorOnce.Do(func() { - if flags.DisableLogColor { + if flags.Server.DisableLogColor { needColor = false return }