From a342cd50b05ebd9e7fde868d2116431d91380184 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 7 Oct 2021 13:24:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=88=B0=20Gou=20=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20SQLite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/{info.go => inspect.go} | 8 ++-- cmd/migrate.go | 13 ++++-- cmd/root.go | 28 +++++++++-- cmd/start.go | 78 ++++++++++++++++++++----------- config/config.go | 92 ++++++++++++++++++++++++++++++++++--- global/init_test.go | 2 +- global/load.go | 47 +++++++++++++++++++ global/vars.go | 17 ------- go.mod | 13 +++--- go.sum | 19 ++++++++ main_test.go | 15 +++--- xlog/xlog.go | 5 ++ 12 files changed, 265 insertions(+), 72 deletions(-) rename cmd/{info.go => inspect.go} (75%) diff --git a/cmd/info.go b/cmd/inspect.go similarity index 75% rename from cmd/info.go rename to cmd/inspect.go index 508af1ba..240b87b1 100644 --- a/cmd/info.go +++ b/cmd/inspect.go @@ -4,18 +4,20 @@ import ( "github.com/spf13/cobra" "github.com/yaoapp/kun/maps" "github.com/yaoapp/kun/utils" + "github.com/yaoapp/xiang/config" "github.com/yaoapp/xiang/global" ) -var infoCmd = &cobra.Command{ - Use: "info", +var inspectCmd = &cobra.Command{ + Use: "inspect", Short: "显示当前配置信息", Long: `显示当前配置信息`, Run: func(cmd *cobra.Command, args []string) { + Boot() res := maps.Map{ "version": global.VERSION, "domain": global.DOMAIN, - "config": global.Conf, + "config": config.Conf, } utils.Dump(res) }, diff --git a/cmd/migrate.go b/cmd/migrate.go index 00711fce..2173e8af 100644 --- a/cmd/migrate.go +++ b/cmd/migrate.go @@ -1,9 +1,13 @@ package cmd import ( + "fmt" + + "github.com/fatih/color" "github.com/spf13/cobra" "github.com/yaoapp/gou" - "github.com/yaoapp/kun/utils" + "github.com/yaoapp/xiang/config" + "github.com/yaoapp/xiang/global" ) var name string @@ -12,6 +16,9 @@ var migrateCmd = &cobra.Command{ Short: "更新数据结构", Long: `更新数据库结构`, Run: func(cmd *cobra.Command, args []string) { + Boot() + // 加载数据模型 + global.Load(config.Conf) if name != "" { mod, has := gou.Models[name] @@ -22,8 +29,8 @@ var migrateCmd = &cobra.Command{ } // Do Stuff Here - for name, mod := range gou.Models { - utils.Dump(name) + for _, mod := range gou.Models { + fmt.Println(color.GreenString("更新数据模型 %s 绑定数据表: %s", mod.Name, mod.MetaData.Table.Name)) mod.Migrate(true) } }, diff --git a/cmd/root.go b/cmd/root.go index 1d45eed1..fa7f0da3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -3,10 +3,15 @@ package cmd import ( "fmt" "os" + "path/filepath" "github.com/spf13/cobra" + "github.com/yaoapp/xiang/config" ) +var appPath string +var envFile string + var rootCmd = &cobra.Command{ Use: "xiang", Short: "象传应用引擎命令行工具", @@ -27,12 +32,12 @@ func init() { versionCmd, domainCmd, migrateCmd, - infoCmd, + inspectCmd, startCmd, ) - rootCmd.SetHelpCommand(helpCmd) - + rootCmd.PersistentFlags().StringVarP(&appPath, "app", "a", "", "指定应用目录") + rootCmd.PersistentFlags().StringVarP(&envFile, "env", "e", "", "指定环境变量文件") } // Execute 运行Root @@ -42,3 +47,20 @@ func Execute() { os.Exit(1) } } + +// Boot 设定配置 +func Boot() { + + if envFile == "" && appPath != "" { + config.SetAppPath(appPath, filepath.Join(appPath, ".env")) + return + } + + if envFile != "" { // 指定环境变量文件 + config.SetEnvFile(envFile) + } + + if appPath != "" { + config.SetAppPath(appPath) + } +} diff --git a/cmd/start.go b/cmd/start.go index f33c7365..f371fe34 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -1,50 +1,68 @@ package cmd import ( - "log" + "fmt" "path/filepath" + "strings" + "github.com/fatih/color" "github.com/spf13/cobra" "github.com/yaoapp/gou" + "github.com/yaoapp/xiang/config" "github.com/yaoapp/xiang/global" ) -var startAppPath string var startCmd = &cobra.Command{ Use: "start", Short: "启动象传应用引擎", Long: `启动象传应用引擎`, Run: func(cmd *cobra.Command, args []string) { - defer global.ServiceStop(func() { log.Println("服务已关闭") }) - log.Printf("启动象传应用引擎 v%s mode=%s", global.VERSION, global.Conf.Mode) - log.Printf("应用根目录: %s", global.Conf.Root) + defer global.ServiceStop(func() { fmt.Println("服务已关闭") }) - // 应用目录 - if startAppPath != "" { - global.Conf.Root = startAppPath - global.Conf.RootAPI = filepath.Join(startAppPath, "/apis") - global.Conf.RootFLow = filepath.Join(startAppPath, "/flows") - global.Conf.RootModel = filepath.Join(startAppPath, "/models") - global.Conf.RootPlugin = filepath.Join(startAppPath, "/plugins") - global.Conf.RootTable = filepath.Join(startAppPath, "/tables") - global.Conf.RootChart = filepath.Join(startAppPath, "/charts") - global.Conf.RootScreen = filepath.Join(startAppPath, "/screens") - global.Conf.RootData = filepath.Join(startAppPath, "/data") - - // 重新加载应用 - global.Reload(global.Conf) + Boot() + mode := config.Conf.Mode + if mode == "debug" { + mode = color.RedString("调试模式") + } else { + mode = "" } - // 启动服务 - for _, api := range gou.APIs { - log.Printf("%s(%d)", api.Name, len(api.HTTP.Paths)) + fmt.Printf(color.GreenString("\n象传应用引擎 v%s %s", global.VERSION, mode)) + + // 加载数据模型 API 等 + global.Load(config.Conf) + + // 打印应用目录信息 + fmt.Printf(color.GreenString("\n应用根目录: %s\n", config.Conf.Root)) + for _, api := range gou.APIs { // API信息 + fmt.Printf(color.CyanString("\n%s(%d)\n", api.Name, len(api.HTTP.Paths))) for _, p := range api.HTTP.Paths { - log.Println(p.Method, filepath.Join("/api", api.HTTP.Group, p.Path), "\tprocess:", p.Process) + + fmt.Println( + colorMehtod(p.Method), + color.WhiteString(filepath.Join("/api", api.HTTP.Group, p.Path)), + "\tprocess:", p.Process) } + } + domain := global.DOMAIN + if domain == "*.iqka.com" { + domain = "local.iqka.com" + } + + port := fmt.Sprintf(":%d", config.Conf.Service.Port) + if port == ":80" { + port = "" + } + + fmt.Printf(color.GreenString("\n前台界面: http://%s%s/\n", domain, port)) + fmt.Printf(color.GreenString("管理后台: http://%s%s/xiang/login\n", domain, port)) + fmt.Printf(color.GreenString("API 接口: http://%s%s/api\n", domain, port)) + fmt.Printf(color.GreenString("跨域访问: %s\n\n", strings.Join(config.Conf.Service.Allow, ","))) + // 调试模式 - if global.Conf.Mode == "debug" { + if config.Conf.Mode == "debug" { global.WatchChanges() } @@ -52,6 +70,14 @@ var startCmd = &cobra.Command{ }, } -func init() { - startCmd.PersistentFlags().StringVarP(&startAppPath, "app", "a", "", "指定应用目录") +func colorMehtod(method string) string { + method = strings.ToUpper(method) + switch method { + case "GET": + return color.GreenString("GET") + case "POST": + return color.YellowString("POST") + default: + return color.WhiteString(method) + } } diff --git a/config/config.go b/config/config.go index d3ff284b..fec04612 100644 --- a/config/config.go +++ b/config/config.go @@ -4,6 +4,8 @@ import ( "io" "log" "os" + "path/filepath" + "strings" "github.com/caarlos0/env/v6" "github.com/joho/godotenv" @@ -30,6 +32,8 @@ type XiangConfig struct { Source string `json:"source,omitempty" env:"XIANG_SOURCE" envDefault:"fs://."` // 源码路径(用于单元测试载入数据) Path string `json:"path,omitempty" env:"XIANG_PATH" envDefault:"bin://xiang"` // 引擎文件目录 Root string `json:"root,omitempty" env:"XIANG_ROOT" envDefault:"fs://."` // 应用文件目录 + RootUI string `json:"root_ui,omitempty" env:"XIANG_ROOT_UI"` // 应用界面静态文件目录 + RootDB string `json:"root_db,omitempty" env:"XIANG_ROOT_DB"` // 应用SQLite数据库目录 RootData string `json:"root_data,omitempty" env:"XIANG_ROOT_DATA"` // 应用数据文件目录 RootAPI string `json:"root_api,omitempty" env:"XIANG_ROOT_API"` // 应用API文件目录 RootModel string `json:"root_model,omitempty" env:"XIANG_ROOT_MODEL"` // 应用模型文件目录 @@ -54,10 +58,11 @@ type ServiceConfig struct { // DatabaseConfig 数据库配置 type DatabaseConfig struct { - Debug bool `json:"debug,omitempty" env:"XIANG_DB_DEBUG" envDefault:"false"` // DEBUG 开关 - Primary []string `json:"primary,omitempty" env:"XIANG_DB_PRIMARY" envSeparator:"|"` // 主库连接DSN - Secondary []string `json:"secondary,omitempty" env:"XIANG_DB_SECONDARY" envSeparator:"|"` // 从库连接DSN - AESKey string `json:"aeskey,omitempty" env:"XIANG_DB_AESKEY"` // 加密存储KEY + Debug bool `json:"debug,omitempty" env:"XIANG_DB_DEBUG" envDefault:"false"` // DEBUG 开关 + Driver string `json:"driver,omitempty" env:"XIANG_DB_DRIVER" envDefault:"sqlite3"` // 数据库驱动 ( sqlite3, mysql, postgres) + Primary []string `json:"primary,omitempty" env:"XIANG_DB_PRIMARY" envSeparator:"|" envDefault:"file:xiang.db?cache=shared&mode=memory"` // 主库连接DSN + Secondary []string `json:"secondary,omitempty" env:"XIANG_DB_SECONDARY" envSeparator:"|"` // 从库连接DSN + AESKey string `json:"aeskey,omitempty" env:"XIANG_DB_AESKEY"` // 加密存储KEY } // StorageConfig 存储配置 @@ -81,15 +86,25 @@ type LogConfig struct { } // NewConfig 创建配置文件 -func NewConfig() Config { +func NewConfig(envfile ...string) Config { + filename := os.Getenv("XIANG_ENV_FILE") if filename == "" { filename = ".env" } - err := godotenv.Load(filename) + if len(envfile) > 0 { + file, err := filepath.Abs(envfile[0]) + if err != nil { + log.Printf("加载环境配置文件%s出错 %s\n", envfile[0], err.Error()) + } else { + filename = file + } + } + + err := godotenv.Overload(filename) if err != nil { - log.Printf("读取环境配置文件%s出错 %s\n", filename, err.Error()) + log.Printf("加载环境配置文件%s出错 %s\n", filename, err.Error()) } cfg := Config{} @@ -126,6 +141,7 @@ func (cfg *Config) SetDefaults() { if cfg.RootPlugin == "" { cfg.RootPlugin = cfg.Root + "/plugins" } + if cfg.RootTable == "" { cfg.RootTable = cfg.Root + "/tables" } @@ -135,10 +151,72 @@ func (cfg *Config) SetDefaults() { if cfg.RootScreen == "" { cfg.RootScreen = cfg.Root + "/screens" } + if cfg.RootData == "" { cfg.RootData = cfg.Root + "/data" } + if cfg.RootDB == "" { + cfg.RootDB = cfg.Root + "/db" + cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "fs://") + cfg.RootDB = strings.TrimPrefix(cfg.RootDB, "file://") + } + if cfg.RootUI == "" { + cfg.RootUI = cfg.Root + "/ui" + cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "fs://") + cfg.RootUI = strings.TrimPrefix(cfg.RootUI, "file://") + + } + +} + +// SetEnvFile 指定ENV文件 +func SetEnvFile(filename string) { + Conf = NewConfig(filename) +} + +// SetAppPath 设定应用目录 +func SetAppPath(root string, envfile ...string) { + + fullpath, err := filepath.Abs(root) + if err != nil { + log.Panicf("设定应用目录%s出错 %s\n", root, err.Error()) + } + + // 创建应用目录 + pathinfo, err := os.Stat(fullpath) + if os.IsNotExist(err) { + err := os.MkdirAll(fullpath, os.ModePerm) + if err != nil { + log.Panicf("创建目录失败(%s) %s", root, err) + } + } + pathinfo, err = os.Stat(fullpath) + if !pathinfo.IsDir() { + log.Panicf("检查应用目录失败(%s) ", err) + } + + if !pathinfo.IsDir() { + log.Panicf("应用目录不是文件夹(%s) ", root) + } + + // Set ENV + if len(envfile) > 0 { + Conf = NewConfig(envfile[0]) + } + + // 从加载配置文件 + Conf.Root = fullpath + Conf.RootAPI = filepath.Join(fullpath, "/apis") + Conf.RootFLow = filepath.Join(fullpath, "/flows") + Conf.RootModel = filepath.Join(fullpath, "/models") + Conf.RootPlugin = filepath.Join(fullpath, "/plugins") + Conf.RootTable = filepath.Join(fullpath, "/tables") + Conf.RootChart = filepath.Join(fullpath, "/charts") + Conf.RootScreen = filepath.Join(root, "/screens") + Conf.RootData = filepath.Join(fullpath, "/data") + Conf.RootUI = filepath.Join(fullpath, "/ui") + Conf.RootDB = filepath.Join(fullpath, "/db") } // IsDebug 是否为调试模式 diff --git a/global/init_test.go b/global/init_test.go index 8525468f..294144f7 100644 --- a/global/init_test.go +++ b/global/init_test.go @@ -15,7 +15,7 @@ var cfg config.Config func TestMain(m *testing.M) { // 加载模型等 - Load(Conf) + Load(config.Conf) // 加载表格(临时) root := "fs://" + path.Join(Conf.Source, "/app/tables/service.json") diff --git a/global/load.go b/global/load.go index 41cb7206..b4dbd039 100644 --- a/global/load.go +++ b/global/load.go @@ -1,6 +1,7 @@ package global import ( + "fmt" "io/ioutil" "log" "os" @@ -15,6 +16,7 @@ import ( "github.com/yaoapp/xiang/data" "github.com/yaoapp/xiang/table" "github.com/yaoapp/xiang/xfs" + "github.com/yaoapp/xun/capsule" ) // Script 脚本文件类型 @@ -51,6 +53,9 @@ var App AppInfo // Load 根据配置加载 API, FLow, Model, Plugin func Load(cfg config.Config) { + + AppInit(cfg) + DBConnect(cfg.Database) LoadAppInfo(cfg.Root) LoadEngine(cfg.Path) LoadApp(AppRoot{ @@ -63,6 +68,13 @@ func Load(cfg config.Config) { Screens: cfg.RootScreen, Data: cfg.RootData, }) + + // 加密密钥函数 + gou.LoadCrypt(fmt.Sprintf(`{"key":"%s"}`, cfg.Database.AESKey), "AES") + gou.LoadCrypt(`{}`, "PASSWORD") + + // 设定已加载配置 + Conf = cfg } // Reload 根据配置重新加载 API, FLow, Model, Plugin @@ -74,6 +86,41 @@ func Reload(cfg config.Config) { Load(cfg) } +// DBConnect 建立数据库连接 +func DBConnect(dbconfig config.DatabaseConfig) { + + // 连接主库 + for i, dsn := range dbconfig.Primary { + db := capsule.AddConn("primary", dbconfig.Driver, dsn) + if i == 0 { + db.SetAsGlobal() + } + } + + // 连接从库 + for _, dsn := range dbconfig.Secondary { + capsule.AddReadConn("secondary", dbconfig.Driver, dsn) + } +} + +// AppInit 应用初始化 +func AppInit(cfg config.Config) { + + if _, err := os.Stat(cfg.RootUI); os.IsNotExist(err) { + err := os.MkdirAll(cfg.RootUI, os.ModePerm) + if err != nil { + log.Panicf("创建目录失败(%s) %s", cfg.RootUI, err) + } + } + + if _, err := os.Stat(cfg.RootDB); os.IsNotExist(err) { + err := os.MkdirAll(cfg.RootDB, os.ModePerm) + if err != nil { + log.Panicf("创建目录失败(%s) %s", cfg.RootDB, err) + } + } +} + // LoadAppInfo 读取应用信息 func LoadAppInfo(root string) { info := defaultAppInfo() diff --git a/global/vars.go b/global/vars.go index 000242b4..a4562cfa 100644 --- a/global/vars.go +++ b/global/vars.go @@ -1,14 +1,11 @@ package global import ( - "fmt" "net/http" "strings" - "github.com/yaoapp/gou" "github.com/yaoapp/xiang/config" "github.com/yaoapp/xiang/data" - "github.com/yaoapp/xun/capsule" ) // VERSION 版本号 @@ -42,18 +39,4 @@ func init() { } AllowHosts = append(AllowHosts, domain) } - - Conf = config.Conf - - // 数据库连接 - if len(Conf.Database.Primary) > 0 { - capsule.AddConn("primary", "mysql", Conf.Database.Primary[0]).SetAsGlobal() - } - - // 加密密钥 - gou.LoadCrypt(fmt.Sprintf(`{"key":"%s"}`, Conf.Database.AESKey), "AES") - gou.LoadCrypt(`{}`, "PASSWORD") - - // 加载数据 - Load(Conf) } diff --git a/go.mod b/go.mod index f4cb5e63..8c3e851c 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/gin-gonic/gin v1.7.4 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/hashicorp/go-hclog v1.0.0 // indirect github.com/hashicorp/go-plugin v1.4.3 // indirect github.com/hashicorp/yamux v0.0.0-20210826001029-26ff87cf9493 // indirect github.com/jmoiron/sqlx v1.3.4 // indirect @@ -21,18 +22,18 @@ require ( github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-sqlite3 v1.14.8 // indirect github.com/mojocn/base64Captcha v1.3.5 // indirect - github.com/robertkrimen/otto v0.0.0-20210927222213-f9375a256948 // indirect + github.com/robertkrimen/otto v0.0.0-20211004134430-12a632260352 // indirect github.com/spf13/afero v1.6.0 // indirect github.com/spf13/cobra v1.2.1 // indirect github.com/stretchr/testify v1.7.0 - github.com/yaoapp/gou v0.0.0-20211003110813-8a100940e019 // indirect + github.com/yaoapp/gou v0.0.0-20211007044811-e0834e575aa0 // indirect github.com/yaoapp/kun v0.6.7 - github.com/yaoapp/xun v0.5.2 // indirect + github.com/yaoapp/xun v0.6.0 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect - golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 // indirect - golang.org/x/sys v0.0.0-20211002104244-808efd93c36d // indirect - google.golang.org/genproto v0.0.0-20211001223012-bfb93cce50d9 // indirect + golang.org/x/net v0.0.0-20211006190231-62292e806868 // indirect + golang.org/x/sys v0.0.0-20211006225509-1a26e0398eed // indirect + google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e // indirect google.golang.org/grpc v1.41.0 // indirect ) diff --git a/go.sum b/go.sum index 70ba9918..a090e2ce 100644 --- a/go.sum +++ b/go.sum @@ -192,6 +192,8 @@ github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.0.0 h1:bkKf0BeBXcSYa7f5Fyi9gMuQ8gNsxeiNpZjR6VxNZeo= +github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= @@ -318,6 +320,8 @@ github.com/robertkrimen/otto v0.0.0-20210614181706-373ff5438452 h1:ewTtJ72GFy2e0 github.com/robertkrimen/otto v0.0.0-20210614181706-373ff5438452/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY= github.com/robertkrimen/otto v0.0.0-20210927222213-f9375a256948 h1:JgBmCxzPLP5ldSfEsVYhMUlJ7gQsOeBIPZOOeUdTTU8= github.com/robertkrimen/otto v0.0.0-20210927222213-f9375a256948/go.mod h1:/mK7FZ3mFYEn9zvNPhpngTyatyehSwte5bJZ4ehL5Xw= +github.com/robertkrimen/otto v0.0.0-20211004134430-12a632260352 h1:hqx3srlCjXphJgUFQqfo41HrWvZuYvMM9WEkb3oBgi0= +github.com/robertkrimen/otto v0.0.0-20211004134430-12a632260352/go.mod h1:/mK7FZ3mFYEn9zvNPhpngTyatyehSwte5bJZ4ehL5Xw= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -388,6 +392,8 @@ github.com/yaoapp/gou v0.0.0-20211001101736-7de3f97a840a h1:E4eybsoNhNrfKzmnjH5z github.com/yaoapp/gou v0.0.0-20211001101736-7de3f97a840a/go.mod h1:vcNZXFRgGuZWzjtYH65ck1o6nzWYDpToQ09zHC9xNDE= github.com/yaoapp/gou v0.0.0-20211003110813-8a100940e019 h1:ufa7z9jiqvD+t8yYN1oj8xz+YNiLzxGhhRkIu9aoWeE= github.com/yaoapp/gou v0.0.0-20211003110813-8a100940e019/go.mod h1:vcNZXFRgGuZWzjtYH65ck1o6nzWYDpToQ09zHC9xNDE= +github.com/yaoapp/gou v0.0.0-20211007044811-e0834e575aa0 h1:LyMs1aDbBAShEqHT7HrR+0gVqJjq2vxaqB7W/aNujPM= +github.com/yaoapp/gou v0.0.0-20211007044811-e0834e575aa0/go.mod h1:rLXQyNCz8z8fGCyr4NDZ2OFn9/CYdUVvM0RFMdKRSYo= github.com/yaoapp/kun v0.6.1 h1:gbjP5wmAuJLe1RGZ2evH4rPCVWykf0iqbksaHikF/GI= github.com/yaoapp/kun v0.6.1/go.mod h1:igsTcWDnzpp0HtRN7sBP+XOEN2tzoC5hk2MyoPFs3xA= github.com/yaoapp/kun v0.6.2 h1:QbtdZpVIklRDGEvL5YYRf/eR05YFZVFk/8rX2vy2K0Q= @@ -404,11 +410,14 @@ github.com/yaoapp/kun v0.6.7 h1:OgdArT+RLC6KI4LV1mpPFZLQijIQ/PdMP7S76NCn+BY= github.com/yaoapp/kun v0.6.7/go.mod h1:igsTcWDnzpp0HtRN7sBP+XOEN2tzoC5hk2MyoPFs3xA= github.com/yaoapp/xun v0.5.2 h1:DedZ26FpcXfkLnPKXzJsrbVmpWDRx9adUo8AvOcNT+g= github.com/yaoapp/xun v0.5.2/go.mod h1:y107NMHO635nhqJxMt582i1iqLjnNxAoeYr5/500UBw= +github.com/yaoapp/xun v0.6.0 h1:U8SBDv0OVkPWsJ2A7Y1TurTZQpxSeB1slR6ryaFKgdo= +github.com/yaoapp/xun v0.6.0/go.mod h1:SCJhBxU8AN4EIBZY5AkQI02JqtCe+HAOxHMl6BVhNQQ= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= @@ -511,6 +520,7 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d h1:LO7XpTYMwTqxjLcGWPijK3vRXg1aWdlNOVOHRq45d7c= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210913180222-943fd674d43e h1:+b/22bPvDYt4NPDcy4xAGCmON713ONAWFeY3Z7I3tR8= @@ -521,6 +531,8 @@ golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7 golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6 h1:Z04ewVs7JhXaYkmDhBERPi41gnltfQpMWDnTnQbaCqk= golang.org/x/net v0.0.0-20210929193557-e81a3d93ecf6/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211006190231-62292e806868 h1:KlOXYy8wQWTUJYFgkUI40Lzr06ofg5IRXUK5C7qZt1k= +golang.org/x/net v0.0.0-20211006190231-62292e806868/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -593,6 +605,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b h1:3Dq0eVHn0uaQJmPO+/aYPI/fRMqdrVDbu7MQcku54gg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -608,6 +621,9 @@ golang.org/x/sys v0.0.0-20211001092434-39dca1131b70 h1:pGleJoyD1yA5HfvuaksHxD040 golang.org/x/sys v0.0.0-20211001092434-39dca1131b70/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211002104244-808efd93c36d h1:SABT8Vei3iTiu+Gy8KOzpSNz+W1EQ5YBCRtiEETxF+0= golang.org/x/sys v0.0.0-20211002104244-808efd93c36d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211004093028-2c5d950f24ef/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211006225509-1a26e0398eed h1:E159xujlywdAeN3FqsTBPzRKGUq/pDHolXbuttkC36E= +golang.org/x/sys v0.0.0-20211006225509-1a26e0398eed/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -674,6 +690,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -761,6 +778,8 @@ google.golang.org/genproto v0.0.0-20210930144712-2e2e1008e8a3 h1:+F3FcO6LTrzNq5w google.golang.org/genproto v0.0.0-20210930144712-2e2e1008e8a3/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211001223012-bfb93cce50d9 h1:eF1wcrhdz56Vugf8qNX5dD93ItkrhothojQyHXqloe0= google.golang.org/genproto v0.0.0-20211001223012-bfb93cce50d9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e h1:Im71rbA1N3CbIag/PumYhQcNR8bLNmuOtRIyOnnLsT8= +google.golang.org/genproto v0.0.0-20211005153810-c76a74d43a8e/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= diff --git a/main_test.go b/main_test.go index 98dee2ba..f1f2413a 100644 --- a/main_test.go +++ b/main_test.go @@ -13,6 +13,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/yaoapp/kun/any" "github.com/yaoapp/kun/maps" + "github.com/yaoapp/kun/utils" + "github.com/yaoapp/xiang/config" "github.com/yaoapp/xiang/global" ) @@ -41,6 +43,7 @@ func TestCommandStart(t *testing.T) { defer func() { os.Args = oldArgs global.ServiceStop(func() {}) + log.Println("服务已关闭") }() go func() { os.Args = append(os.Args, "start") @@ -49,8 +52,8 @@ func TestCommandStart(t *testing.T) { // 发送请求 request := func() (maps.MapStr, error) { - time.Sleep(time.Microsecond * 1000) - url := fmt.Sprintf("http://%s:%d/api/user/find/1?select=id,name", "local.iqka.com", global.Conf.Service.Port) + time.Sleep(time.Microsecond * 2000) + url := fmt.Sprintf("http://%s:%d/api/user/find/1?select=id,name", "local.iqka.com", config.Conf.Service.Port) // utils.Dump(url) resp, err := http.Get(url) if err != nil { @@ -94,9 +97,9 @@ func TestCommandStop(t *testing.T) { // 发送请求 request := func() (maps.MapStr, error) { - time.Sleep(time.Microsecond * 1000) - url := fmt.Sprintf("http://%s:%d/api/user/find/1?select=id,name", "local.iqka.com", global.Conf.Service.Port) - // utils.Dump(url) + time.Sleep(time.Microsecond * 2000) + url := fmt.Sprintf("http://%s:%d/api/user/find/1?select=id,name", "local.iqka.com", config.Conf.Service.Port) + utils.Dump(url) resp, err := http.Get(url) if err != nil { return nil, err @@ -124,7 +127,7 @@ func TestCommandStop(t *testing.T) { // 测试关闭 global.ServiceStop(func() { log.Println("服务已关闭") }) - time.Sleep(time.Second * 1) + time.Sleep(time.Second * 2) _, err = request() assert.NotNil(t, err) return diff --git a/xlog/xlog.go b/xlog/xlog.go index a0054960..1b6b1a3b 100644 --- a/xlog/xlog.go +++ b/xlog/xlog.go @@ -27,3 +27,8 @@ func Printf(format string, v ...interface{}) { func Println(v ...interface{}) { log.Output(2, fmt.Sprintln(v...)) } + +// Fatalf is equivalent to Printf() followed by a call to os.Exit(1). +func Fatalf(format string, v ...interface{}) { + log.Fatalf(format, v...) +}