diff --git a/cmd/web.go b/cmd/web.go
index 0f57d91..5e275a9 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -1,194 +1,192 @@
package cmd
import (
- "github.com/ouqiang/gocron/modules/app"
- "github.com/ouqiang/gocron/routers"
- "github.com/urfave/cli"
- "gopkg.in/macaron.v1"
- "os"
- "os/signal"
- "syscall"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/ouqiang/gocron/service"
- "github.com/ouqiang/gocron/models"
- "github.com/ouqiang/gocron/modules/setting"
- "time"
- "github.com/ouqiang/gocron/modules/rpc/grpcpool"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/app"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/rpc/grpcpool"
+ "github.com/ouqiang/gocron/modules/setting"
+ "github.com/ouqiang/gocron/routers"
+ "github.com/ouqiang/gocron/service"
+ "github.com/urfave/cli"
+ "gopkg.in/macaron.v1"
+ "os"
+ "os/signal"
+ "syscall"
+ "time"
)
// web服务器默认端口
const DefaultPort = 5920
-
var CmdWeb = cli.Command{
- Name: "web",
- Usage: "run web server",
- Action: runWeb,
- Flags: []cli.Flag{
- cli.StringFlag{
- Name: "host",
- Value: "0.0.0.0",
- Usage: "bind host",
- },
- cli.IntFlag{
- Name: "port,p",
- Value: DefaultPort,
- Usage: "bind port",
- },
- cli.StringFlag{
- Name: "env,e",
- Value: "prod",
- Usage: "runtime environment, dev|test|prod",
- },
- },
+ Name: "web",
+ Usage: "run web server",
+ Action: runWeb,
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "host",
+ Value: "0.0.0.0",
+ Usage: "bind host",
+ },
+ cli.IntFlag{
+ Name: "port,p",
+ Value: DefaultPort,
+ Usage: "bind port",
+ },
+ cli.StringFlag{
+ Name: "env,e",
+ Value: "prod",
+ Usage: "runtime environment, dev|test|prod",
+ },
+ },
}
func runWeb(ctx *cli.Context) {
- // 设置运行环境
- setEnvironment(ctx)
- // 初始化应用
- app.InitEnv(ctx.App.Version)
- // 初始化模块 DB、定时任务等
- initModule()
- // 捕捉信号,配置热更新等
- go catchSignal()
- m := macaron.Classic()
+ // 设置运行环境
+ setEnvironment(ctx)
+ // 初始化应用
+ app.InitEnv(ctx.App.Version)
+ // 初始化模块 DB、定时任务等
+ initModule()
+ // 捕捉信号,配置热更新等
+ go catchSignal()
+ m := macaron.Classic()
- // 注册路由
- routers.Register(m)
- // 注册中间件.
- routers.RegisterMiddleware(m)
- host := parseHost(ctx)
- port := parsePort(ctx)
- m.Run(host, port)
+ // 注册路由
+ routers.Register(m)
+ // 注册中间件.
+ routers.RegisterMiddleware(m)
+ host := parseHost(ctx)
+ port := parsePort(ctx)
+ m.Run(host, port)
}
-func initModule() {
- if !app.Installed {
- return
- }
+func initModule() {
+ if !app.Installed {
+ return
+ }
- config, err := setting.Read(app.AppConfig)
- if err != nil {
- logger.Fatal("读取应用配置失败", err)
- }
- app.Setting = config
+ config, err := setting.Read(app.AppConfig)
+ if err != nil {
+ logger.Fatal("读取应用配置失败", err)
+ }
+ app.Setting = config
- // 初始化DB
- models.Db = models.CreateDb()
+ // 初始化DB
+ models.Db = models.CreateDb()
- // 版本升级
- upgradeIfNeed()
+ // 版本升级
+ upgradeIfNeed()
- // 初始化定时任务
- serviceTask := new(service.Task)
- serviceTask.Initialize()
+ // 初始化定时任务
+ serviceTask := new(service.Task)
+ serviceTask.Initialize()
}
// 解析端口
func parsePort(ctx *cli.Context) int {
- var port int = DefaultPort
- if ctx.IsSet("port") {
- port = ctx.Int("port")
- }
- if port <= 0 || port >= 65535 {
- port = DefaultPort
- }
+ var port int = DefaultPort
+ if ctx.IsSet("port") {
+ port = ctx.Int("port")
+ }
+ if port <= 0 || port >= 65535 {
+ port = DefaultPort
+ }
- return port
+ return port
}
-func parseHost(ctx *cli.Context) string {
- if ctx.IsSet("host") {
- return ctx.String("host")
- }
+func parseHost(ctx *cli.Context) string {
+ if ctx.IsSet("host") {
+ return ctx.String("host")
+ }
- return "0.0.0.0"
+ return "0.0.0.0"
}
-func setEnvironment(ctx *cli.Context) {
- var env string = "prod"
- if ctx.IsSet("env") {
- env = ctx.String("env")
- }
+func setEnvironment(ctx *cli.Context) {
+ var env string = "prod"
+ if ctx.IsSet("env") {
+ env = ctx.String("env")
+ }
- switch env {
- case "test":
- macaron.Env = macaron.TEST
- case "dev":
- macaron.Env = macaron.DEV
- default:
- macaron.Env = macaron.PROD
- }
+ switch env {
+ case "test":
+ macaron.Env = macaron.TEST
+ case "dev":
+ macaron.Env = macaron.DEV
+ default:
+ macaron.Env = macaron.PROD
+ }
}
// 捕捉信号
-func catchSignal() {
- c := make(chan os.Signal)
- // todo 配置热更新, windows 不支持 syscall.SIGUSR1, syscall.SIGUSR2
- signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
- for {
- s := <- c
- logger.Info("收到信号 -- ", s)
- switch s {
- case syscall.SIGHUP:
- logger.Info("收到终端断开信号, 忽略")
- case syscall.SIGINT, syscall.SIGTERM:
- shutdown()
- }
- }
+func catchSignal() {
+ c := make(chan os.Signal)
+ // todo 配置热更新, windows 不支持 syscall.SIGUSR1, syscall.SIGUSR2
+ signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
+ for {
+ s := <-c
+ logger.Info("收到信号 -- ", s)
+ switch s {
+ case syscall.SIGHUP:
+ logger.Info("收到终端断开信号, 忽略")
+ case syscall.SIGINT, syscall.SIGTERM:
+ shutdown()
+ }
+ }
}
-
// 应用退出
-func shutdown() {
- defer func() {
- logger.Info("已退出")
- os.Exit(0)
- }()
+func shutdown() {
+ defer func() {
+ logger.Info("已退出")
+ os.Exit(0)
+ }()
- if !app.Installed {
- return
- }
- logger.Info("应用准备退出")
- serviceTask := new(service.Task)
- // 停止所有任务调度
- logger.Info("停止定时任务调度")
- serviceTask.StopAll()
+ if !app.Installed {
+ return
+ }
+ logger.Info("应用准备退出")
+ serviceTask := new(service.Task)
+ // 停止所有任务调度
+ logger.Info("停止定时任务调度")
+ serviceTask.StopAll()
- taskNumInRunning := service.TaskNum.Num()
- logger.Infof("正在运行的任务有%d个", taskNumInRunning)
- if taskNumInRunning > 0 {
- logger.Info("等待所有任务执行完成后退出")
- }
- for {
- if taskNumInRunning <= 0 {
- break
- }
- time.Sleep(3 * time.Second)
- taskNumInRunning = service.TaskNum.Num()
- }
+ taskNumInRunning := service.TaskNum.Num()
+ logger.Infof("正在运行的任务有%d个", taskNumInRunning)
+ if taskNumInRunning > 0 {
+ logger.Info("等待所有任务执行完成后退出")
+ }
+ for {
+ if taskNumInRunning <= 0 {
+ break
+ }
+ time.Sleep(3 * time.Second)
+ taskNumInRunning = service.TaskNum.Num()
+ }
- // 释放gRPC连接池
- grpcpool.Pool.ReleaseAll()
+ // 释放gRPC连接池
+ grpcpool.Pool.ReleaseAll()
}
// 判断应用是否需要升级, 当存在版本号文件且版本小于app.VersionId时升级
-func upgradeIfNeed() {
- currentVersionId := app.GetCurrentVersionId()
- // 没有版本号文件
- if currentVersionId == 0 {
- return;
- }
- if currentVersionId >= app.VersionId {
- return
- }
+func upgradeIfNeed() {
+ currentVersionId := app.GetCurrentVersionId()
+ // 没有版本号文件
+ if currentVersionId == 0 {
+ return
+ }
+ if currentVersionId >= app.VersionId {
+ return
+ }
- migration := new(models.Migration)
- logger.Infof("版本升级开始, 当前版本号%d", currentVersionId)
+ migration := new(models.Migration)
+ logger.Infof("版本升级开始, 当前版本号%d", currentVersionId)
- migration.Upgrade(currentVersionId)
- app.UpdateVersionFile()
+ migration.Upgrade(currentVersionId)
+ app.UpdateVersionFile()
- logger.Infof("已升级到最新版本%d", app.VersionId)
-}
\ No newline at end of file
+ logger.Infof("已升级到最新版本%d", app.VersionId)
+}
diff --git a/gocron-node.go b/gocron-node.go
index 812317e..c751f0d 100644
--- a/gocron-node.go
+++ b/gocron-node.go
@@ -4,67 +4,65 @@
package main
import (
+ "flag"
+ "fmt"
+ "github.com/ouqiang/gocron/modules/rpc/auth"
"github.com/ouqiang/gocron/modules/rpc/server"
- "flag"
- "runtime"
- "os"
- "fmt"
- "strings"
- "github.com/ouqiang/gocron/modules/rpc/auth"
- "github.com/ouqiang/gocron/modules/utils"
+ "github.com/ouqiang/gocron/modules/utils"
+ "os"
+ "runtime"
+ "strings"
)
const AppVersion = "1.2.2"
-func main() {
+func main() {
var serverAddr string
- var allowRoot bool
- var version bool
- var CAFile string
- var certFile string
- var keyFile string
- var enableTLS bool
- flag.BoolVar(&allowRoot, "allow-root", false, "./gocron-node -allow-root")
- flag.StringVar(&serverAddr, "s", "0.0.0.0:5921", "./gocron-node -s ip:port")
- flag.BoolVar(&version, "v", false, "./gocron-node -v")
- flag.BoolVar(&enableTLS, "enable-tls", false, "./gocron-node -enable-tls")
- flag.StringVar(&CAFile, "ca-file", "", "./gocron-node -ca-file path")
- flag.StringVar(&certFile, "cert-file", "", "./gocron-node -cert-file path")
- flag.StringVar(&keyFile, "key-file", "", "./gocron-node -key-file path")
- flag.Parse()
+ var allowRoot bool
+ var version bool
+ var CAFile string
+ var certFile string
+ var keyFile string
+ var enableTLS bool
+ flag.BoolVar(&allowRoot, "allow-root", false, "./gocron-node -allow-root")
+ flag.StringVar(&serverAddr, "s", "0.0.0.0:5921", "./gocron-node -s ip:port")
+ flag.BoolVar(&version, "v", false, "./gocron-node -v")
+ flag.BoolVar(&enableTLS, "enable-tls", false, "./gocron-node -enable-tls")
+ flag.StringVar(&CAFile, "ca-file", "", "./gocron-node -ca-file path")
+ flag.StringVar(&certFile, "cert-file", "", "./gocron-node -cert-file path")
+ flag.StringVar(&keyFile, "key-file", "", "./gocron-node -key-file path")
+ flag.Parse()
- if version {
- fmt.Println(AppVersion)
- return
- }
+ if version {
+ fmt.Println(AppVersion)
+ return
+ }
- if (enableTLS) {
- if !utils.FileExist(CAFile) {
- fmt.Printf("failed to read ca cert file: %s", CAFile)
- return
- }
- if !utils.FileExist(certFile) {
- fmt.Printf("failed to read server cert file: %s", certFile)
- return
- }
- if !utils.FileExist(keyFile) {
- fmt.Printf("failed to read server key file: %s", keyFile)
- return
- }
- }
+ if enableTLS {
+ if !utils.FileExist(CAFile) {
+ fmt.Printf("failed to read ca cert file: %s", CAFile)
+ return
+ }
+ if !utils.FileExist(certFile) {
+ fmt.Printf("failed to read server cert file: %s", certFile)
+ return
+ }
+ if !utils.FileExist(keyFile) {
+ fmt.Printf("failed to read server key file: %s", keyFile)
+ return
+ }
+ }
- certificate := auth.Certificate{
- CAFile: strings.TrimSpace(CAFile),
- CertFile: strings.TrimSpace(certFile),
- KeyFile: strings.TrimSpace(keyFile),
- }
-
-
- if runtime.GOOS != "windows" && os.Getuid() == 0 && !allowRoot {
- fmt.Println("Do not run gocron-node as root user")
- return
- }
+ certificate := auth.Certificate{
+ CAFile: strings.TrimSpace(CAFile),
+ CertFile: strings.TrimSpace(certFile),
+ KeyFile: strings.TrimSpace(keyFile),
+ }
+ if runtime.GOOS != "windows" && os.Getuid() == 0 && !allowRoot {
+ fmt.Println("Do not run gocron-node as root user")
+ return
+ }
server.Start(serverAddr, enableTLS, certificate)
-}
\ No newline at end of file
+}
diff --git a/gocron.go b/gocron.go
index 2f29406..086797d 100644
--- a/gocron.go
+++ b/gocron.go
@@ -4,22 +4,22 @@
package main
import (
- "github.com/urfave/cli"
- "os"
+ "github.com/urfave/cli"
+ "os"
- "github.com/ouqiang/gocron/cmd"
+ "github.com/ouqiang/gocron/cmd"
)
const AppVersion = "1.2.2"
func main() {
- app := cli.NewApp()
- app.Name = "gocron"
- app.Usage = "gocron service"
- app.Version = AppVersion
- app.Commands = []cli.Command{
- cmd.CmdWeb,
- }
- app.Flags = append(app.Flags, []cli.Flag{}...)
- app.Run(os.Args)
+ app := cli.NewApp()
+ app.Name = "gocron"
+ app.Usage = "gocron service"
+ app.Version = AppVersion
+ app.Commands = []cli.Command{
+ cmd.CmdWeb,
+ }
+ app.Flags = append(app.Flags, []cli.Flag{}...)
+ app.Run(os.Args)
}
diff --git a/models/host.go b/models/host.go
index cd13247..ab0ad36 100644
--- a/models/host.go
+++ b/models/host.go
@@ -1,95 +1,94 @@
package models
import (
- "github.com/go-xorm/xorm"
+ "github.com/go-xorm/xorm"
)
// 主机
type Host struct {
- Id int16 `xorm:"smallint pk autoincr"`
- Name string `xorm:"varchar(64) notnull"` // 主机名称
- Alias string `xorm:"varchar(32) notnull default '' "` // 主机别名
- Port int `xorm:"notnull default 22"` // 主机端口
- Remark string `xorm:"varchar(100) notnull default '' "` // 备注
- BaseModel `xorm:"-"`
- Selected bool `xorm:"-"`
+ Id int16 `xorm:"smallint pk autoincr"`
+ Name string `xorm:"varchar(64) notnull"` // 主机名称
+ Alias string `xorm:"varchar(32) notnull default '' "` // 主机别名
+ Port int `xorm:"notnull default 22"` // 主机端口
+ Remark string `xorm:"varchar(100) notnull default '' "` // 备注
+ BaseModel `xorm:"-"`
+ Selected bool `xorm:"-"`
}
// 新增
func (host *Host) Create() (insertId int16, err error) {
- _, err = Db.Insert(host)
- if err == nil {
- insertId = host.Id
- }
+ _, err = Db.Insert(host)
+ if err == nil {
+ insertId = host.Id
+ }
- return
+ return
}
-func (host *Host) UpdateBean(id int16) (int64, error) {
- return Db.ID(id).Cols("name,alias,port,remark").Update(host)
+func (host *Host) UpdateBean(id int16) (int64, error) {
+ return Db.ID(id).Cols("name,alias,port,remark").Update(host)
}
-
// 更新
func (host *Host) Update(id int, data CommonMap) (int64, error) {
- return Db.Table(host).ID(id).Update(data)
+ return Db.Table(host).ID(id).Update(data)
}
// 删除
func (host *Host) Delete(id int) (int64, error) {
- return Db.Id(id).Delete(new(Host))
+ return Db.Id(id).Delete(new(Host))
}
func (host *Host) Find(id int) error {
- _, err := Db.Id(id).Get(host)
+ _, err := Db.Id(id).Get(host)
- return err
+ return err
}
-func (host *Host) NameExists(name string, id int16) (bool, error) {
- if id == 0 {
- count, err := Db.Where("name = ?", name).Count(host);
- return count > 0, err
- }
+func (host *Host) NameExists(name string, id int16) (bool, error) {
+ if id == 0 {
+ count, err := Db.Where("name = ?", name).Count(host)
+ return count > 0, err
+ }
- count, err := Db.Where("name = ? AND id != ?", name, id).Count(host);
- return count > 0, err
+ count, err := Db.Where("name = ? AND id != ?", name, id).Count(host)
+ return count > 0, err
}
func (host *Host) List(params CommonMap) ([]Host, error) {
- host.parsePageAndPageSize(params)
- list := make([]Host, 0)
- session := Db.Desc("id")
- host.parseWhere(session, params)
- err := session.Limit(host.PageSize, host.pageLimitOffset()).Find(&list)
+ host.parsePageAndPageSize(params)
+ list := make([]Host, 0)
+ session := Db.Desc("id")
+ host.parseWhere(session, params)
+ err := session.Limit(host.PageSize, host.pageLimitOffset()).Find(&list)
- return list, err
+ return list, err
}
func (host *Host) AllList() ([]Host, error) {
- list := make([]Host, 0)
- err := Db.Cols("name,port").Desc("id").Find(&list)
+ list := make([]Host, 0)
+ err := Db.Cols("name,port").Desc("id").Find(&list)
- return list, err
+ return list, err
}
func (host *Host) Total(params CommonMap) (int64, error) {
- session := Db.NewSession()
- host.parseWhere(session, params)
- return session.Count(host)
+ session := Db.NewSession()
+ host.parseWhere(session, params)
+ return session.Count(host)
}
// 解析where
-func (host *Host) parseWhere(session *xorm.Session, params CommonMap) {
- if len(params) == 0 {
- return
- }
- id, ok := params["Id"]
- if ok && id.(int) > 0 {
- session.And("id = ?", id)
- }
- name, ok := params["Name"]
- if ok && name.(string) != "" {
- session.And("name = ?", name)
- }
-}
\ No newline at end of file
+func (host *Host) parseWhere(session *xorm.Session, params CommonMap) {
+ if len(params) == 0 {
+ return
+ }
+ id, ok := params["Id"]
+ if ok && id.(int) > 0 {
+ session.And("id = ?", id)
+ }
+ name, ok := params["Name"]
+ if ok && name.(string) != "" {
+ session.And("name = ?", name)
+ }
+}
diff --git a/models/login_log.go b/models/login_log.go
index b86ade2..e4bf24e 100644
--- a/models/login_log.go
+++ b/models/login_log.go
@@ -1,36 +1,36 @@
package models
import (
- "time"
+ "time"
)
// 用户登录日志
type LoginLog struct {
- Id int `xorm:"pk autoincr notnull "`
- Username string `xorm:"varchar(32) notnull"`
- Ip string `xorm:"varchar(15) not null"`
- Created time.Time `xorm:"datetime notnull created"`
- BaseModel `xorm:"-"`
+ Id int `xorm:"pk autoincr notnull "`
+ Username string `xorm:"varchar(32) notnull"`
+ Ip string `xorm:"varchar(15) not null"`
+ Created time.Time `xorm:"datetime notnull created"`
+ BaseModel `xorm:"-"`
}
func (log *LoginLog) Create() (insertId int, err error) {
- _, err = Db.Insert(log)
- if err == nil {
- insertId = log.Id
- }
+ _, err = Db.Insert(log)
+ if err == nil {
+ insertId = log.Id
+ }
- return
+ return
}
func (log *LoginLog) List(params CommonMap) ([]LoginLog, error) {
- log.parsePageAndPageSize(params)
- list := make([]LoginLog, 0)
- err := Db.Desc("id").Limit(log.PageSize, log.pageLimitOffset()).Find(&list)
+ log.parsePageAndPageSize(params)
+ list := make([]LoginLog, 0)
+ err := Db.Desc("id").Limit(log.PageSize, log.pageLimitOffset()).Find(&list)
- return list, err
+ return list, err
}
func (log *LoginLog) Total() (int64, error) {
- return Db.Count(log)
-}
\ No newline at end of file
+ return Db.Count(log)
+}
diff --git a/models/migration.go b/models/migration.go
index 8d3999d..96b75e2 100644
--- a/models/migration.go
+++ b/models/migration.go
@@ -1,159 +1,157 @@
package models
import (
- "errors"
- "fmt"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/go-xorm/xorm"
- "strconv"
+ "errors"
+ "fmt"
+ "github.com/go-xorm/xorm"
+ "github.com/ouqiang/gocron/modules/logger"
+ "strconv"
)
-
type Migration struct{}
// 首次安装, 创建数据库表
func (migration *Migration) Install(dbName string) error {
- if !isDatabaseExist(dbName) {
- return errors.New("数据库不存在")
- }
- setting := new(Setting)
- task := new(Task)
- tables := []interface{}{
- &User{}, task, &TaskLog{}, &Host{}, setting,&LoginLog{},&TaskHost{},
- }
- for _, table := range tables {
- exist, err:= Db.IsTableExist(table)
- if exist {
- return errors.New("数据表已存在")
- }
- if err != nil {
- return err
- }
- err = Db.Sync2(table)
- if err != nil {
- return err
- }
- }
- setting.InitBasicField()
- task.CreateTestTask()
+ if !isDatabaseExist(dbName) {
+ return errors.New("数据库不存在")
+ }
+ setting := new(Setting)
+ task := new(Task)
+ tables := []interface{}{
+ &User{}, task, &TaskLog{}, &Host{}, setting, &LoginLog{}, &TaskHost{},
+ }
+ for _, table := range tables {
+ exist, err := Db.IsTableExist(table)
+ if exist {
+ return errors.New("数据表已存在")
+ }
+ if err != nil {
+ return err
+ }
+ err = Db.Sync2(table)
+ if err != nil {
+ return err
+ }
+ }
+ setting.InitBasicField()
+ task.CreateTestTask()
- return nil
+ return nil
}
// 判断数据库是否存在
func isDatabaseExist(name string) bool {
- _, err := Db.Exec("use ?", name)
+ _, err := Db.Exec("use ?", name)
- return err != nil
+ return err != nil
}
// 迭代升级数据库, 新建表、新增字段等
-func (migration *Migration) Upgrade(oldVersionId int) {
- // v1.2版本不支持升级
- if oldVersionId == 120 {
- return
- }
+func (migration *Migration) Upgrade(oldVersionId int) {
+ // v1.2版本不支持升级
+ if oldVersionId == 120 {
+ return
+ }
- versionIds := []int{110, 122}
- upgradeFuncs := []func(*xorm.Session) error {
- migration.upgradeFor110,
- migration.upgradeFor122,
- }
+ versionIds := []int{110, 122}
+ upgradeFuncs := []func(*xorm.Session) error{
+ migration.upgradeFor110,
+ migration.upgradeFor122,
+ }
- startIndex := -1
- // 从当前版本的下一版本开始升级
- for i, value := range versionIds {
- if value > oldVersionId {
- startIndex = i
- break;
- }
- }
+ startIndex := -1
+ // 从当前版本的下一版本开始升级
+ for i, value := range versionIds {
+ if value > oldVersionId {
+ startIndex = i
+ break
+ }
+ }
- if startIndex == -1 {
- return
- }
+ if startIndex == -1 {
+ return
+ }
- length := len(versionIds)
- if startIndex >= length {
- return
- }
+ length := len(versionIds)
+ if startIndex >= length {
+ return
+ }
- session := Db.NewSession()
- err := session.Begin()
- if err != nil {
- logger.Fatalf("开启事务失败-%s", err.Error())
- }
- for startIndex < length {
- err = upgradeFuncs[startIndex](session)
- if err == nil {
- startIndex++
- continue
- }
- dbErr := session.Rollback()
- if dbErr != nil {
- logger.Fatalf("事务回滚失败-%s",dbErr.Error())
- }
- logger.Fatal(err)
- }
- err = session.Commit()
- if err != nil {
- logger.Fatalf("提交事务失败-%s", err.Error())
- }
+ session := Db.NewSession()
+ err := session.Begin()
+ if err != nil {
+ logger.Fatalf("开启事务失败-%s", err.Error())
+ }
+ for startIndex < length {
+ err = upgradeFuncs[startIndex](session)
+ if err == nil {
+ startIndex++
+ continue
+ }
+ dbErr := session.Rollback()
+ if dbErr != nil {
+ logger.Fatalf("事务回滚失败-%s", dbErr.Error())
+ }
+ logger.Fatal(err)
+ }
+ err = session.Commit()
+ if err != nil {
+ logger.Fatalf("提交事务失败-%s", err.Error())
+ }
}
// 升级到v1.1版本
func (migration *Migration) upgradeFor110(session *xorm.Session) error {
- logger.Info("开始升级到v1.1")
- // 创建表task_host
- err := session.Sync2(new(TaskHost))
- if err != nil {
- return err
- }
+ logger.Info("开始升级到v1.1")
+ // 创建表task_host
+ err := session.Sync2(new(TaskHost))
+ if err != nil {
+ return err
+ }
- tableName := TablePrefix + "task"
- // 把task对应的host_id写入task_host表
- sql := fmt.Sprintf("SELECT id, host_id FROM %s WHERE host_id > 0", tableName)
- results, err := session.Query(sql)
- if err != nil {
- return err
- }
+ tableName := TablePrefix + "task"
+ // 把task对应的host_id写入task_host表
+ sql := fmt.Sprintf("SELECT id, host_id FROM %s WHERE host_id > 0", tableName)
+ results, err := session.Query(sql)
+ if err != nil {
+ return err
+ }
- for _, value := range results {
- taskHostModel := &TaskHost{}
- taskId, err := strconv.Atoi(string(value["id"]))
- if err != nil {
- return err
- }
- hostId, err := strconv.Atoi(string(value["host_id"]))
- if err != nil {
- return err
- }
- taskHostModel.TaskId = taskId
- taskHostModel.HostId = int16(hostId)
- _, err = session.Insert(taskHostModel)
- if err != nil {
- return err
- }
- }
+ for _, value := range results {
+ taskHostModel := &TaskHost{}
+ taskId, err := strconv.Atoi(string(value["id"]))
+ if err != nil {
+ return err
+ }
+ hostId, err := strconv.Atoi(string(value["host_id"]))
+ if err != nil {
+ return err
+ }
+ taskHostModel.TaskId = taskId
+ taskHostModel.HostId = int16(hostId)
+ _, err = session.Insert(taskHostModel)
+ if err != nil {
+ return err
+ }
+ }
+ // 删除task表host_id字段
+ _, err = session.Exec(fmt.Sprintf("ALTER TABLE %s DROP COLUMN host_id", tableName))
- // 删除task表host_id字段
- _, err = session.Exec(fmt.Sprintf("ALTER TABLE %s DROP COLUMN host_id", tableName))
+ logger.Info("已升级到v1.1\n")
- logger.Info("已升级到v1.1\n")
-
- return err
+ return err
}
// 升级到1.2.2版本
func (migration *Migration) upgradeFor122(session *xorm.Session) error {
- logger.Info("开始升级到v1.2.2")
+ logger.Info("开始升级到v1.2.2")
- tableName := TablePrefix + "task"
- // task表增加tag字段
- _, err := session.Exec(fmt.Sprintf("ALTER TABLE %s ADD COLUMN tag VARCHAR(32) NOT NULL DEFAULT '' ", tableName))
+ tableName := TablePrefix + "task"
+ // task表增加tag字段
+ _, err := session.Exec(fmt.Sprintf("ALTER TABLE %s ADD COLUMN tag VARCHAR(32) NOT NULL DEFAULT '' ", tableName))
- logger.Info("已升级到v1.2.2\n")
+ logger.Info("已升级到v1.2.2\n")
- return err
-}
\ No newline at end of file
+ return err
+}
diff --git a/models/model.go b/models/model.go
index 2ebc993..4b18b5d 100644
--- a/models/model.go
+++ b/models/model.go
@@ -1,16 +1,16 @@
package models
import (
- "fmt"
- _ "github.com/go-sql-driver/mysql"
- "github.com/go-xorm/core"
- "github.com/go-xorm/xorm"
- "gopkg.in/macaron.v1"
- "strings"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/ouqiang/gocron/modules/app"
- "time"
- "github.com/ouqiang/gocron/modules/setting"
+ "fmt"
+ _ "github.com/go-sql-driver/mysql"
+ "github.com/go-xorm/core"
+ "github.com/go-xorm/xorm"
+ "github.com/ouqiang/gocron/modules/app"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/setting"
+ "gopkg.in/macaron.v1"
+ "strings"
+ "time"
)
type Status int8
@@ -20,105 +20,105 @@ var TablePrefix string = ""
var Db *xorm.Engine
const (
- Disabled Status = 0 // 禁用
- Failure Status = 0 // 失败
- Enabled Status = 1 // 启用
- Running Status = 1 // 运行中
- Finish Status = 2 // 完成
- Cancel Status = 3 // 取消
- Waiting Status = 5 // 等待中
+ Disabled Status = 0 // 禁用
+ Failure Status = 0 // 失败
+ Enabled Status = 1 // 启用
+ Running Status = 1 // 运行中
+ Finish Status = 2 // 完成
+ Cancel Status = 3 // 取消
+ Waiting Status = 5 // 等待中
)
const (
- Page = 1 // 当前页数
- PageSize = 20 // 每页多少条数据
- MaxPageSize = 100000 // 每次最多取多少条
+ Page = 1 // 当前页数
+ PageSize = 20 // 每页多少条数据
+ MaxPageSize = 100000 // 每次最多取多少条
)
const DefaultTimeFormat = "2006-01-02 15:04:05"
-type BaseModel struct {
- Page int `xorm:"-"`
- PageSize int `xorm:"-"`
+type BaseModel struct {
+ Page int `xorm:"-"`
+ PageSize int `xorm:"-"`
}
func (model *BaseModel) parsePageAndPageSize(params CommonMap) {
- page, ok := params["Page"]
- if ok {
- model.Page = page.(int)
- }
- pageSize, ok := params["PageSize"]
- if ok {
- model.PageSize = pageSize.(int)
- }
- if model.Page <= 0 {
- model.Page = Page
- }
- if model.PageSize <= 0 {
- model.PageSize = MaxPageSize
- }
+ page, ok := params["Page"]
+ if ok {
+ model.Page = page.(int)
+ }
+ pageSize, ok := params["PageSize"]
+ if ok {
+ model.PageSize = pageSize.(int)
+ }
+ if model.Page <= 0 {
+ model.Page = Page
+ }
+ if model.PageSize <= 0 {
+ model.PageSize = MaxPageSize
+ }
}
func (model *BaseModel) pageLimitOffset() int {
- return (model.Page - 1) * model.PageSize
+ return (model.Page - 1) * model.PageSize
}
// 创建Db
func CreateDb() *xorm.Engine {
- dsn := getDbEngineDSN(app.Setting)
- engine, err := xorm.NewEngine(app.Setting.Db.Engine, dsn)
- if err != nil {
- logger.Fatal("创建xorm引擎失败", err)
- }
- engine.SetMaxIdleConns(app.Setting.Db.MaxIdleConns)
- engine.SetMaxOpenConns(app.Setting.Db.MaxOpenConns)
+ dsn := getDbEngineDSN(app.Setting)
+ engine, err := xorm.NewEngine(app.Setting.Db.Engine, dsn)
+ if err != nil {
+ logger.Fatal("创建xorm引擎失败", err)
+ }
+ engine.SetMaxIdleConns(app.Setting.Db.MaxIdleConns)
+ engine.SetMaxOpenConns(app.Setting.Db.MaxOpenConns)
- if app.Setting.Db.Prefix != "" {
- // 设置表前缀
- TablePrefix = app.Setting.Db.Prefix
- mapper := core.NewPrefixMapper(core.SnakeMapper{}, app.Setting.Db.Prefix)
- engine.SetTableMapper(mapper)
- }
- // 本地环境开启日志
- if macaron.Env == macaron.DEV {
- engine.ShowSQL(true)
- engine.Logger().SetLevel(core.LOG_DEBUG)
- }
+ if app.Setting.Db.Prefix != "" {
+ // 设置表前缀
+ TablePrefix = app.Setting.Db.Prefix
+ mapper := core.NewPrefixMapper(core.SnakeMapper{}, app.Setting.Db.Prefix)
+ engine.SetTableMapper(mapper)
+ }
+ // 本地环境开启日志
+ if macaron.Env == macaron.DEV {
+ engine.ShowSQL(true)
+ engine.Logger().SetLevel(core.LOG_DEBUG)
+ }
- go keepDbAlived(engine)
+ go keepDbAlived(engine)
- return engine
+ return engine
}
// 创建临时数据库连接
-func CreateTmpDb(setting *setting.Setting) (*xorm.Engine, error) {
- dsn := getDbEngineDSN(setting)
+func CreateTmpDb(setting *setting.Setting) (*xorm.Engine, error) {
+ dsn := getDbEngineDSN(setting)
- return xorm.NewEngine(setting.Db.Engine, dsn)
+ return xorm.NewEngine(setting.Db.Engine, dsn)
}
// 获取数据库引擎DSN mysql,sqlite
func getDbEngineDSN(setting *setting.Setting) string {
- engine := strings.ToLower(setting.Db.Engine)
- var dsn string = ""
- switch engine {
- case "mysql":
- dsn = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s",
- setting.Db.User,
- setting.Db.Password,
- setting.Db.Host,
- setting.Db.Port ,
- setting.Db.Database,
- setting.Db.Charset)
- }
+ engine := strings.ToLower(setting.Db.Engine)
+ var dsn string = ""
+ switch engine {
+ case "mysql":
+ dsn = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s",
+ setting.Db.User,
+ setting.Db.Password,
+ setting.Db.Host,
+ setting.Db.Port,
+ setting.Db.Database,
+ setting.Db.Charset)
+ }
- return dsn
+ return dsn
}
-func keepDbAlived(engine *xorm.Engine) {
- t := time.Tick(180 * time.Second)
- for {
- <- t
- engine.Ping()
- }
-}
\ No newline at end of file
+func keepDbAlived(engine *xorm.Engine) {
+ t := time.Tick(180 * time.Second)
+ for {
+ <-t
+ engine.Ping()
+ }
+}
diff --git a/models/setting.go b/models/setting.go
index 0007e0f..f34ea70 100644
--- a/models/setting.go
+++ b/models/setting.go
@@ -1,14 +1,14 @@
package models
import (
- "encoding/json"
+ "encoding/json"
)
-type Setting struct {
- Id int `xorm:"int pk autoincr"`
- Code string `xorm:"varchar(32) notnull"`
- Key string `xorm:"varchar(64) notnull"`
- Value string `xorm:"varchar(4096) notnull default '' "`
+type Setting struct {
+ Id int `xorm:"int pk autoincr"`
+ Code string `xorm:"varchar(32) notnull"`
+ Key string `xorm:"varchar(64) notnull"`
+ Value string `xorm:"varchar(4096) notnull default '' "`
}
const SlackCode = "slack"
@@ -21,154 +21,154 @@ const MailUserKey = "user"
// 初始化基本字段 邮件、slack等
func (setting *Setting) InitBasicField() {
- setting.Code = SlackCode;
- setting.Key = SlackUrlKey
- Db.Insert(setting)
+ setting.Code = SlackCode
+ setting.Key = SlackUrlKey
+ Db.Insert(setting)
- setting.Id = 0
- setting.Code = MailCode
- setting.Key = MailServerKey
- Db.Insert(setting)
+ setting.Id = 0
+ setting.Code = MailCode
+ setting.Key = MailServerKey
+ Db.Insert(setting)
}
// region slack配置
type Slack struct {
- Url string
- Channels []Channel
+ Url string
+ Channels []Channel
}
type Channel struct {
- Id int
- Name string
+ Id int
+ Name string
}
-func (setting *Setting) Slack() (Slack, error) {
- list := make([]Setting, 0)
- err := Db.Where("code = ?", SlackCode).Find(&list)
- slack := Slack{Url:"", Channels:make([]Channel, 0)}
- if err != nil {
- return slack, err
- }
+func (setting *Setting) Slack() (Slack, error) {
+ list := make([]Setting, 0)
+ err := Db.Where("code = ?", SlackCode).Find(&list)
+ slack := Slack{Url: "", Channels: make([]Channel, 0)}
+ if err != nil {
+ return slack, err
+ }
- setting.formatSlack(list, &slack)
+ setting.formatSlack(list, &slack)
- return slack, err
+ return slack, err
}
-func (setting *Setting) formatSlack(list []Setting, slack *Slack) {
- for _, v := range list {
- if v.Key == SlackUrlKey {
- slack.Url = v.Value
- continue
- }
+func (setting *Setting) formatSlack(list []Setting, slack *Slack) {
+ for _, v := range list {
+ if v.Key == SlackUrlKey {
+ slack.Url = v.Value
+ continue
+ }
- slack.Channels = append(slack.Channels, Channel{
- v.Id, v.Value,
- })
- }
+ slack.Channels = append(slack.Channels, Channel{
+ v.Id, v.Value,
+ })
+ }
}
// 更新slack webhook url
func (setting *Setting) UpdateSlackUrl(url string) (int64, error) {
- setting.Value = url
+ setting.Value = url
- return Db.Cols("value").Update(setting, Setting{Code:SlackCode, Key:SlackUrlKey})
+ return Db.Cols("value").Update(setting, Setting{Code: SlackCode, Key: SlackUrlKey})
}
-
// 创建slack渠道
func (setting *Setting) CreateChannel(channel string) (int64, error) {
- setting.Code = SlackCode
- setting.Key = SlackChannelKey
- setting.Value = channel
+ setting.Code = SlackCode
+ setting.Key = SlackChannelKey
+ setting.Value = channel
- return Db.Insert(setting)
+ return Db.Insert(setting)
}
-func (setting *Setting) IsChannelExist(channel string) (bool) {
- setting.Code = SlackCode
- setting.Key = SlackChannelKey
- setting.Value = channel
+func (setting *Setting) IsChannelExist(channel string) bool {
+ setting.Code = SlackCode
+ setting.Key = SlackChannelKey
+ setting.Value = channel
- count, _ := Db.Count(setting)
+ count, _ := Db.Count(setting)
- return count > 0
+ return count > 0
}
// 删除slack渠道
-func (setting *Setting) RemoveChannel(id int) (int64, error) {
- setting.Code = SlackCode
- setting.Key = SlackChannelKey
- setting.Id = id
- return Db.Delete(setting)
+func (setting *Setting) RemoveChannel(id int) (int64, error) {
+ setting.Code = SlackCode
+ setting.Key = SlackChannelKey
+ setting.Id = id
+ return Db.Delete(setting)
}
// endregion
type Mail struct {
- Host string
- Port int
- User string
- Password string
- MailUsers []MailUser
+ Host string
+ Port int
+ User string
+ Password string
+ MailUsers []MailUser
}
type MailUser struct {
- Id int
- Username string
- Email string
+ Id int
+ Username string
+ Email string
}
// region 邮件配置
-func (setting *Setting) Mail() (Mail, error) {
- list := make([]Setting, 0)
- err := Db.Where("code = ?", MailCode).Find(&list)
- mail := Mail{MailUsers:make([]MailUser, 0)}
- if err != nil {
- return mail, err
- }
+func (setting *Setting) Mail() (Mail, error) {
+ list := make([]Setting, 0)
+ err := Db.Where("code = ?", MailCode).Find(&list)
+ mail := Mail{MailUsers: make([]MailUser, 0)}
+ if err != nil {
+ return mail, err
+ }
- setting.formatMail(list, &mail)
+ setting.formatMail(list, &mail)
- return mail, err
+ return mail, err
}
-func (setting *Setting) formatMail(list []Setting, mail *Mail) {
- mailUser := MailUser{}
- for _, v := range list {
- if v.Key == MailServerKey {
- json.Unmarshal([]byte(v.Value), mail)
- continue
- }
- json.Unmarshal([]byte(v.Value), &mailUser)
- mailUser.Id = v.Id
- mail.MailUsers = append(mail.MailUsers, mailUser)
- }
+func (setting *Setting) formatMail(list []Setting, mail *Mail) {
+ mailUser := MailUser{}
+ for _, v := range list {
+ if v.Key == MailServerKey {
+ json.Unmarshal([]byte(v.Value), mail)
+ continue
+ }
+ json.Unmarshal([]byte(v.Value), &mailUser)
+ mailUser.Id = v.Id
+ mail.MailUsers = append(mail.MailUsers, mailUser)
+ }
}
-func (setting *Setting) UpdateMailServer(config string) (int64, error) {
- setting.Value = config
- return Db.Cols("value").Update(setting, Setting{Code:MailCode, Key:MailServerKey})
+func (setting *Setting) UpdateMailServer(config string) (int64, error) {
+ setting.Value = config
+ return Db.Cols("value").Update(setting, Setting{Code: MailCode, Key: MailServerKey})
}
func (setting *Setting) CreateMailUser(username, email string) (int64, error) {
- setting.Code = MailCode
- setting.Key = MailUserKey
- mailUser := MailUser{0, username, email}
- jsonByte, err := json.Marshal(mailUser)
- if err != nil {
- return 0, err
- }
- setting.Value = string(jsonByte)
+ setting.Code = MailCode
+ setting.Key = MailUserKey
+ mailUser := MailUser{0, username, email}
+ jsonByte, err := json.Marshal(mailUser)
+ if err != nil {
+ return 0, err
+ }
+ setting.Value = string(jsonByte)
- return Db.Insert(setting)
+ return Db.Insert(setting)
}
-func (setting *Setting) RemoveMailUser(id int) (int64, error) {
- setting.Code = MailCode
- setting.Key = MailUserKey
- setting.Id = id
- return Db.Delete(setting)
+func (setting *Setting) RemoveMailUser(id int) (int64, error) {
+ setting.Code = MailCode
+ setting.Key = MailUserKey
+ setting.Id = id
+ return Db.Delete(setting)
}
-// endregion
\ No newline at end of file
+
+// endregion
diff --git a/models/task.go b/models/task.go
index c2c62ee..dffdba2 100644
--- a/models/task.go
+++ b/models/task.go
@@ -1,272 +1,271 @@
package models
import (
- "time"
- "github.com/go-xorm/xorm"
- "errors"
- "strings"
+ "errors"
+ "github.com/go-xorm/xorm"
+ "strings"
+ "time"
)
type TaskProtocol int8
const (
- TaskHTTP TaskProtocol = iota + 1 // HTTP协议
- TaskRPC // RPC方式执行命令
+ TaskHTTP TaskProtocol = iota + 1 // HTTP协议
+ TaskRPC // RPC方式执行命令
)
type TaskLevel int8
const (
- TaskLevelParent TaskLevel = 1 // 父任务
- TaskLevelChild TaskLevel = 2 // 子任务(依赖任务)
+ TaskLevelParent TaskLevel = 1 // 父任务
+ TaskLevelChild TaskLevel = 2 // 子任务(依赖任务)
)
type TaskDependencyStatus int8
const (
- TaskDependencyStatusStrong TaskDependencyStatus = 1 // 强依赖
- TaskDependencyStatusWeak TaskDependencyStatus = 2 // 弱依赖
+ TaskDependencyStatusStrong TaskDependencyStatus = 1 // 强依赖
+ TaskDependencyStatusWeak TaskDependencyStatus = 2 // 弱依赖
)
// 任务
type Task struct {
- Id int `xorm:"int pk autoincr"`
- Name string `xorm:"varchar(32) notnull"` // 任务名称
- Level TaskLevel `xorm:"smallint notnull index default 1"` // 任务等级 1: 主任务 2: 依赖任务
- DependencyTaskId string `xorm:"varchar(64) notnull default ''"` // 依赖任务ID,多个ID逗号分隔
- DependencyStatus TaskDependencyStatus `xorm:"smallint notnull default 1"` // 依赖关系 1:强依赖 主任务执行成功, 依赖任务才会被执行 2:弱依赖
- Spec string `xorm:"varchar(64) notnull"` // crontab
- Protocol TaskProtocol `xorm:"tinyint notnull index"` // 协议 1:http 2:系统命令
- Command string `xorm:"varchar(256) notnull"` // URL地址或shell命令
- Timeout int `xorm:"mediumint notnull default 0"` // 任务执行超时时间(单位秒),0不限制
- Multi int8 `xorm:"tinyint notnull default 1"` // 是否允许多实例运行
- RetryTimes int8 `xorm:"tinyint notnull default 0"` // 重试次数
- NotifyStatus int8 `xorm:"smallint notnull default 1"` // 任务执行结束是否通知 0: 不通知 1: 失败通知 2: 执行结束通知
- NotifyType int8 `xorm:"smallint notnull default 0"` // 通知类型 1: 邮件 2: slack
- NotifyReceiverId string `xorm:"varchar(256) notnull default '' "` // 通知接受者ID, setting表主键ID,多个ID逗号分隔
- Tag string `xorm:"varchar(32) notnull default ''"`
- Remark string `xorm:"varchar(100) notnull default ''"` // 备注
- Status Status `xorm:"tinyint notnull index default 0"` // 状态 1:正常 0:停止
- Created time.Time `xorm:"datetime notnull created"` // 创建时间
- Deleted time.Time `xorm:"datetime deleted"` // 删除时间
- BaseModel `xorm:"-"`
- Hosts []TaskHostDetail `xorm:"-"`
+ Id int `xorm:"int pk autoincr"`
+ Name string `xorm:"varchar(32) notnull"` // 任务名称
+ Level TaskLevel `xorm:"smallint notnull index default 1"` // 任务等级 1: 主任务 2: 依赖任务
+ DependencyTaskId string `xorm:"varchar(64) notnull default ''"` // 依赖任务ID,多个ID逗号分隔
+ DependencyStatus TaskDependencyStatus `xorm:"smallint notnull default 1"` // 依赖关系 1:强依赖 主任务执行成功, 依赖任务才会被执行 2:弱依赖
+ Spec string `xorm:"varchar(64) notnull"` // crontab
+ Protocol TaskProtocol `xorm:"tinyint notnull index"` // 协议 1:http 2:系统命令
+ Command string `xorm:"varchar(256) notnull"` // URL地址或shell命令
+ Timeout int `xorm:"mediumint notnull default 0"` // 任务执行超时时间(单位秒),0不限制
+ Multi int8 `xorm:"tinyint notnull default 1"` // 是否允许多实例运行
+ RetryTimes int8 `xorm:"tinyint notnull default 0"` // 重试次数
+ NotifyStatus int8 `xorm:"smallint notnull default 1"` // 任务执行结束是否通知 0: 不通知 1: 失败通知 2: 执行结束通知
+ NotifyType int8 `xorm:"smallint notnull default 0"` // 通知类型 1: 邮件 2: slack
+ NotifyReceiverId string `xorm:"varchar(256) notnull default '' "` // 通知接受者ID, setting表主键ID,多个ID逗号分隔
+ Tag string `xorm:"varchar(32) notnull default ''"`
+ Remark string `xorm:"varchar(100) notnull default ''"` // 备注
+ Status Status `xorm:"tinyint notnull index default 0"` // 状态 1:正常 0:停止
+ Created time.Time `xorm:"datetime notnull created"` // 创建时间
+ Deleted time.Time `xorm:"datetime deleted"` // 删除时间
+ BaseModel `xorm:"-"`
+ Hosts []TaskHostDetail `xorm:"-"`
}
func taskHostTableName() []string {
- return []string{TablePrefix + "task_host", "th"}
+ return []string{TablePrefix + "task_host", "th"}
}
// 新增
func (task *Task) Create() (insertId int, err error) {
- _, err = Db.Insert(task)
- if err == nil {
- insertId = task.Id
- }
+ _, err = Db.Insert(task)
+ if err == nil {
+ insertId = task.Id
+ }
- return
+ return
}
// 新增测试任务
func (task *Task) CreateTestTask() {
- // HTTP任务
- task.Name = "测试HTTP任务"
- task.Level = TaskLevelParent
- task.Protocol = TaskHTTP
- task.Spec = "*/30 * * * * *"
- task.Tag = "test-task"
- // 查询IP地址区域信息
- task.Command = "http://ip.taobao.com/service/getIpInfo.php?ip=117.27.140.253"
- task.Status = Enabled
- task.Create()
+ // HTTP任务
+ task.Name = "测试HTTP任务"
+ task.Level = TaskLevelParent
+ task.Protocol = TaskHTTP
+ task.Spec = "*/30 * * * * *"
+ task.Tag = "test-task"
+ // 查询IP地址区域信息
+ task.Command = "http://ip.taobao.com/service/getIpInfo.php?ip=117.27.140.253"
+ task.Status = Enabled
+ task.Create()
}
-func (task *Task) UpdateBean(id int) (int64, error) {
- return Db.ID(id).
- Cols("name,spec,protocol,command,timeout,multi,retry_times,remark,notify_status,notify_type,notify_receiver_id, dependency_task_id, dependency_status, tag").
- Update(task)
+func (task *Task) UpdateBean(id int) (int64, error) {
+ return Db.ID(id).
+ Cols("name,spec,protocol,command,timeout,multi,retry_times,remark,notify_status,notify_type,notify_receiver_id, dependency_task_id, dependency_status, tag").
+ Update(task)
}
// 更新
func (task *Task) Update(id int, data CommonMap) (int64, error) {
- return Db.Table(task).ID(id).Update(data)
+ return Db.Table(task).ID(id).Update(data)
}
// 删除
func (task *Task) Delete(id int) (int64, error) {
- return Db.Id(id).Delete(task)
+ return Db.Id(id).Delete(task)
}
// 禁用
func (task *Task) Disable(id int) (int64, error) {
- return task.Update(id, CommonMap{"status": Disabled})
+ return task.Update(id, CommonMap{"status": Disabled})
}
// 激活
func (task *Task) Enable(id int) (int64, error) {
- return task.Update(id, CommonMap{"status": Enabled})
+ return task.Update(id, CommonMap{"status": Enabled})
}
// 获取所有激活任务
func (task *Task) ActiveList() ([]Task, error) {
- list := make([]Task, 0)
- err := Db.Where("status = ? AND level = ?", Enabled, TaskLevelParent).
- Find(&list)
+ list := make([]Task, 0)
+ err := Db.Where("status = ? AND level = ?", Enabled, TaskLevelParent).
+ Find(&list)
- if err != nil {
- return list, err
- }
+ if err != nil {
+ return list, err
+ }
- return task.setHostsForTasks(list)
+ return task.setHostsForTasks(list)
}
// 获取某个主机下的所有激活任务
func (task *Task) ActiveListByHostId(hostId int16) ([]Task, error) {
- taskHostModel := new(TaskHost)
- taskIds, err := taskHostModel.GetTaskIdsByHostId(hostId)
- if err != nil {
- return nil, err
- }
- list := make([]Task, 0)
- err = Db.Where("status = ? AND level = ?", Enabled, TaskLevelParent).
- In("id", taskIds...).
- Find(&list)
- if err != nil {
- return list, err
- }
+ taskHostModel := new(TaskHost)
+ taskIds, err := taskHostModel.GetTaskIdsByHostId(hostId)
+ if err != nil {
+ return nil, err
+ }
+ list := make([]Task, 0)
+ err = Db.Where("status = ? AND level = ?", Enabled, TaskLevelParent).
+ In("id", taskIds...).
+ Find(&list)
+ if err != nil {
+ return list, err
+ }
- return task.setHostsForTasks(list)
+ return task.setHostsForTasks(list)
}
func (task *Task) setHostsForTasks(tasks []Task) ([]Task, error) {
- taskHostModel := new(TaskHost)
- var err error
- for i, value := range tasks {
- taskHostDetails, err := taskHostModel.GetHostIdsByTaskId(value.Id)
- if err != nil {
- return nil, err
- }
- tasks[i].Hosts = taskHostDetails
- }
+ taskHostModel := new(TaskHost)
+ var err error
+ for i, value := range tasks {
+ taskHostDetails, err := taskHostModel.GetHostIdsByTaskId(value.Id)
+ if err != nil {
+ return nil, err
+ }
+ tasks[i].Hosts = taskHostDetails
+ }
- return tasks, err
+ return tasks, err
}
// 判断任务名称是否存在
-func (task *Task) NameExist(name string, id int) (bool, error) {
- if id > 0 {
- count, err := Db.Where("name = ? AND status = ? AND id != ?", name, Enabled, id).Count(task);
- return count > 0, err
- }
- count, err := Db.Where("name = ? AND status = ?", name, Enabled).Count(task);
+func (task *Task) NameExist(name string, id int) (bool, error) {
+ if id > 0 {
+ count, err := Db.Where("name = ? AND status = ? AND id != ?", name, Enabled, id).Count(task)
+ return count > 0, err
+ }
+ count, err := Db.Where("name = ? AND status = ?", name, Enabled).Count(task)
- return count > 0, err
+ return count > 0, err
}
func (task *Task) GetStatus(id int) (Status, error) {
- exist, err := Db.Id(id).Get(task)
- if err != nil {
- return 0, err
- }
- if !exist {
- return 0, errors.New("not exist")
- }
+ exist, err := Db.Id(id).Get(task)
+ if err != nil {
+ return 0, err
+ }
+ if !exist {
+ return 0, errors.New("not exist")
+ }
- return task.Status, nil
+ return task.Status, nil
}
-func(task *Task) Detail(id int) (Task, error) {
- t := Task{}
- _, err := Db.Where("id=?", id).Get(&t)
+func (task *Task) Detail(id int) (Task, error) {
+ t := Task{}
+ _, err := Db.Where("id=?", id).Get(&t)
- if err != nil {
- return t, err
- }
+ if err != nil {
+ return t, err
+ }
- taskHostModel := new(TaskHost)
- t.Hosts, err = taskHostModel.GetHostIdsByTaskId(id)
+ taskHostModel := new(TaskHost)
+ t.Hosts, err = taskHostModel.GetHostIdsByTaskId(id)
- return t, err
+ return t, err
}
func (task *Task) List(params CommonMap) ([]Task, error) {
- task.parsePageAndPageSize(params)
- list := make([]Task, 0)
- session := Db.Alias("t").Join("LEFT", taskHostTableName(), "t.id = th.task_id")
- task.parseWhere(session, params)
- err := session.GroupBy("t.id").Desc("t.id").Cols("t.*").Limit(task.PageSize, task.pageLimitOffset()).Find(&list)
+ task.parsePageAndPageSize(params)
+ list := make([]Task, 0)
+ session := Db.Alias("t").Join("LEFT", taskHostTableName(), "t.id = th.task_id")
+ task.parseWhere(session, params)
+ err := session.GroupBy("t.id").Desc("t.id").Cols("t.*").Limit(task.PageSize, task.pageLimitOffset()).Find(&list)
- if err != nil {
- return nil, err
- }
+ if err != nil {
+ return nil, err
+ }
- return task.setHostsForTasks(list)
+ return task.setHostsForTasks(list)
}
// 获取依赖任务列表
func (task *Task) GetDependencyTaskList(ids string) ([]Task, error) {
- list := make([]Task, 0)
- if ids == "" {
- return list, nil
- }
- idList := strings.Split(ids, ",")
- taskIds := make([]interface{}, len(idList))
- for i, v := range idList {
- taskIds[i] = v
- }
- fields := "t.*"
- err := Db.Alias("t").
- Where("t.level = ?", TaskLevelChild).
- In("t.id", taskIds).
- Cols(fields).
- Find(&list)
+ list := make([]Task, 0)
+ if ids == "" {
+ return list, nil
+ }
+ idList := strings.Split(ids, ",")
+ taskIds := make([]interface{}, len(idList))
+ for i, v := range idList {
+ taskIds[i] = v
+ }
+ fields := "t.*"
+ err := Db.Alias("t").
+ Where("t.level = ?", TaskLevelChild).
+ In("t.id", taskIds).
+ Cols(fields).
+ Find(&list)
- if err != nil {
- return list, err
- }
+ if err != nil {
+ return list, err
+ }
- return task.setHostsForTasks(list)
+ return task.setHostsForTasks(list)
}
func (task *Task) Total(params CommonMap) (int64, error) {
- session := Db.Alias("t").Join("LEFT", taskHostTableName(), "t.id = th.task_id")
- task.parseWhere(session, params)
- list := make([]Task, 0)
+ session := Db.Alias("t").Join("LEFT", taskHostTableName(), "t.id = th.task_id")
+ task.parseWhere(session, params)
+ list := make([]Task, 0)
- err := session.GroupBy("t.id").Find(&list)
+ err := session.GroupBy("t.id").Find(&list)
- return int64(len(list)), err
+ return int64(len(list)), err
}
// 解析where
-func (task *Task) parseWhere(session *xorm.Session, params CommonMap) {
- if len(params) == 0 {
- return
- }
- id, ok := params["Id"]
- if ok && id.(int) > 0 {
- session.And("t.id = ?", id)
- }
- hostId, ok := params["HostId"]
- if ok && hostId.(int) > 0 {
- session.And("th.host_id = ?", hostId)
- }
- name, ok := params["Name"]
- if ok && name.(string) != "" {
- session.And("t.name LIKE ?", "%" + name.(string) + "%")
- }
- protocol, ok := params["Protocol"]
- if ok && protocol.(int) > 0 {
- session.And("protocol = ?", protocol)
- }
- status, ok := params["Status"]
- if ok && status.(int) > -1 {
- session.And("status = ?", status)
- }
+func (task *Task) parseWhere(session *xorm.Session, params CommonMap) {
+ if len(params) == 0 {
+ return
+ }
+ id, ok := params["Id"]
+ if ok && id.(int) > 0 {
+ session.And("t.id = ?", id)
+ }
+ hostId, ok := params["HostId"]
+ if ok && hostId.(int) > 0 {
+ session.And("th.host_id = ?", hostId)
+ }
+ name, ok := params["Name"]
+ if ok && name.(string) != "" {
+ session.And("t.name LIKE ?", "%"+name.(string)+"%")
+ }
+ protocol, ok := params["Protocol"]
+ if ok && protocol.(int) > 0 {
+ session.And("protocol = ?", protocol)
+ }
+ status, ok := params["Status"]
+ if ok && status.(int) > -1 {
+ session.And("status = ?", status)
+ }
- tag, ok := params["Tag"]
- if ok && tag.(string) != "" {
- session.And("tag = ? ", tag)
- }
+ tag, ok := params["Tag"]
+ if ok && tag.(string) != "" {
+ session.And("tag = ? ", tag)
+ }
}
-
diff --git a/models/task_host.go b/models/task_host.go
index 5d1015d..c812160 100644
--- a/models/task_host.go
+++ b/models/task_host.go
@@ -1,81 +1,80 @@
package models
-
type TaskHost struct {
- Id int `xorm:"int pk autoincr"`
- TaskId int `xorm:"int not null index"`
- HostId int16 `xorm:"smallint not null index"`
+ Id int `xorm:"int pk autoincr"`
+ TaskId int `xorm:"int not null index"`
+ HostId int16 `xorm:"smallint not null index"`
}
type TaskHostDetail struct {
- TaskHost `xorm:"extends"`
- Name string
- Port int
- Alias string
+ TaskHost `xorm:"extends"`
+ Name string
+ Port int
+ Alias string
}
-func (TaskHostDetail) TableName() string {
- return TablePrefix + "task_host"
+func (TaskHostDetail) TableName() string {
+ return TablePrefix + "task_host"
}
func hostTableName() []string {
- return []string{TablePrefix + "host", "h"}
+ return []string{TablePrefix + "host", "h"}
}
func (th *TaskHost) Remove(taskId int) error {
- _, err := Db.Where("task_id = ?", taskId).Delete(new(TaskHost))
+ _, err := Db.Where("task_id = ?", taskId).Delete(new(TaskHost))
- return err
+ return err
}
func (th *TaskHost) Add(taskId int, hostIds []int) error {
- err := th.Remove(taskId)
- if err != nil {
- return err
- }
+ err := th.Remove(taskId)
+ if err != nil {
+ return err
+ }
- taskHosts := make([]TaskHost, len(hostIds))
- for i, value := range hostIds {
- taskHosts[i].TaskId = taskId
- taskHosts[i].HostId = int16(value)
- }
+ taskHosts := make([]TaskHost, len(hostIds))
+ for i, value := range hostIds {
+ taskHosts[i].TaskId = taskId
+ taskHosts[i].HostId = int16(value)
+ }
- _, err = Db.Insert(&taskHosts)
+ _, err = Db.Insert(&taskHosts)
- return err
+ return err
}
func (th *TaskHost) GetHostIdsByTaskId(taskId int) ([]TaskHostDetail, error) {
- list := make([]TaskHostDetail, 0)
- fields := "th.id,th.host_id,h.alias,h.name,h.port"
- err := Db.Alias("th").
- Join("LEFT", hostTableName(), "th.host_id=h.id").
- Where("th.task_id = ?", taskId).
- Cols(fields).
- Find(&list)
+ list := make([]TaskHostDetail, 0)
+ fields := "th.id,th.host_id,h.alias,h.name,h.port"
+ err := Db.Alias("th").
+ Join("LEFT", hostTableName(), "th.host_id=h.id").
+ Where("th.task_id = ?", taskId).
+ Cols(fields).
+ Find(&list)
- return list, err
+ return list, err
}
-func (th *TaskHost) GetTaskIdsByHostId(hostId int16) ([]interface{}, error) {
- list := make([]TaskHost, 0)
- err := Db.Where("host_id = ?", hostId).Cols("task_id").Find(&list)
- if err != nil {
- return nil, err
- }
+func (th *TaskHost) GetTaskIdsByHostId(hostId int16) ([]interface{}, error) {
+ list := make([]TaskHost, 0)
+ err := Db.Where("host_id = ?", hostId).Cols("task_id").Find(&list)
+ if err != nil {
+ return nil, err
+ }
- taskIds := make([]interface{}, len(list))
- for i, value := range list {
- taskIds[i] = value.TaskId
- }
+ taskIds := make([]interface{}, len(list))
+ for i, value := range list {
+ taskIds[i] = value.TaskId
+ }
- return taskIds, err
+ return taskIds, err
}
// 判断主机id是否有引用
func (th *TaskHost) HostIdExist(hostId int16) (bool, error) {
- count, err := Db.Where("host_id = ?", hostId).Count(th);
+ count, err := Db.Where("host_id = ?", hostId).Count(th)
- return count > 0, err
-}
\ No newline at end of file
+ return count > 0, err
+}
diff --git a/models/task_log.go b/models/task_log.go
index 47db18c..e38c059 100644
--- a/models/task_log.go
+++ b/models/task_log.go
@@ -1,99 +1,98 @@
package models
import (
- "time"
- "github.com/go-xorm/xorm"
+ "github.com/go-xorm/xorm"
+ "time"
)
type TaskType int8
-
// 任务执行日志
type TaskLog struct {
- Id int64 `xorm:"bigint pk autoincr"`
- TaskId int `xorm:"int notnull index default 0"` // 任务id
- Name string `xorm:"varchar(32) notnull"` // 任务名称
- Spec string `xorm:"varchar(64) notnull"` // crontab
- Protocol TaskProtocol `xorm:"tinyint notnull index"` // 协议 1:http 2:RPC
- Command string `xorm:"varchar(256) notnull"` // URL地址或shell命令
- Timeout int `xorm:"mediumint notnull default 0"` // 任务执行超时时间(单位秒),0不限制
- RetryTimes int8 `xorm:"tinyint notnull default 0"` // 任务重试次数
- Hostname string `xorm:"varchar(128) notnull defalut '' "` // RPC主机名,逗号分隔
- StartTime time.Time `xorm:"datetime created"` // 开始执行时间
- EndTime time.Time `xorm:"datetime updated"` // 执行完成(失败)时间
- Status Status `xorm:"tinyint notnull index default 1"` // 状态 0:执行失败 1:执行中 2:执行完毕 3:任务取消(上次任务未执行完成) 4:异步执行
- Result string `xorm:"mediumtext notnull defalut '' "` // 执行结果
- TotalTime int `xorm:"-"` // 执行总时长
- BaseModel `xorm:"-"`
+ Id int64 `xorm:"bigint pk autoincr"`
+ TaskId int `xorm:"int notnull index default 0"` // 任务id
+ Name string `xorm:"varchar(32) notnull"` // 任务名称
+ Spec string `xorm:"varchar(64) notnull"` // crontab
+ Protocol TaskProtocol `xorm:"tinyint notnull index"` // 协议 1:http 2:RPC
+ Command string `xorm:"varchar(256) notnull"` // URL地址或shell命令
+ Timeout int `xorm:"mediumint notnull default 0"` // 任务执行超时时间(单位秒),0不限制
+ RetryTimes int8 `xorm:"tinyint notnull default 0"` // 任务重试次数
+ Hostname string `xorm:"varchar(128) notnull defalut '' "` // RPC主机名,逗号分隔
+ StartTime time.Time `xorm:"datetime created"` // 开始执行时间
+ EndTime time.Time `xorm:"datetime updated"` // 执行完成(失败)时间
+ Status Status `xorm:"tinyint notnull index default 1"` // 状态 0:执行失败 1:执行中 2:执行完毕 3:任务取消(上次任务未执行完成) 4:异步执行
+ Result string `xorm:"mediumtext notnull defalut '' "` // 执行结果
+ TotalTime int `xorm:"-"` // 执行总时长
+ BaseModel `xorm:"-"`
}
func (taskLog *TaskLog) Create() (insertId int64, err error) {
- _, err = Db.Insert(taskLog)
- if err == nil {
- insertId = taskLog.Id
- }
+ _, err = Db.Insert(taskLog)
+ if err == nil {
+ insertId = taskLog.Id
+ }
- return
+ return
}
// 更新
func (taskLog *TaskLog) Update(id int64, data CommonMap) (int64, error) {
- return Db.Table(taskLog).ID(id).Update(data)
+ return Db.Table(taskLog).ID(id).Update(data)
}
func (taskLog *TaskLog) List(params CommonMap) ([]TaskLog, error) {
- taskLog.parsePageAndPageSize(params)
- list := make([]TaskLog, 0)
- session := Db.Desc("id")
- taskLog.parseWhere(session, params)
- err := session.Limit(taskLog.PageSize, taskLog.pageLimitOffset()).Find(&list)
- if len(list) > 0 {
- for i, item := range list {
- endTime := item.EndTime
- if item.Status == Running {
- endTime = time.Now()
- }
- execSeconds := endTime.Sub(item.StartTime).Seconds()
- list[i].TotalTime = int(execSeconds)
- }
- }
+ taskLog.parsePageAndPageSize(params)
+ list := make([]TaskLog, 0)
+ session := Db.Desc("id")
+ taskLog.parseWhere(session, params)
+ err := session.Limit(taskLog.PageSize, taskLog.pageLimitOffset()).Find(&list)
+ if len(list) > 0 {
+ for i, item := range list {
+ endTime := item.EndTime
+ if item.Status == Running {
+ endTime = time.Now()
+ }
+ execSeconds := endTime.Sub(item.StartTime).Seconds()
+ list[i].TotalTime = int(execSeconds)
+ }
+ }
- return list, err
+ return list, err
}
// 清空表
-func (taskLog *TaskLog) Clear() (int64, error) {
- return Db.Where("1=1").Delete(taskLog);
+func (taskLog *TaskLog) Clear() (int64, error) {
+ return Db.Where("1=1").Delete(taskLog)
}
// 删除N个月前的日志
func (taskLog *TaskLog) Remove(id int) (int64, error) {
- t := time.Now().AddDate(0, -id, 0)
- return Db.Where("start_time <= ?", t.Format(DefaultTimeFormat)).Delete(taskLog)
+ t := time.Now().AddDate(0, -id, 0)
+ return Db.Where("start_time <= ?", t.Format(DefaultTimeFormat)).Delete(taskLog)
}
func (taskLog *TaskLog) Total(params CommonMap) (int64, error) {
- session := Db.NewSession()
- defer session.Close()
- taskLog.parseWhere(session, params)
- return session.Count(taskLog)
+ session := Db.NewSession()
+ defer session.Close()
+ taskLog.parseWhere(session, params)
+ return session.Count(taskLog)
}
// 解析where
-func (taskLog *TaskLog) parseWhere(session *xorm.Session, params CommonMap) {
- if len(params) == 0 {
- return
- }
- taskId, ok := params["TaskId"]
- if ok && taskId.(int) > 0 {
- session.And("task_id = ?", taskId)
- }
- protocol, ok := params["Protocol"]
- if ok && protocol.(int) > 0 {
- session.And("protocol = ?", protocol)
- }
- status, ok := params["Status"]
- if ok && status.(int) > -1 {
- session.And("status = ?", status)
- }
-}
\ No newline at end of file
+func (taskLog *TaskLog) parseWhere(session *xorm.Session, params CommonMap) {
+ if len(params) == 0 {
+ return
+ }
+ taskId, ok := params["TaskId"]
+ if ok && taskId.(int) > 0 {
+ session.And("task_id = ?", taskId)
+ }
+ protocol, ok := params["Protocol"]
+ if ok && protocol.(int) > 0 {
+ session.And("protocol = ?", protocol)
+ }
+ status, ok := params["Status"]
+ if ok && status.(int) > -1 {
+ session.And("status = ?", status)
+ }
+}
diff --git a/models/user.go b/models/user.go
index 64dd24a..00f8703 100644
--- a/models/user.go
+++ b/models/user.go
@@ -1,110 +1,110 @@
package models
import (
- "github.com/ouqiang/gocron/modules/utils"
- "time"
+ "github.com/ouqiang/gocron/modules/utils"
+ "time"
)
const PasswordSaltLength = 6
// 用户model
type User struct {
- Id int `xorm:"pk autoincr notnull "`
- Name string `xorm:"varchar(32) notnull unique"` // 用户名
- Password string `xorm:"char(32) notnull "` // 密码
- Salt string `xorm:"char(6) notnull "` // 密码盐值
- Email string `xorm:"varchar(50) notnull unique default '' "` // 邮箱
- Created time.Time `xorm:"datetime notnull created"`
- Updated time.Time `xorm:"datetime updated"`
- Deleted time.Time `xorm:"datetime deleted"`
- IsAdmin int8 `xorm:"tinyint notnull default 0"` // 是否是管理员 1:管理员 0:普通用户
- Status Status `xorm:"tinyint notnull default 1"` // 1: 正常 0:禁用
- BaseModel `xorm:"-"`
+ Id int `xorm:"pk autoincr notnull "`
+ Name string `xorm:"varchar(32) notnull unique"` // 用户名
+ Password string `xorm:"char(32) notnull "` // 密码
+ Salt string `xorm:"char(6) notnull "` // 密码盐值
+ Email string `xorm:"varchar(50) notnull unique default '' "` // 邮箱
+ Created time.Time `xorm:"datetime notnull created"`
+ Updated time.Time `xorm:"datetime updated"`
+ Deleted time.Time `xorm:"datetime deleted"`
+ IsAdmin int8 `xorm:"tinyint notnull default 0"` // 是否是管理员 1:管理员 0:普通用户
+ Status Status `xorm:"tinyint notnull default 1"` // 1: 正常 0:禁用
+ BaseModel `xorm:"-"`
}
// 新增
func (user *User) Create() (insertId int, err error) {
- user.Status = Enabled
- user.Salt = user.generateSalt()
- user.Password = user.encryptPassword(user.Password, user.Salt)
+ user.Status = Enabled
+ user.Salt = user.generateSalt()
+ user.Password = user.encryptPassword(user.Password, user.Salt)
- _, err = Db.Insert(user)
- if err == nil {
- insertId = user.Id
- }
+ _, err = Db.Insert(user)
+ if err == nil {
+ insertId = user.Id
+ }
- return
+ return
}
// 更新
func (user *User) Update(id int, data CommonMap) (int64, error) {
- return Db.Table(user).ID(id).Update(data)
+ return Db.Table(user).ID(id).Update(data)
}
-func (user *User) UpdatePassword(id int, password string) (int64, error) {
- salt := user.generateSalt()
- safePassword := user.encryptPassword(password, salt)
+func (user *User) UpdatePassword(id int, password string) (int64, error) {
+ salt := user.generateSalt()
+ safePassword := user.encryptPassword(password, salt)
- return user.Update(id, CommonMap{"password": safePassword, "salt": salt})
+ return user.Update(id, CommonMap{"password": safePassword, "salt": salt})
}
// 删除
func (user *User) Delete(id int) (int64, error) {
- return Db.Id(id).Delete(user)
+ return Db.Id(id).Delete(user)
}
// 禁用
func (user *User) Disable(id int) (int64, error) {
- return user.Update(id, CommonMap{"status": Disabled})
+ return user.Update(id, CommonMap{"status": Disabled})
}
// 激活
func (user *User) Enable(id int) (int64, error) {
- return user.Update(id, CommonMap{"status": Enabled})
+ return user.Update(id, CommonMap{"status": Enabled})
}
// 验证用户名和密码
func (user *User) Match(username, password string) bool {
- where := "(name = ? OR email = ?)"
- _, err := Db.Where(where, username, username).Get(user)
- if err != nil {
- return false
- }
- hashPassword := user.encryptPassword(password, user.Salt)
- if hashPassword != user.Password {
- return false
- }
+ where := "(name = ? OR email = ?)"
+ _, err := Db.Where(where, username, username).Get(user)
+ if err != nil {
+ return false
+ }
+ hashPassword := user.encryptPassword(password, user.Salt)
+ if hashPassword != user.Password {
+ return false
+ }
- return true
+ return true
}
// 用户名是否存在
func (user *User) UsernameExists(username string) (int64, error) {
- return Db.Where("name = ?", username).Count(user)
+ return Db.Where("name = ?", username).Count(user)
}
// 邮箱地址是否存在
func (user *User) EmailExists(email string) (int64, error) {
- return Db.Where("email = ?", email).Count(user)
+ return Db.Where("email = ?", email).Count(user)
}
func (user *User) List() ([]User, error) {
- list := make([]User, 0)
- err := Db.Desc("id").Find(&list)
+ list := make([]User, 0)
+ err := Db.Desc("id").Find(&list)
- return list, err
+ return list, err
}
func (user *User) Total() (int64, error) {
- return Db.Count(user)
+ return Db.Count(user)
}
// 密码加密
func (user *User) encryptPassword(password, salt string) string {
- return utils.Md5(password + salt)
+ return utils.Md5(password + salt)
}
// 生成密码盐值
func (user *User) generateSalt() string {
- return utils.RandString(PasswordSaltLength)
+ return utils.RandString(PasswordSaltLength)
}
diff --git a/modules/app/app.go b/modules/app/app.go
index f1df384..1af491a 100644
--- a/modules/app/app.go
+++ b/modules/app/app.go
@@ -1,117 +1,116 @@
package app
import (
- "os"
+ "os"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/ouqiang/gocron/modules/utils"
- "io/ioutil"
- "strconv"
- "strings"
- "github.com/ouqiang/gocron/modules/setting"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/setting"
+ "github.com/ouqiang/gocron/modules/utils"
+ "io/ioutil"
+ "strconv"
+ "strings"
)
var (
- AppDir string // 应用根目录
- ConfDir string // 配置目录
- LogDir string // 日志目录
- DataDir string // 存放session等
- AppConfig string // 应用配置文件
- Installed bool // 应用是否安装过
- Setting *setting.Setting // 应用配置
- VersionId int // 版本号
- VersionFile string // 版本号文件
+ AppDir string // 应用根目录
+ ConfDir string // 配置目录
+ LogDir string // 日志目录
+ DataDir string // 存放session等
+ AppConfig string // 应用配置文件
+ Installed bool // 应用是否安装过
+ Setting *setting.Setting // 应用配置
+ VersionId int // 版本号
+ VersionFile string // 版本号文件
)
-
func InitEnv(versionString string) {
- logger.InitLogger()
- wd, err := os.Getwd()
- if err != nil {
- logger.Fatal(err)
- }
- AppDir = wd
- ConfDir = AppDir + "/conf"
- LogDir = AppDir + "/log"
- DataDir = AppDir + "/data"
- AppConfig = ConfDir + "/app.ini"
- VersionFile = ConfDir + "/.version"
- checkDirExists(ConfDir, LogDir, DataDir)
- Installed = IsInstalled()
- VersionId = ToNumberVersion(versionString)
+ logger.InitLogger()
+ wd, err := os.Getwd()
+ if err != nil {
+ logger.Fatal(err)
+ }
+ AppDir = wd
+ ConfDir = AppDir + "/conf"
+ LogDir = AppDir + "/log"
+ DataDir = AppDir + "/data"
+ AppConfig = ConfDir + "/app.ini"
+ VersionFile = ConfDir + "/.version"
+ checkDirExists(ConfDir, LogDir, DataDir)
+ Installed = IsInstalled()
+ VersionId = ToNumberVersion(versionString)
}
// 判断应用是否已安装
func IsInstalled() bool {
- _, err := os.Stat(ConfDir + "/install.lock")
- if os.IsNotExist(err) {
- return false
- }
+ _, err := os.Stat(ConfDir + "/install.lock")
+ if os.IsNotExist(err) {
+ return false
+ }
- return true
+ return true
}
// 创建安装锁文件
func CreateInstallLock() error {
- _, err := os.Create(ConfDir + "/install.lock")
- if err != nil {
- logger.Error("创建安装锁文件conf/install.lock失败")
- }
+ _, err := os.Create(ConfDir + "/install.lock")
+ if err != nil {
+ logger.Error("创建安装锁文件conf/install.lock失败")
+ }
- return err
+ return err
}
// 更新应用版本号文件
-func UpdateVersionFile() {
- err := ioutil.WriteFile(VersionFile,
- []byte(strconv.Itoa(VersionId)),
- 0644,
- )
+func UpdateVersionFile() {
+ err := ioutil.WriteFile(VersionFile,
+ []byte(strconv.Itoa(VersionId)),
+ 0644,
+ )
- if err != nil {
- logger.Fatal(err)
- }
+ if err != nil {
+ logger.Fatal(err)
+ }
}
// 获取应用当前版本号, 从版本号文件中读取
func GetCurrentVersionId() int {
- if !utils.FileExist(VersionFile) {
- return 0;
- }
+ if !utils.FileExist(VersionFile) {
+ return 0
+ }
- bytes, err := ioutil.ReadFile(VersionFile)
- if err != nil {
- logger.Fatal(err)
- }
+ bytes, err := ioutil.ReadFile(VersionFile)
+ if err != nil {
+ logger.Fatal(err)
+ }
- versionId, err := strconv.Atoi(strings.TrimSpace(string(bytes)))
- if err != nil {
- logger.Fatal(err)
- }
+ versionId, err := strconv.Atoi(strings.TrimSpace(string(bytes)))
+ if err != nil {
+ logger.Fatal(err)
+ }
- return versionId
+ return versionId
}
// 把字符串版本号a.b.c转换为整数版本号abc
-func ToNumberVersion(versionString string) int {
- v := strings.Replace(versionString, ".", "", -1)
- if len(v) < 3 {
- v += "0"
- }
+func ToNumberVersion(versionString string) int {
+ v := strings.Replace(versionString, ".", "", -1)
+ if len(v) < 3 {
+ v += "0"
+ }
- versionId, err := strconv.Atoi(v)
- if err != nil {
- logger.Fatal(err)
- }
+ versionId, err := strconv.Atoi(v)
+ if err != nil {
+ logger.Fatal(err)
+ }
- return versionId
+ return versionId
}
// 检测目录是否存在
func checkDirExists(path ...string) {
- for _, value := range path {
- if !utils.FileExist(value) {
- logger.Fatal(value + "目录不存在或无权限访问")
- }
- }
-}
\ No newline at end of file
+ for _, value := range path {
+ if !utils.FileExist(value) {
+ logger.Fatal(value + "目录不存在或无权限访问")
+ }
+ }
+}
diff --git a/modules/httpclient/http_client.go b/modules/httpclient/http_client.go
index 36d5c19..29f4334 100644
--- a/modules/httpclient/http_client.go
+++ b/modules/httpclient/http_client.go
@@ -3,81 +3,81 @@ package httpclient
// http-client
import (
- "io/ioutil"
- "net/http"
- "time"
- "fmt"
- "bytes"
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "time"
)
-type ResponseWrapper struct {
- StatusCode int
- Body string
- Header http.Header
+type ResponseWrapper struct {
+ StatusCode int
+ Body string
+ Header http.Header
}
func Get(url string, timeout int) ResponseWrapper {
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return createRequestError(err)
- }
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return createRequestError(err)
+ }
- return request(req, timeout)
+ return request(req, timeout)
}
-func PostParams(url string,params string, timeout int) ResponseWrapper {
- buf := bytes.NewBufferString(params)
- req, err := http.NewRequest("POST", url, buf)
- if err != nil {
- return createRequestError(err)
- }
- req.Header.Set("Content-type", "application/x-www-form-urlencoded")
+func PostParams(url string, params string, timeout int) ResponseWrapper {
+ buf := bytes.NewBufferString(params)
+ req, err := http.NewRequest("POST", url, buf)
+ if err != nil {
+ return createRequestError(err)
+ }
+ req.Header.Set("Content-type", "application/x-www-form-urlencoded")
- return request(req, timeout)
+ return request(req, timeout)
}
func PostJson(url string, body string, timeout int) ResponseWrapper {
- buf := bytes.NewBufferString(body)
- req, err := http.NewRequest("POST", url, buf)
- if err != nil {
- return createRequestError(err)
- }
- req.Header.Set("Content-type", "application/json")
+ buf := bytes.NewBufferString(body)
+ req, err := http.NewRequest("POST", url, buf)
+ if err != nil {
+ return createRequestError(err)
+ }
+ req.Header.Set("Content-type", "application/json")
- return request(req, timeout)
+ return request(req, timeout)
}
func request(req *http.Request, timeout int) ResponseWrapper {
- wrapper := ResponseWrapper{StatusCode: 0, Body: "", Header: make(http.Header)}
- client := &http.Client{}
- if timeout > 0 {
- client.Timeout = time.Duration(timeout) * time.Second
- }
- setRequestHeader(req)
- resp, err := client.Do(req)
- if err != nil {
- wrapper.Body = fmt.Sprintf("执行HTTP请求错误-%s", err.Error())
- return wrapper
- }
- defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- wrapper.Body = fmt.Sprintf("读取HTTP请求返回值失败-%s", err.Error())
- return wrapper
- }
- wrapper.StatusCode = resp.StatusCode
- wrapper.Body = string(body)
- wrapper.Header = resp.Header
+ wrapper := ResponseWrapper{StatusCode: 0, Body: "", Header: make(http.Header)}
+ client := &http.Client{}
+ if timeout > 0 {
+ client.Timeout = time.Duration(timeout) * time.Second
+ }
+ setRequestHeader(req)
+ resp, err := client.Do(req)
+ if err != nil {
+ wrapper.Body = fmt.Sprintf("执行HTTP请求错误-%s", err.Error())
+ return wrapper
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ wrapper.Body = fmt.Sprintf("读取HTTP请求返回值失败-%s", err.Error())
+ return wrapper
+ }
+ wrapper.StatusCode = resp.StatusCode
+ wrapper.Body = string(body)
+ wrapper.Header = resp.Header
- return wrapper
+ return wrapper
}
-func setRequestHeader(req *http.Request) {
- req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6")
- req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 golang/gocron")
+func setRequestHeader(req *http.Request) {
+ req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8,en;q=0.6")
+ req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 golang/gocron")
}
func createRequestError(err error) ResponseWrapper {
- errorMessage := fmt.Sprintf("创建HTTP请求错误-%s", err.Error())
- return ResponseWrapper{0, errorMessage, make(http.Header)}
-}
\ No newline at end of file
+ errorMessage := fmt.Sprintf("创建HTTP请求错误-%s", err.Error())
+ return ResponseWrapper{0, errorMessage, make(http.Header)}
+}
diff --git a/modules/logger/logger.go b/modules/logger/logger.go
index 04398b3..cf76940 100644
--- a/modules/logger/logger.go
+++ b/modules/logger/logger.go
@@ -1,11 +1,11 @@
package logger
import (
- "github.com/cihub/seelog"
- "gopkg.in/macaron.v1"
- "fmt"
- "os"
- "runtime"
+ "fmt"
+ "github.com/cihub/seelog"
+ "gopkg.in/macaron.v1"
+ "os"
+ "runtime"
)
// 日志库
@@ -22,113 +22,113 @@ const (
FATAL
)
-func InitLogger() {
- config := getLogConfig()
- l, err := seelog.LoggerFromConfigAsString(config)
- if err != nil {
- panic(err)
- }
- logger = l
+func InitLogger() {
+ config := getLogConfig()
+ l, err := seelog.LoggerFromConfigAsString(config)
+ if err != nil {
+ panic(err)
+ }
+ logger = l
}
func Debug(v ...interface{}) {
- if macaron.Env != macaron.DEV {
- return
- }
+ if macaron.Env != macaron.DEV {
+ return
+ }
write(DEBUG, v)
}
-func Debugf(format string, v ...interface{}) {
- if macaron.Env != macaron.DEV {
- return
- }
- writef(DEBUG, format, v...)
+func Debugf(format string, v ...interface{}) {
+ if macaron.Env != macaron.DEV {
+ return
+ }
+ writef(DEBUG, format, v...)
}
func Info(v ...interface{}) {
write(INFO, v)
}
-func Infof(format string, v ...interface{}) {
- writef(INFO, format, v...)
+func Infof(format string, v ...interface{}) {
+ writef(INFO, format, v...)
}
func Warn(v ...interface{}) {
write(WARN, v)
}
-func Warnf(format string, v ...interface{}) {
- writef(WARN, format, v...)
+func Warnf(format string, v ...interface{}) {
+ writef(WARN, format, v...)
}
func Error(v ...interface{}) {
write(ERROR, v)
}
-func Errorf(format string, v ...interface{}) {
- writef(ERROR, format, v...)
+func Errorf(format string, v ...interface{}) {
+ writef(ERROR, format, v...)
}
func Fatal(v ...interface{}) {
write(FATAL, v)
}
-func Fatalf(format string, v ...interface{}) {
- writef(FATAL, format, v...)
+func Fatalf(format string, v ...interface{}) {
+ writef(FATAL, format, v...)
}
func write(level Level, v ...interface{}) {
- defer logger.Flush()
+ defer logger.Flush()
- content := ""
- if macaron.Env == macaron.DEV {
- pc, file, line, ok := runtime.Caller(2)
- if ok {
- content = fmt.Sprintf("#%s#%s#%d行#", file, runtime.FuncForPC(pc).Name(), line)
- }
- }
+ content := ""
+ if macaron.Env == macaron.DEV {
+ pc, file, line, ok := runtime.Caller(2)
+ if ok {
+ content = fmt.Sprintf("#%s#%s#%d行#", file, runtime.FuncForPC(pc).Name(), line)
+ }
+ }
- switch level {
- case DEBUG:
- logger.Debug(content, v)
- case INFO:
- logger.Info(content, v)
- case WARN:
- logger.Warn(content, v)
- case FATAL:
- logger.Critical(content, v)
- os.Exit(1)
- case ERROR:
- logger.Error(content, v)
+ switch level {
+ case DEBUG:
+ logger.Debug(content, v)
+ case INFO:
+ logger.Info(content, v)
+ case WARN:
+ logger.Warn(content, v)
+ case FATAL:
+ logger.Critical(content, v)
+ os.Exit(1)
+ case ERROR:
+ logger.Error(content, v)
}
}
-func writef(level Level, format string, v ...interface{}) {
- defer logger.Flush()
+func writef(level Level, format string, v ...interface{}) {
+ defer logger.Flush()
- content := ""
- if macaron.Env == macaron.DEV {
- pc, file, line, ok := runtime.Caller(2)
- if ok {
- content = fmt.Sprintf("#%s#%s#%d行#", file, runtime.FuncForPC(pc).Name(), line)
- }
- }
+ content := ""
+ if macaron.Env == macaron.DEV {
+ pc, file, line, ok := runtime.Caller(2)
+ if ok {
+ content = fmt.Sprintf("#%s#%s#%d行#", file, runtime.FuncForPC(pc).Name(), line)
+ }
+ }
- format = content + format
+ format = content + format
- switch level {
- case DEBUG:
- logger.Debugf(format, v...)
- case INFO:
- logger.Infof(format, v...)
- case WARN:
- logger.Warnf(format, v...)
- case FATAL:
- logger.Criticalf(format, v...)
- os.Exit(1)
- case ERROR:
- logger.Errorf(format, v...)
- }
+ switch level {
+ case DEBUG:
+ logger.Debugf(format, v...)
+ case INFO:
+ logger.Infof(format, v...)
+ case WARN:
+ logger.Warnf(format, v...)
+ case FATAL:
+ logger.Criticalf(format, v...)
+ os.Exit(1)
+ case ERROR:
+ logger.Errorf(format, v...)
+ }
}
func getLogConfig() string {
@@ -145,16 +145,16 @@ func getLogConfig() string {
`
- consoleConfig := ""
- if macaron.Env == macaron.DEV {
- consoleConfig =
- `
+ consoleConfig := ""
+ if macaron.Env == macaron.DEV {
+ consoleConfig =
+ `
`
- }
- config = fmt.Sprintf(config, consoleConfig)
+ }
+ config = fmt.Sprintf(config, consoleConfig)
- return config
+ return config
}
diff --git a/modules/notify/mail.go b/modules/notify/mail.go
index f9ba373..aa3edd0 100644
--- a/modules/notify/mail.go
+++ b/modules/notify/mail.go
@@ -1,84 +1,82 @@
package notify
import (
- "github.com/ouqiang/gocron/models"
- "github.com/ouqiang/gocron/modules/logger"
- "strconv"
- "strings"
- "github.com/ouqiang/gocron/modules/utils"
- "time"
- "github.com/go-gomail/gomail"
+ "github.com/go-gomail/gomail"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/utils"
+ "strconv"
+ "strings"
+ "time"
)
// @author qiang.ou
// @date 2017/5/1-00:19
-
type Mail struct {
-
}
-func (mail *Mail) Send(msg Message) {
- model := new(models.Setting)
- mailSetting, err := model.Mail()
- logger.Debugf("%+v", mailSetting)
- if err != nil {
- logger.Error("#mail#从数据库获取mail配置失败", err)
- return
- }
- if mailSetting.Host == "" {
- logger.Error("#mail#Host为空")
- return
- }
- if mailSetting.Port == 0 {
- logger.Error("#mail#Port为空")
- return
- }
- if mailSetting.User == "" {
- logger.Error("#mail#User为空")
- return
- }
- if mailSetting.Password == "" {
- logger.Error("#mail#Password为空")
- return
- }
- toUsers := mail.getActiveMailUsers(mailSetting, msg)
- mail.send(mailSetting, toUsers, msg)
+func (mail *Mail) Send(msg Message) {
+ model := new(models.Setting)
+ mailSetting, err := model.Mail()
+ logger.Debugf("%+v", mailSetting)
+ if err != nil {
+ logger.Error("#mail#从数据库获取mail配置失败", err)
+ return
+ }
+ if mailSetting.Host == "" {
+ logger.Error("#mail#Host为空")
+ return
+ }
+ if mailSetting.Port == 0 {
+ logger.Error("#mail#Port为空")
+ return
+ }
+ if mailSetting.User == "" {
+ logger.Error("#mail#User为空")
+ return
+ }
+ if mailSetting.Password == "" {
+ logger.Error("#mail#Password为空")
+ return
+ }
+ toUsers := mail.getActiveMailUsers(mailSetting, msg)
+ mail.send(mailSetting, toUsers, msg)
}
-func (mail *Mail) send(mailSetting models.Mail, toUsers []string, msg Message) {
- body := msg["content"].(string)
- body = strings.Replace(body, "\n", "
", -1)
- gomailMessage := gomail.NewMessage()
- gomailMessage.SetHeader("From", mailSetting.User)
- gomailMessage.SetHeader("To", toUsers...)
- gomailMessage.SetHeader("Subject", "gocron-定时任务监控通知")
- gomailMessage.SetBody("text/html", body)
- mailer := gomail.NewPlainDialer(mailSetting.Host, mailSetting.Port,
- mailSetting.User, mailSetting.Password)
- maxTimes := 3
- i := 0
- for i < maxTimes {
- err := mailer.DialAndSend(gomailMessage)
- if err == nil {
- break;
- }
- i += 1
- time.Sleep(2 * time.Second)
- if i < maxTimes {
- logger.Errorf("mail#发送消息失败#%s#消息内容-%s", err.Error(), msg["content"])
- }
- }
+func (mail *Mail) send(mailSetting models.Mail, toUsers []string, msg Message) {
+ body := msg["content"].(string)
+ body = strings.Replace(body, "\n", "
", -1)
+ gomailMessage := gomail.NewMessage()
+ gomailMessage.SetHeader("From", mailSetting.User)
+ gomailMessage.SetHeader("To", toUsers...)
+ gomailMessage.SetHeader("Subject", "gocron-定时任务监控通知")
+ gomailMessage.SetBody("text/html", body)
+ mailer := gomail.NewPlainDialer(mailSetting.Host, mailSetting.Port,
+ mailSetting.User, mailSetting.Password)
+ maxTimes := 3
+ i := 0
+ for i < maxTimes {
+ err := mailer.DialAndSend(gomailMessage)
+ if err == nil {
+ break
+ }
+ i += 1
+ time.Sleep(2 * time.Second)
+ if i < maxTimes {
+ logger.Errorf("mail#发送消息失败#%s#消息内容-%s", err.Error(), msg["content"])
+ }
+ }
}
-func (mail *Mail) getActiveMailUsers(mailSetting models.Mail, msg Message) []string {
- taskReceiverIds := strings.Split(msg["task_receiver_id"].(string), ",")
- users := []string{}
- for _, v := range(mailSetting.MailUsers) {
- if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) {
- users = append(users, v.Email)
- }
- }
+func (mail *Mail) getActiveMailUsers(mailSetting models.Mail, msg Message) []string {
+ taskReceiverIds := strings.Split(msg["task_receiver_id"].(string), ",")
+ users := []string{}
+ for _, v := range mailSetting.MailUsers {
+ if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) {
+ users = append(users, v.Email)
+ }
+ }
- return users
-}
\ No newline at end of file
+ return users
+}
diff --git a/modules/notify/notify.go b/modules/notify/notify.go
index 00714f6..1e34ddf 100644
--- a/modules/notify/notify.go
+++ b/modules/notify/notify.go
@@ -1,52 +1,52 @@
package notify
import (
- "time"
- "github.com/ouqiang/gocron/modules/logger"
- "fmt"
+ "fmt"
+ "github.com/ouqiang/gocron/modules/logger"
+ "time"
)
type Message map[string]interface{}
type Notifiable interface {
- Send(msg Message)
+ Send(msg Message)
}
var queue chan Message = make(chan Message, 100)
-func init() {
- go run()
+func init() {
+ go run()
}
// 把消息推入队列
func Push(msg Message) {
- queue <- msg
+ queue <- msg
}
func run() {
- for msg := range queue {
- // 根据任务配置发送通知
- taskType, taskTypeOk := msg["task_type"]
- _, taskReceiverIdOk := msg["task_receiver_id"]
- _, nameOk := msg["name"]
- _, outputOk := msg["output"]
- _, statusOk := msg["status"]
- if !taskTypeOk || !taskReceiverIdOk || !nameOk || !outputOk || !statusOk {
- logger.Errorf("#notify#参数不完整#%+v", msg)
- continue
- }
- msg["content"] = fmt.Sprintf("============\n============\n============\n任务名称: %s\n状态: %s\n输出:\n %s\n", msg["name"], msg["status"], msg["output"])
- logger.Debugf("%+v", msg)
- switch(taskType.(int8)) {
- case 1:
- // 邮件
- mail := Mail{}
- go mail.Send(msg)
- case 2:
- // Slack
- slack := Slack{}
- go slack.Send(msg)
- }
- time.Sleep(1 * time.Second)
- }
-}
\ No newline at end of file
+ for msg := range queue {
+ // 根据任务配置发送通知
+ taskType, taskTypeOk := msg["task_type"]
+ _, taskReceiverIdOk := msg["task_receiver_id"]
+ _, nameOk := msg["name"]
+ _, outputOk := msg["output"]
+ _, statusOk := msg["status"]
+ if !taskTypeOk || !taskReceiverIdOk || !nameOk || !outputOk || !statusOk {
+ logger.Errorf("#notify#参数不完整#%+v", msg)
+ continue
+ }
+ msg["content"] = fmt.Sprintf("============\n============\n============\n任务名称: %s\n状态: %s\n输出:\n %s\n", msg["name"], msg["status"], msg["output"])
+ logger.Debugf("%+v", msg)
+ switch taskType.(int8) {
+ case 1:
+ // 邮件
+ mail := Mail{}
+ go mail.Send(msg)
+ case 2:
+ // Slack
+ slack := Slack{}
+ go slack.Send(msg)
+ }
+ time.Sleep(1 * time.Second)
+ }
+}
diff --git a/modules/notify/slack.go b/modules/notify/slack.go
index 6c5f8e8..d64d570 100644
--- a/modules/notify/slack.go
+++ b/modules/notify/slack.go
@@ -1,78 +1,79 @@
package notify
+
// 发送消息到slack
import (
- "fmt"
- "github.com/ouqiang/gocron/modules/httpclient"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/ouqiang/gocron/modules/utils"
- "strings"
- "github.com/ouqiang/gocron/models"
- "strconv"
- "time"
+ "fmt"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/httpclient"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/utils"
+ "strconv"
+ "strings"
+ "time"
)
-type Slack struct {}
+type Slack struct{}
-func (slack *Slack) Send(msg Message) {
- model := new(models.Setting)
- slackSetting, err := model.Slack()
- if err != nil {
- logger.Error("#slack#从数据库获取slack配置失败", err)
- return
- }
- if slackSetting.Url == "" {
- logger.Error("#slack#webhook-url为空")
- return
- }
- if len(slackSetting.Channels) == 0 {
- logger.Error("#slack#channels配置为空")
- return
- }
- logger.Debugf("%+v", slackSetting)
- channels := slack.getActiveSlackChannels(slackSetting, msg)
- logger.Debugf("%+v", channels)
- for _, channel := range(channels) {
- slack.send(msg, slackSetting.Url, channel)
- }
+func (slack *Slack) Send(msg Message) {
+ model := new(models.Setting)
+ slackSetting, err := model.Slack()
+ if err != nil {
+ logger.Error("#slack#从数据库获取slack配置失败", err)
+ return
+ }
+ if slackSetting.Url == "" {
+ logger.Error("#slack#webhook-url为空")
+ return
+ }
+ if len(slackSetting.Channels) == 0 {
+ logger.Error("#slack#channels配置为空")
+ return
+ }
+ logger.Debugf("%+v", slackSetting)
+ channels := slack.getActiveSlackChannels(slackSetting, msg)
+ logger.Debugf("%+v", channels)
+ for _, channel := range channels {
+ slack.send(msg, slackSetting.Url, channel)
+ }
}
-func (slack *Slack) send(msg Message, slackUrl string, channel string) {
- formatBody := slack.format(msg["content"].(string), channel)
- timeout := 30
- maxTimes := 3
- i := 0
- for i < maxTimes {
- resp := httpclient.PostJson(slackUrl, formatBody, timeout)
- if resp.StatusCode == 200 {
- break;
- }
- i += 1
- time.Sleep(2 * time.Second)
- if i < maxTimes {
- logger.Errorf("slack#发送消息失败#%s#消息内容-%s", resp.Body, msg["content"])
- }
- }
+func (slack *Slack) send(msg Message, slackUrl string, channel string) {
+ formatBody := slack.format(msg["content"].(string), channel)
+ timeout := 30
+ maxTimes := 3
+ i := 0
+ for i < maxTimes {
+ resp := httpclient.PostJson(slackUrl, formatBody, timeout)
+ if resp.StatusCode == 200 {
+ break
+ }
+ i += 1
+ time.Sleep(2 * time.Second)
+ if i < maxTimes {
+ logger.Errorf("slack#发送消息失败#%s#消息内容-%s", resp.Body, msg["content"])
+ }
+ }
}
-func (slack *Slack) getActiveSlackChannels(slackSetting models.Slack, msg Message) []string {
- taskReceiverIds := strings.Split(msg["task_receiver_id"].(string), ",")
- channels := []string{}
- for _, v := range(slackSetting.Channels) {
- if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) {
- channels = append(channels, v.Name)
- }
- }
+func (slack *Slack) getActiveSlackChannels(slackSetting models.Slack, msg Message) []string {
+ taskReceiverIds := strings.Split(msg["task_receiver_id"].(string), ",")
+ channels := []string{}
+ for _, v := range slackSetting.Channels {
+ if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) {
+ channels = append(channels, v.Name)
+ }
+ }
- return channels
+ return channels
}
// 格式化消息内容
-func (slack *Slack) format(content string, channel string) string {
- content = utils.EscapeJson(content)
- specialChars := []string{"&", "<", ">"}
- replaceChars := []string{"&", "<", ">"}
- content = utils.ReplaceStrings(content, specialChars, replaceChars)
+func (slack *Slack) format(content string, channel string) string {
+ content = utils.EscapeJson(content)
+ specialChars := []string{"&", "<", ">"}
+ replaceChars := []string{"&", "<", ">"}
+ content = utils.ReplaceStrings(content, specialChars, replaceChars)
- return fmt.Sprintf(`{"text":"%s","username":"监控", "channel":"%s"}`, content, channel)
-}
\ No newline at end of file
+ return fmt.Sprintf(`{"text":"%s","username":"监控", "channel":"%s"}`, content, channel)
+}
diff --git a/modules/rpc/auth/Certification.go b/modules/rpc/auth/Certification.go
index 767e109..7e41853 100644
--- a/modules/rpc/auth/Certification.go
+++ b/modules/rpc/auth/Certification.go
@@ -3,16 +3,16 @@ package auth
import (
"crypto/tls"
"crypto/x509"
- "io/ioutil"
"errors"
"fmt"
"google.golang.org/grpc/credentials"
+ "io/ioutil"
)
type Certificate struct {
- CAFile string
- CertFile string
- KeyFile string
+ CAFile string
+ CertFile string
+ KeyFile string
ServerName string
}
@@ -33,14 +33,12 @@ func (c Certificate) GetTLSConfigForServer() (*tls.Config, error) {
return nil, errors.New("failed to append client certs")
}
-
tlsConfig := &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{certificate},
ClientCAs: certPool,
}
-
return tlsConfig, nil
}
@@ -68,4 +66,4 @@ func (c Certificate) GetTransportCredsForClient() (credentials.TransportCredenti
})
return transportCreds, nil
-}
\ No newline at end of file
+}
diff --git a/modules/rpc/client/client.go b/modules/rpc/client/client.go
index 937459d..d6d1b51 100644
--- a/modules/rpc/client/client.go
+++ b/modules/rpc/client/client.go
@@ -1,80 +1,65 @@
package client
import (
- pb "github.com/ouqiang/gocron/modules/rpc/proto"
- "golang.org/x/net/context"
- "fmt"
- "time"
- "errors"
- "github.com/ouqiang/gocron/modules/rpc/grpcpool"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc"
- "github.com/ouqiang/gocron/modules/logger"
+ "errors"
+ "fmt"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/rpc/grpcpool"
+ pb "github.com/ouqiang/gocron/modules/rpc/proto"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "time"
)
var (
- errUnavailable = errors.New("无法连接远程服务器")
+ errUnavailable = errors.New("无法连接远程服务器")
)
-func ExecWithRetry(ip string, port int, taskReq *pb.TaskRequest) (string, error) {
- tryTimes := 60
- i := 0
- for i < tryTimes {
- output, err := Exec(ip, port, taskReq)
- if err != errUnavailable {
- return output, err
- }
- i++
- time.Sleep(2 * time.Second)
- }
+func Exec(ip string, port int, taskReq *pb.TaskRequest) (string, error) {
+ defer func() {
+ if err := recover(); err != nil {
+ logger.Error("panic#rpc/client.go:Exec#", err)
+ }
+ }()
+ addr := fmt.Sprintf("%s:%d", ip, port)
+ conn, err := grpcpool.Pool.Get(addr)
+ if err != nil {
+ return "", err
+ }
+ isConnClosed := false
+ defer func() {
+ if !isConnClosed {
+ grpcpool.Pool.Put(addr, conn)
+ }
+ }()
+ c := pb.NewTaskClient(conn)
+ if taskReq.Timeout <= 0 || taskReq.Timeout > 86400 {
+ taskReq.Timeout = 86400
+ }
+ timeout := time.Duration(taskReq.Timeout) * time.Second
+ ctx, cancel := context.WithTimeout(context.Background(), timeout)
+ defer cancel()
+ resp, err := c.Run(ctx, taskReq)
+ if err != nil {
+ return parseGRPCError(err, conn, &isConnClosed)
+ }
- return "", errUnavailable
-}
+ if resp.Error == "" {
+ return resp.Output, nil
+ }
-func Exec(ip string, port int, taskReq *pb.TaskRequest) (string, error) {
- defer func() {
- if err := recover(); err != nil {
- logger.Error("panic#rpc/client.go:Exec#", err)
- }
- } ()
- addr := fmt.Sprintf("%s:%d", ip, port)
- conn, err := grpcpool.Pool.Get(addr)
- if err != nil {
- return "", err
- }
- isConnClosed := false
- defer func() {
- if !isConnClosed {
- grpcpool.Pool.Put(addr, conn)
- }
- }()
- c := pb.NewTaskClient(conn)
- if taskReq.Timeout <= 0 || taskReq.Timeout > 86400 {
- taskReq.Timeout = 86400
- }
- timeout := time.Duration(taskReq.Timeout) * time.Second
- ctx, cancel := context.WithTimeout(context.Background(), timeout)
- defer cancel()
- resp, err := c.Run(ctx, taskReq)
- if err != nil {
- return parseGRPCError(err, conn, &isConnClosed)
- }
-
- if resp.Error == "" {
- return resp.Output, nil
- }
-
- return resp.Output, errors.New(resp.Error)
+ return resp.Output, errors.New(resp.Error)
}
func parseGRPCError(err error, conn *grpc.ClientConn, connClosed *bool) (string, error) {
- switch grpc.Code(err) {
- case codes.Unavailable, codes.Internal:
- conn.Close()
- *connClosed = true
- return "", errUnavailable
- case codes.DeadlineExceeded:
- return "", errors.New("执行超时, 强制结束")
- }
- return "", err
+ switch grpc.Code(err) {
+ case codes.Unavailable, codes.Internal:
+ conn.Close()
+ *connClosed = true
+ return "", errUnavailable
+ case codes.DeadlineExceeded:
+ return "", errors.New("执行超时, 强制结束")
+ }
+ return "", err
}
diff --git a/modules/rpc/grpcpool/grpc_pool.go b/modules/rpc/grpcpool/grpc_pool.go
index d6ce85e..36eec75 100644
--- a/modules/rpc/grpcpool/grpc_pool.go
+++ b/modules/rpc/grpcpool/grpc_pool.go
@@ -1,141 +1,139 @@
package grpcpool
import (
- "github.com/silenceper/pool"
- "sync"
- "time"
- "google.golang.org/grpc"
- "errors"
- "github.com/ouqiang/gocron/modules/rpc/auth"
- "github.com/ouqiang/gocron/modules/app"
- "strings"
-)
-
-
-var (
- Pool GRPCPool
+ "errors"
+ "github.com/ouqiang/gocron/modules/app"
+ "github.com/ouqiang/gocron/modules/rpc/auth"
+ "github.com/silenceper/pool"
+ "google.golang.org/grpc"
+ "strings"
+ "sync"
+ "time"
)
var (
- ErrInvalidConn = errors.New("invalid connection")
+ Pool GRPCPool
)
-func init() {
- Pool = GRPCPool{
- make(map[string]pool.Pool),
- sync.RWMutex{},
- }
+var (
+ ErrInvalidConn = errors.New("invalid connection")
+)
+
+func init() {
+ Pool = GRPCPool{
+ make(map[string]pool.Pool),
+ sync.RWMutex{},
+ }
}
type GRPCPool struct {
- // map key格式 ip:port
- conns map[string]pool.Pool
- sync.RWMutex
+ // map key格式 ip:port
+ conns map[string]pool.Pool
+ sync.RWMutex
}
-func (p *GRPCPool) Get(addr string) (*grpc.ClientConn, error) {
- p.RLock()
- pool, ok := p.conns[addr]
- p.RUnlock()
- if !ok {
- err := p.newCommonPool(addr)
- if err != nil {
- return nil, err
- }
- }
+func (p *GRPCPool) Get(addr string) (*grpc.ClientConn, error) {
+ p.RLock()
+ pool, ok := p.conns[addr]
+ p.RUnlock()
+ if !ok {
+ err := p.newCommonPool(addr)
+ if err != nil {
+ return nil, err
+ }
+ }
- p.RLock()
- pool = p.conns[addr]
- p.RUnlock()
- conn, err := pool.Get()
- if err != nil {
- return nil, err
- }
+ p.RLock()
+ pool = p.conns[addr]
+ p.RUnlock()
+ conn, err := pool.Get()
+ if err != nil {
+ return nil, err
+ }
- return conn.(*grpc.ClientConn), nil
+ return conn.(*grpc.ClientConn), nil
}
func (p *GRPCPool) Put(addr string, conn *grpc.ClientConn) error {
- p.RLock()
- defer p.RUnlock()
- pool, ok := p.conns[addr]
- if ok {
- return pool.Put(conn)
- }
+ p.RLock()
+ defer p.RUnlock()
+ pool, ok := p.conns[addr]
+ if ok {
+ return pool.Put(conn)
+ }
- return ErrInvalidConn
+ return ErrInvalidConn
}
-
// 释放连接池
func (p *GRPCPool) Release(addr string) {
- p.Lock()
- defer p.Unlock()
- pool, ok := p.conns[addr]
- if !ok {
- return
- }
- pool.Release()
- delete(p.conns, addr)
+ p.Lock()
+ defer p.Unlock()
+ pool, ok := p.conns[addr]
+ if !ok {
+ return
+ }
+ pool.Release()
+ delete(p.conns, addr)
}
// 释放所有连接池
-func (p *GRPCPool) ReleaseAll() {
- p.Lock()
- defer p.Unlock()
- for _, pool := range(p.conns) {
- pool.Release()
- }
+func (p *GRPCPool) ReleaseAll() {
+ p.Lock()
+ defer p.Unlock()
+ for _, pool := range p.conns {
+ pool.Release()
+ }
}
// 初始化底层连接池
-func (p *GRPCPool) newCommonPool(addr string) (error) {
- p.Lock()
- defer p.Unlock()
- commonPool, ok := p.conns[addr]
- if ok {
- return nil
- }
- poolConfig := &pool.PoolConfig{
- InitialCap: 1,
- MaxCap: 30,
- Factory: func() (interface{}, error) {
- if !app.Setting.EnableTLS {
- return grpc.Dial(addr, grpc.WithInsecure())
- }
+func (p *GRPCPool) newCommonPool(addr string) error {
+ p.Lock()
+ defer p.Unlock()
+ commonPool, ok := p.conns[addr]
+ if ok {
+ return nil
+ }
+ poolConfig := &pool.PoolConfig{
+ InitialCap: 1,
+ MaxCap: 30,
+ Factory: func() (interface{}, error) {
+ if !app.Setting.EnableTLS {
+ return grpc.Dial(addr, grpc.WithInsecure())
+ }
- server := strings.Split(addr, ":")
+ server := strings.Split(addr, ":")
- certificate := auth.Certificate{
- CAFile: app.Setting.CAFile,
- CertFile: app.Setting.CertFile,
- KeyFile: app.Setting.KeyFile,
- ServerName: server[0],
- }
+ certificate := auth.Certificate{
+ CAFile: app.Setting.CAFile,
+ CertFile: app.Setting.CertFile,
+ KeyFile: app.Setting.KeyFile,
+ ServerName: server[0],
+ }
- transportCreds, err := certificate.GetTransportCredsForClient()
- if err != nil {
- return nil, err
- }
+ transportCreds, err := certificate.GetTransportCredsForClient()
+ if err != nil {
+ return nil, err
+ }
- return grpc.Dial(addr, grpc.WithTransportCredentials(transportCreds))
- },
- Close: func(v interface{}) error {
- conn, ok := v.(*grpc.ClientConn)
- if ok && conn != nil {
- return conn.Close()
- }
- return ErrInvalidConn
- },
- IdleTimeout: 3 * time.Minute,
- }
+ return grpc.Dial(addr, grpc.WithTransportCredentials(transportCreds))
+ },
+ Close: func(v interface{}) error {
+ conn, ok := v.(*grpc.ClientConn)
+ if ok && conn != nil {
+ return conn.Close()
+ }
+ return ErrInvalidConn
+ },
+ IdleTimeout: 3 * time.Minute,
+ }
- commonPool, err := pool.NewChannelPool(poolConfig)
- if err != nil {
- return err
- }
+ commonPool, err := pool.NewChannelPool(poolConfig)
+ if err != nil {
+ return err
+ }
- p.conns[addr] = commonPool
+ p.conns[addr] = commonPool
- return nil
-}
\ No newline at end of file
+ return nil
+}
diff --git a/modules/rpc/server/server.go b/modules/rpc/server/server.go
index a529a40..1e0ad55 100644
--- a/modules/rpc/server/server.go
+++ b/modules/rpc/server/server.go
@@ -1,65 +1,64 @@
package server
import (
- "golang.org/x/net/context"
- "net"
- "google.golang.org/grpc/grpclog"
- "google.golang.org/grpc"
- pb "github.com/ouqiang/gocron/modules/rpc/proto"
- "github.com/ouqiang/gocron/modules/utils"
- "github.com/ouqiang/gocron/modules/rpc/auth"
- "google.golang.org/grpc/credentials"
+ "github.com/ouqiang/gocron/modules/rpc/auth"
+ pb "github.com/ouqiang/gocron/modules/rpc/proto"
+ "github.com/ouqiang/gocron/modules/utils"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/grpclog"
+ "net"
)
-type Server struct {}
+type Server struct{}
-func (s Server) Run(ctx context.Context, req *pb.TaskRequest) (*pb.TaskResponse, error) {
- defer func() {
- if err := recover(); err != nil {
- grpclog.Println(err)
- }
- } ()
- output, err := utils.ExecShell(ctx, req.Command)
- resp := new(pb.TaskResponse)
- resp.Output = output
- if err != nil {
- resp.Error = err.Error()
- } else {
- resp.Error = ""
- }
+func (s Server) Run(ctx context.Context, req *pb.TaskRequest) (*pb.TaskResponse, error) {
+ defer func() {
+ if err := recover(); err != nil {
+ grpclog.Println(err)
+ }
+ }()
+ output, err := utils.ExecShell(ctx, req.Command)
+ resp := new(pb.TaskResponse)
+ resp.Output = output
+ if err != nil {
+ resp.Error = err.Error()
+ } else {
+ resp.Error = ""
+ }
- return resp, nil
+ return resp, nil
}
-func Start(addr string, enableTLS bool, certificate auth.Certificate) {
- defer func() {
- if err := recover(); err != nil {
- grpclog.Println("panic", err)
- }
- } ()
+func Start(addr string, enableTLS bool, certificate auth.Certificate) {
+ defer func() {
+ if err := recover(); err != nil {
+ grpclog.Println("panic", err)
+ }
+ }()
- l, err := net.Listen("tcp", addr)
- if err != nil {
- grpclog.Fatal(err)
- }
+ l, err := net.Listen("tcp", addr)
+ if err != nil {
+ grpclog.Fatal(err)
+ }
- var s *grpc.Server
- if enableTLS {
- tlsConfig, err := certificate.GetTLSConfigForServer()
- if err != nil {
- grpclog.Fatal(err)
- }
- opt := grpc.Creds(credentials.NewTLS(tlsConfig))
- s = grpc.NewServer(opt)
- pb.RegisterTaskServer(s, Server{})
- grpclog.Printf("listen %s with TLS", addr)
- } else {
- s = grpc.NewServer()
- pb.RegisterTaskServer(s, Server{})
- grpclog.Printf("listen %s", addr)
- }
+ var s *grpc.Server
+ if enableTLS {
+ tlsConfig, err := certificate.GetTLSConfigForServer()
+ if err != nil {
+ grpclog.Fatal(err)
+ }
+ opt := grpc.Creds(credentials.NewTLS(tlsConfig))
+ s = grpc.NewServer(opt)
+ pb.RegisterTaskServer(s, Server{})
+ grpclog.Printf("listen %s with TLS", addr)
+ } else {
+ s = grpc.NewServer()
+ pb.RegisterTaskServer(s, Server{})
+ grpclog.Printf("listen %s", addr)
+ }
- err = s.Serve(l)
- grpclog.Fatal(err)
+ err = s.Serve(l)
+ grpclog.Fatal(err)
}
-
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index d5da574..b41e72d 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -1,111 +1,111 @@
package setting
import (
- "errors"
- "gopkg.in/ini.v1"
- "github.com/ouqiang/gocron/modules/utils"
- "github.com/ouqiang/gocron/modules/logger"
+ "errors"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/utils"
+ "gopkg.in/ini.v1"
)
const DefaultSection = "default"
type Setting struct {
- Db struct{
- Engine string
- Host string
- Port int
- User string
- Password string
- Database string
- Prefix string
- Charset string
- MaxIdleConns int
- MaxOpenConns int
- }
- AllowIps string
- AppName string
- ApiKey string
- ApiSecret string
- ApiSignEnable bool
+ Db struct {
+ Engine string
+ Host string
+ Port int
+ User string
+ Password string
+ Database string
+ Prefix string
+ Charset string
+ MaxIdleConns int
+ MaxOpenConns int
+ }
+ AllowIps string
+ AppName string
+ ApiKey string
+ ApiSecret string
+ ApiSignEnable bool
- EnableTLS bool
- CAFile string
- CertFile string
- KeyFile string
+ EnableTLS bool
+ CAFile string
+ CertFile string
+ KeyFile string
}
// 读取配置
-func Read(filename string) (*Setting,error) {
- config, err := ini.Load(filename)
- if err != nil {
- return nil, err
- }
- section := config.Section(DefaultSection)
+func Read(filename string) (*Setting, error) {
+ config, err := ini.Load(filename)
+ if err != nil {
+ return nil, err
+ }
+ section := config.Section(DefaultSection)
- var s Setting
+ var s Setting
- s.Db.Engine = section.Key("db.engine").MustString("mysql")
- s.Db.Host = section.Key("db.host").MustString("127.0.0.1")
- s.Db.Port = section.Key("db.port").MustInt(3306)
- s.Db.User = section.Key("db.user").MustString("")
- s.Db.Password = section.Key("db.password").MustString("")
- s.Db.Database = section.Key("db.database").MustString("gocron")
- s.Db.Prefix = section.Key("db.prefix").MustString("")
- s.Db.Charset = section.Key("db.charset").MustString("utf8")
- s.Db.MaxIdleConns = section.Key("db.max.idle.conns").MustInt(30)
- s.Db.MaxOpenConns = section.Key("db.max.open.conns").MustInt(100)
+ s.Db.Engine = section.Key("db.engine").MustString("mysql")
+ s.Db.Host = section.Key("db.host").MustString("127.0.0.1")
+ s.Db.Port = section.Key("db.port").MustInt(3306)
+ s.Db.User = section.Key("db.user").MustString("")
+ s.Db.Password = section.Key("db.password").MustString("")
+ s.Db.Database = section.Key("db.database").MustString("gocron")
+ s.Db.Prefix = section.Key("db.prefix").MustString("")
+ s.Db.Charset = section.Key("db.charset").MustString("utf8")
+ s.Db.MaxIdleConns = section.Key("db.max.idle.conns").MustInt(30)
+ s.Db.MaxOpenConns = section.Key("db.max.open.conns").MustInt(100)
- s.AllowIps = section.Key("allow_ips").MustString("")
- s.AppName = section.Key("app.name").MustString("定时任务管理系统")
- s.ApiKey = section.Key("api.key").MustString("")
- s.ApiSecret = section.Key("api.secret").MustString("")
- s.ApiSignEnable = section.Key("api.sign.enable").MustBool(true)
+ s.AllowIps = section.Key("allow_ips").MustString("")
+ s.AppName = section.Key("app.name").MustString("定时任务管理系统")
+ s.ApiKey = section.Key("api.key").MustString("")
+ s.ApiSecret = section.Key("api.secret").MustString("")
+ s.ApiSignEnable = section.Key("api.sign.enable").MustBool(true)
- s.EnableTLS = section.Key("enable_tls").MustBool(false)
- s.CAFile = section.Key("ca_file").MustString("")
- s.CertFile = section.Key("cert_file").MustString("")
- s.KeyFile = section.Key("key_file").MustString("")
+ s.EnableTLS = section.Key("enable_tls").MustBool(false)
+ s.CAFile = section.Key("ca_file").MustString("")
+ s.CertFile = section.Key("cert_file").MustString("")
+ s.KeyFile = section.Key("key_file").MustString("")
- if s.EnableTLS {
- if !utils.FileExist(s.CAFile) {
- logger.Fatalf("failed to read ca cert file: %s", s.CAFile)
- }
+ if s.EnableTLS {
+ if !utils.FileExist(s.CAFile) {
+ logger.Fatalf("failed to read ca cert file: %s", s.CAFile)
+ }
- if !utils.FileExist(s.CertFile) {
- logger.Fatalf("failed to read client cert file: %s", s.CertFile)
- }
+ if !utils.FileExist(s.CertFile) {
+ logger.Fatalf("failed to read client cert file: %s", s.CertFile)
+ }
- if !utils.FileExist(s.KeyFile) {
- logger.Fatalf("failed to read client key file: %s", s.KeyFile)
- }
- }
+ if !utils.FileExist(s.KeyFile) {
+ logger.Fatalf("failed to read client key file: %s", s.KeyFile)
+ }
+ }
- return &s, nil
+ return &s, nil
}
// 写入配置
func Write(config []string, filename string) error {
- if len(config) == 0 {
- return errors.New("参数不能为空")
- }
- if len(config) % 2 != 0 {
- return errors.New("参数不匹配")
- }
+ if len(config) == 0 {
+ return errors.New("参数不能为空")
+ }
+ if len(config)%2 != 0 {
+ return errors.New("参数不匹配")
+ }
- file := ini.Empty()
+ file := ini.Empty()
- section, err := file.NewSection(DefaultSection)
- if err != nil {
- return err
- }
- for i := 0 ;i < len(config); {
- _, err = section.NewKey(config[i], config[i+1])
- if err != nil {
- return err
- }
- i += 2
- }
- err = file.SaveTo(filename)
+ section, err := file.NewSection(DefaultSection)
+ if err != nil {
+ return err
+ }
+ for i := 0; i < len(config); {
+ _, err = section.NewKey(config[i], config[i+1])
+ if err != nil {
+ return err
+ }
+ i += 2
+ }
+ err = file.SaveTo(filename)
- return err
+ return err
}
diff --git a/modules/ssh/ssh.go b/modules/ssh/ssh.go
index 5b255f9..da9ab81 100644
--- a/modules/ssh/ssh.go
+++ b/modules/ssh/ssh.go
@@ -1,143 +1,139 @@
package ssh
import (
- "golang.org/x/crypto/ssh"
- "fmt"
- "net"
- "time"
- "errors"
+ "errors"
+ "fmt"
+ "golang.org/x/crypto/ssh"
+ "net"
+ "time"
)
-type HostAuthType int8 // 认证方式
+type HostAuthType int8 // 认证方式
const (
- HostPassword = 1 // 密码认证
- HostPublicKey = 2 // 公钥认证
+ HostPassword = 1 // 密码认证
+ HostPublicKey = 2 // 公钥认证
)
const SSHConnectTimeout = 10
-
-type SSHConfig struct {
- AuthType HostAuthType
- User string
- Password string
- PrivateKey string
- Host string
- Port int
- ExecTimeout int// 执行超时时间
+type SSHConfig struct {
+ AuthType HostAuthType
+ User string
+ Password string
+ PrivateKey string
+ Host string
+ Port int
+ ExecTimeout int // 执行超时时间
}
type Result struct {
- Output string
- Err error
+ Output string
+ Err error
}
func parseSSHConfig(sshConfig SSHConfig) (config *ssh.ClientConfig, err error) {
- timeout := time.Duration(SSHConnectTimeout) * time.Second
- // 密码认证
- if sshConfig.AuthType == HostPassword {
- config = &ssh.ClientConfig{
- User: sshConfig.User,
- Auth: []ssh.AuthMethod{
- ssh.Password(sshConfig.Password),
- },
- Timeout: timeout,
- HostKeyCallback:func(hostname string, remote net.Addr, key ssh.PublicKey) error {
- return nil
- },
- }
+ timeout := time.Duration(SSHConnectTimeout) * time.Second
+ // 密码认证
+ if sshConfig.AuthType == HostPassword {
+ config = &ssh.ClientConfig{
+ User: sshConfig.User,
+ Auth: []ssh.AuthMethod{
+ ssh.Password(sshConfig.Password),
+ },
+ Timeout: timeout,
+ HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
+ return nil
+ },
+ }
- return
- }
+ return
+ }
- signer, err := ssh.ParsePrivateKey([]byte(sshConfig.PrivateKey))
- if err != nil {
- return
- }
+ signer, err := ssh.ParsePrivateKey([]byte(sshConfig.PrivateKey))
+ if err != nil {
+ return
+ }
- // 公钥认证
- config = &ssh.ClientConfig{
- User: sshConfig.User,
- Auth: []ssh.AuthMethod{
- ssh.PublicKeys(signer),
- },
- Timeout: timeout,
- HostKeyCallback:func(hostname string, remote net.Addr, key ssh.PublicKey) error {
- return nil
- },
- }
+ // 公钥认证
+ config = &ssh.ClientConfig{
+ User: sshConfig.User,
+ Auth: []ssh.AuthMethod{
+ ssh.PublicKeys(signer),
+ },
+ Timeout: timeout,
+ HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
+ return nil
+ },
+ }
- return
+ return
}
-
// 执行shell命令
func Exec(sshConfig SSHConfig, cmd string) (output string, err error) {
- client, err := getClient(sshConfig)
- if err != nil {
- return "", err
- }
- defer client.Close()
+ client, err := getClient(sshConfig)
+ if err != nil {
+ return "", err
+ }
+ defer client.Close()
- session, err := client.NewSession()
+ session, err := client.NewSession()
- if err != nil {
- return "", err
- }
- defer session.Close()
+ if err != nil {
+ return "", err
+ }
+ defer session.Close()
- // 后台运行
- if sshConfig.ExecTimeout < 0 {
- go session.CombinedOutput(cmd)
- time.Sleep(10 * time.Second)
- return "", nil
- }
- // 不限制超时
- if sshConfig.ExecTimeout == 0 {
- outputByte, execErr := session.CombinedOutput(cmd)
- output = string(outputByte)
- err = execErr
- return
- }
+ // 后台运行
+ if sshConfig.ExecTimeout < 0 {
+ go session.CombinedOutput(cmd)
+ time.Sleep(10 * time.Second)
+ return "", nil
+ }
+ // 不限制超时
+ if sshConfig.ExecTimeout == 0 {
+ outputByte, execErr := session.CombinedOutput(cmd)
+ output = string(outputByte)
+ err = execErr
+ return
+ }
- var resultChan chan Result = make(chan Result)
- var timeoutChan chan bool = make(chan bool)
- go func() {
- output, err := session.CombinedOutput(cmd)
- resultChan <- Result{string(output), err}
- }()
- // todo 等待超时后,如何停止远程正在执行的任务, 使用timeout命令,但不具有通用性
- go triggerTimeout(timeoutChan, sshConfig.ExecTimeout)
- select {
- case result := <- resultChan:
- output = result.Output
- err = result.Err
- case <- timeoutChan:
- output = ""
- err = errors.New("timeout")
- }
+ var resultChan chan Result = make(chan Result)
+ var timeoutChan chan bool = make(chan bool)
+ go func() {
+ output, err := session.CombinedOutput(cmd)
+ resultChan <- Result{string(output), err}
+ }()
+ // todo 等待超时后,如何停止远程正在执行的任务, 使用timeout命令,但不具有通用性
+ go triggerTimeout(timeoutChan, sshConfig.ExecTimeout)
+ select {
+ case result := <-resultChan:
+ output = result.Output
+ err = result.Err
+ case <-timeoutChan:
+ output = ""
+ err = errors.New("timeout")
+ }
- return
+ return
}
-func getClient(sshConfig SSHConfig) (*ssh.Client, error) {
- config, err := parseSSHConfig(sshConfig)
- if err != nil {
- return nil, err
- }
- addr := fmt.Sprintf("%s:%d", sshConfig.Host, sshConfig.Port)
+func getClient(sshConfig SSHConfig) (*ssh.Client, error) {
+ config, err := parseSSHConfig(sshConfig)
+ if err != nil {
+ return nil, err
+ }
+ addr := fmt.Sprintf("%s:%d", sshConfig.Host, sshConfig.Port)
- return ssh.Dial("tcp", addr, config)
+ return ssh.Dial("tcp", addr, config)
}
-
-func triggerTimeout(ch chan bool, timeout int){
- // 最长执行时间不能超过24小时
- if timeout <= 0 || timeout > 86400 {
- timeout = 86400
- }
- time.Sleep(time.Duration(timeout) * time.Second)
- close(ch)
+func triggerTimeout(ch chan bool, timeout int) {
+ // 最长执行时间不能超过24小时
+ if timeout <= 0 || timeout > 86400 {
+ timeout = 86400
+ }
+ time.Sleep(time.Duration(timeout) * time.Second)
+ close(ch)
}
-
diff --git a/modules/utils/json.go b/modules/utils/json.go
index e45d583..cbc5f0a 100644
--- a/modules/utils/json.go
+++ b/modules/utils/json.go
@@ -1,16 +1,16 @@
package utils
import (
- "encoding/json"
- "github.com/ouqiang/gocron/modules/logger"
+ "encoding/json"
+ "github.com/ouqiang/gocron/modules/logger"
)
// json 格式输出
type response struct {
- Code int `json:"code"` // 状态码 0:成功 非0:失败
- Message string `json:"message"` // 信息
- Data interface{} `json:"data"` // 数据
+ Code int `json:"code"` // 状态码 0:成功 非0:失败
+ Message string `json:"message"` // 信息
+ Data interface{} `json:"data"` // 数据
}
type JsonResponse struct{}
@@ -26,40 +26,40 @@ const SuccessContent = "操作成功"
const FailureContent = "操作失败"
func JsonResponseByErr(err error) string {
- json := JsonResponse{}
- if err != nil {
- return json.CommonFailure(FailureContent, err)
- }
+ json := JsonResponse{}
+ if err != nil {
+ return json.CommonFailure(FailureContent, err)
+ }
- return json.Success(SuccessContent, nil)
+ return json.Success(SuccessContent, nil)
}
func (j *JsonResponse) Success(message string, data interface{}) string {
- return j.response(ResponseSuccess, message, data)
+ return j.response(ResponseSuccess, message, data)
}
func (j *JsonResponse) Failure(code int, message string) string {
- return j.response(code, message, nil)
+ return j.response(code, message, nil)
}
-func (j *JsonResponse) CommonFailure(message string, err... error) string {
- if len(err) > 0 {
- logger.Warn(err)
- }
- return j.Failure(ResponseFailure, message)
+func (j *JsonResponse) CommonFailure(message string, err ...error) string {
+ if len(err) > 0 {
+ logger.Warn(err)
+ }
+ return j.Failure(ResponseFailure, message)
}
func (j *JsonResponse) response(code int, message string, data interface{}) string {
- resp := response{
- Code: code,
- Message: message,
- Data: data,
- }
+ resp := response{
+ Code: code,
+ Message: message,
+ Data: data,
+ }
- result, err := json.Marshal(resp)
- if err != nil {
- logger.Error(err)
- }
+ result, err := json.Marshal(resp)
+ if err != nil {
+ logger.Error(err)
+ }
- return string(result)
+ return string(result)
}
diff --git a/modules/utils/utils.go b/modules/utils/utils.go
index 5ce46f2..a1cacab 100644
--- a/modules/utils/utils.go
+++ b/modules/utils/utils.go
@@ -1,107 +1,107 @@
package utils
import (
- "crypto/md5"
- "encoding/hex"
- "math/rand"
- "time"
- "runtime"
- "github.com/Tang-RoseChild/mahonia"
- "strings"
- "os"
- "fmt"
+ "crypto/md5"
+ "encoding/hex"
+ "fmt"
+ "github.com/Tang-RoseChild/mahonia"
+ "math/rand"
+ "os"
+ "runtime"
+ "strings"
+ "time"
)
// 生成长度为length的随机字符串
func RandString(length int64) string {
- sources := []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
- result := []byte{}
- r := rand.New(rand.NewSource(time.Now().UnixNano()))
- sourceLength := len(sources)
- var i int64 = 0
- for ; i < length; i++ {
- result = append(result, sources[r.Intn(sourceLength)])
- }
+ sources := []byte("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
+ result := []byte{}
+ r := rand.New(rand.NewSource(time.Now().UnixNano()))
+ sourceLength := len(sources)
+ var i int64 = 0
+ for ; i < length; i++ {
+ result = append(result, sources[r.Intn(sourceLength)])
+ }
- return string(result)
+ return string(result)
}
// 生成32位MD5摘要
func Md5(str string) string {
- m := md5.New()
- m.Write([]byte(str))
+ m := md5.New()
+ m.Write([]byte(str))
- return hex.EncodeToString(m.Sum(nil))
+ return hex.EncodeToString(m.Sum(nil))
}
// 生成0-max之间随机数
func RandNumber(max int) int {
- r := rand.New(rand.NewSource(time.Now().UnixNano()))
+ r := rand.New(rand.NewSource(time.Now().UnixNano()))
- return r.Intn(max)
+ return r.Intn(max)
}
// 判断当前系统是否是windows
func IsWindows() bool {
- return runtime.GOOS == "windows"
+ return runtime.GOOS == "windows"
}
// GBK编码转换为UTF8
func GBK2UTF8(s string) (string, bool) {
- dec := mahonia.NewDecoder("gbk")
+ dec := mahonia.NewDecoder("gbk")
- return dec.ConvertStringOK(s)
+ return dec.ConvertStringOK(s)
}
// 批量替换字符串
-func ReplaceStrings(s string, old []string, replace []string) string {
- if s == "" {
- return s
- }
- if len(old) != len(replace) {
- return s
- }
+func ReplaceStrings(s string, old []string, replace []string) string {
+ if s == "" {
+ return s
+ }
+ if len(old) != len(replace) {
+ return s
+ }
- for i, v := range old {
- s = strings.Replace(s, v, replace[i], 1000)
- }
+ for i, v := range old {
+ s = strings.Replace(s, v, replace[i], 1000)
+ }
- return s
+ return s
}
func InStringSlice(slice []string, element string) bool {
- element = strings.TrimSpace(element)
- for _, v := range slice {
- if strings.TrimSpace(v) == element{
- return true
- }
- }
+ element = strings.TrimSpace(element)
+ for _, v := range slice {
+ if strings.TrimSpace(v) == element {
+ return true
+ }
+ }
- return false
+ return false
}
// 转义json特殊字符
-func EscapeJson(s string) string {
- specialChars := []string{"\\", "\b","\f", "\n", "\r", "\t", "\"",}
- replaceChars := []string{ "\\\\", "\\b", "\\f", "\\n", "\\r", "\\t", "\\\"",}
+func EscapeJson(s string) string {
+ specialChars := []string{"\\", "\b", "\f", "\n", "\r", "\t", "\""}
+ replaceChars := []string{"\\\\", "\\b", "\\f", "\\n", "\\r", "\\t", "\\\""}
- return ReplaceStrings(s, specialChars, replaceChars)
+ return ReplaceStrings(s, specialChars, replaceChars)
}
// 判断文件是否存在及是否有权限访问
func FileExist(file string) bool {
- _, err := os.Stat(file)
- if os.IsNotExist(err) {
- return false
- }
- if os.IsPermission(err) {
- return false
- }
+ _, err := os.Stat(file)
+ if os.IsNotExist(err) {
+ return false
+ }
+ if os.IsPermission(err) {
+ return false
+ }
- return true
+ return true
}
// 格式化环境变量
func FormatUnixEnv(key, value string) string {
- return fmt.Sprintf("export %s=%s; ", key, value)
-}
\ No newline at end of file
+ return fmt.Sprintf("export %s=%s; ", key, value)
+}
diff --git a/modules/utils/utils_test.go b/modules/utils/utils_test.go
index f92401a..4fe09d6 100644
--- a/modules/utils/utils_test.go
+++ b/modules/utils/utils_test.go
@@ -3,22 +3,22 @@ package utils
import "testing"
func TestRandString(t *testing.T) {
- str := RandString(32)
- if len(str) != 32 {
- t.Fatalf("长度不匹配,目标长度32, 实际%d-%s", len(str), str)
- }
+ str := RandString(32)
+ if len(str) != 32 {
+ t.Fatalf("长度不匹配,目标长度32, 实际%d-%s", len(str), str)
+ }
}
func TestMd5(t *testing.T) {
- str := Md5("123456")
- if len(str) != 32 {
- t.Fatalf("长度不匹配,目标长度32, 实际%d-%s", len(str), str)
- }
+ str := Md5("123456")
+ if len(str) != 32 {
+ t.Fatalf("长度不匹配,目标长度32, 实际%d-%s", len(str), str)
+ }
}
func TestRandNumber(t *testing.T) {
- num := RandNumber(10000)
- if num <= 0 && num >= 10000 {
- t.Fatalf("随机数不在有效范围内-%d", num)
- }
+ num := RandNumber(10000)
+ if num <= 0 && num >= 10000 {
+ t.Fatalf("随机数不在有效范围内-%d", num)
+ }
}
diff --git a/modules/utils/utils_unix.go b/modules/utils/utils_unix.go
index 16539a3..d6d68c9 100644
--- a/modules/utils/utils_unix.go
+++ b/modules/utils/utils_unix.go
@@ -3,35 +3,35 @@
package utils
import (
- "os/exec"
- "syscall"
- "golang.org/x/net/context"
- "errors"
+ "errors"
+ "golang.org/x/net/context"
+ "os/exec"
+ "syscall"
)
type Result struct {
- output string
- err error
+ output string
+ err error
}
// 执行shell命令,可设置执行超时时间
-func ExecShell(ctx context.Context, command string) (string, error) {
- cmd := exec.Command("/bin/bash", "-c", command)
- cmd.SysProcAttr = &syscall.SysProcAttr{
- Setpgid: true,
- }
- var resultChan chan Result = make(chan Result)
- go func() {
- output ,err := cmd.CombinedOutput()
- resultChan <- Result{string(output), err}
- }()
- select {
- case <- ctx.Done():
- if cmd.Process.Pid > 0 {
- syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
- }
- return "", errors.New("timeout killed")
- case result := <- resultChan:
- return result.output, result.err
- }
-}
\ No newline at end of file
+func ExecShell(ctx context.Context, command string) (string, error) {
+ cmd := exec.Command("/bin/bash", "-c", command)
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ Setpgid: true,
+ }
+ var resultChan chan Result = make(chan Result)
+ go func() {
+ output, err := cmd.CombinedOutput()
+ resultChan <- Result{string(output), err}
+ }()
+ select {
+ case <-ctx.Done():
+ if cmd.Process.Pid > 0 {
+ syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
+ }
+ return "", errors.New("timeout killed")
+ case result := <-resultChan:
+ return result.output, result.err
+ }
+}
diff --git a/modules/utils/utils_windows.go b/modules/utils/utils_windows.go
index 6ad321d..bd60bb5 100644
--- a/modules/utils/utils_windows.go
+++ b/modules/utils/utils_windows.go
@@ -3,51 +3,48 @@
package utils
import (
- "syscall"
- "os/exec"
- "strconv"
- "golang.org/x/net/context"
- "errors"
+ "errors"
+ "golang.org/x/net/context"
+ "os/exec"
+ "strconv"
+ "syscall"
)
type Result struct {
- output string
- err error
+ output string
+ err error
}
// 执行shell命令,可设置执行超时时间
-func ExecShell(ctx context.Context, command string) (string, error) {
- cmd := exec.Command("cmd", "/C", command)
- // 隐藏cmd窗口
- cmd.SysProcAttr = &syscall.SysProcAttr{
- HideWindow: true,
- }
- var resultChan chan Result = make(chan Result)
- go func() {
- output ,err := cmd.CombinedOutput()
- resultChan <- Result{string(output), err}
- }()
- select {
- case <- ctx.Done():
- if cmd.Process.Pid > 0 {
- exec.Command("taskkill", "/F", "/T", "/PID", strconv.Itoa(cmd.Process.Pid)).Run()
- cmd.Process.Kill()
- }
- return "", errors.New("timeout killed")
- case result := <- resultChan:
- return ConvertEncoding(result.output), result.err
- }
-
-
- return "", nil
+func ExecShell(ctx context.Context, command string) (string, error) {
+ cmd := exec.Command("cmd", "/C", command)
+ // 隐藏cmd窗口
+ cmd.SysProcAttr = &syscall.SysProcAttr{
+ HideWindow: true,
+ }
+ var resultChan chan Result = make(chan Result)
+ go func() {
+ output, err := cmd.CombinedOutput()
+ resultChan <- Result{string(output), err}
+ }()
+ select {
+ case <-ctx.Done():
+ if cmd.Process.Pid > 0 {
+ exec.Command("taskkill", "/F", "/T", "/PID", strconv.Itoa(cmd.Process.Pid)).Run()
+ cmd.Process.Kill()
+ }
+ return "", errors.New("timeout killed")
+ case result := <-resultChan:
+ return ConvertEncoding(result.output), result.err
+ }
}
-func ConvertEncoding(outputGBK string) (string) {
- // windows平台编码为gbk,需转换为utf8才能入库
- outputUTF8, ok := GBK2UTF8(outputGBK)
- if ok {
- return outputUTF8
- }
+func ConvertEncoding(outputGBK string) string {
+ // windows平台编码为gbk,需转换为utf8才能入库
+ outputUTF8, ok := GBK2UTF8(outputGBK)
+ if ok {
+ return outputUTF8
+ }
- return "命令输出转换编码失败(gbk to utf8)"
-}
\ No newline at end of file
+ return "命令输出转换编码失败(gbk to utf8)"
+}
diff --git a/routers/base/base.go b/routers/base/base.go
index da19c74..11a412d 100644
--- a/routers/base/base.go
+++ b/routers/base/base.go
@@ -1,20 +1,20 @@
package base
import (
- "gopkg.in/macaron.v1"
- "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/models"
+ "gopkg.in/macaron.v1"
)
-func ParsePageAndPageSize(ctx *macaron.Context, params models.CommonMap) {
- page := ctx.QueryInt("page")
- pageSize := ctx.QueryInt("page_size")
- if page <= 0 {
- page = 1
- }
- if pageSize <= 0 {
- pageSize = models.PageSize
- }
+func ParsePageAndPageSize(ctx *macaron.Context, params models.CommonMap) {
+ page := ctx.QueryInt("page")
+ pageSize := ctx.QueryInt("page_size")
+ if page <= 0 {
+ page = 1
+ }
+ if pageSize <= 0 {
+ pageSize = models.PageSize
+ }
- params["Page"] = page
- params["PageSize"] = pageSize
-}
\ No newline at end of file
+ params["Page"] = page
+ params["PageSize"] = pageSize
+}
diff --git a/routers/home.go b/routers/home.go
index 84ebdc2..1d504b5 100644
--- a/routers/home.go
+++ b/routers/home.go
@@ -3,6 +3,6 @@ package routers
import "gopkg.in/macaron.v1"
// 首页
-func Home(ctx *macaron.Context) {
- ctx.Redirect("/task")
+func Home(ctx *macaron.Context) {
+ ctx.Redirect("/task")
}
diff --git a/routers/host/host.go b/routers/host/host.go
index 9625df4..ce8fa9a 100644
--- a/routers/host/host.go
+++ b/routers/host/host.go
@@ -1,194 +1,192 @@
package host
import (
- "gopkg.in/macaron.v1"
- "github.com/ouqiang/gocron/models"
- "github.com/ouqiang/gocron/modules/utils"
- "github.com/ouqiang/gocron/modules/logger"
- "strconv"
- "github.com/ouqiang/gocron/service"
- "github.com/Unknwon/paginater"
- "fmt"
- "html/template"
- "github.com/ouqiang/gocron/routers/base"
- "github.com/go-macaron/binding"
- "github.com/ouqiang/gocron/modules/rpc/grpcpool"
- "strings"
- "github.com/ouqiang/gocron/modules/rpc/client"
- "github.com/ouqiang/gocron/modules/rpc/proto"
+ "fmt"
+ "github.com/Unknwon/paginater"
+ "github.com/go-macaron/binding"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/rpc/client"
+ "github.com/ouqiang/gocron/modules/rpc/grpcpool"
+ "github.com/ouqiang/gocron/modules/rpc/proto"
+ "github.com/ouqiang/gocron/modules/utils"
+ "github.com/ouqiang/gocron/routers/base"
+ "github.com/ouqiang/gocron/service"
+ "gopkg.in/macaron.v1"
+ "html/template"
+ "strconv"
+ "strings"
)
-func Index(ctx *macaron.Context) {
- hostModel := new(models.Host)
- queryParams := parseQueryParams(ctx)
- total, err := hostModel.Total(queryParams)
- hosts, err := hostModel.List(queryParams)
- if err != nil {
- logger.Error(err)
- }
- name, ok := queryParams["name"].(string)
- var safeNameHTML = ""
- if ok {
- safeNameHTML = template.HTMLEscapeString(name)
- }
- PageParams := fmt.Sprintf("id=%d&name=%s&page_size=%d",
- queryParams["Id"], safeNameHTML, queryParams["PageSize"]);
- queryParams["PageParams"] = template.URL(PageParams)
- p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
- ctx.Data["Pagination"] = p
- ctx.Data["Title"] = "主机列表"
- ctx.Data["Hosts"] = hosts
- ctx.Data["Params"] = queryParams
- ctx.HTML(200, "host/index")
+func Index(ctx *macaron.Context) {
+ hostModel := new(models.Host)
+ queryParams := parseQueryParams(ctx)
+ total, err := hostModel.Total(queryParams)
+ hosts, err := hostModel.List(queryParams)
+ if err != nil {
+ logger.Error(err)
+ }
+ name, ok := queryParams["name"].(string)
+ var safeNameHTML = ""
+ if ok {
+ safeNameHTML = template.HTMLEscapeString(name)
+ }
+ PageParams := fmt.Sprintf("id=%d&name=%s&page_size=%d",
+ queryParams["Id"], safeNameHTML, queryParams["PageSize"])
+ queryParams["PageParams"] = template.URL(PageParams)
+ p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
+ ctx.Data["Pagination"] = p
+ ctx.Data["Title"] = "主机列表"
+ ctx.Data["Hosts"] = hosts
+ ctx.Data["Params"] = queryParams
+ ctx.HTML(200, "host/index")
}
-func Create(ctx *macaron.Context) {
- ctx.Data["Title"] = "添加主机"
- ctx.HTML(200, "host/host_form")
+func Create(ctx *macaron.Context) {
+ ctx.Data["Title"] = "添加主机"
+ ctx.HTML(200, "host/host_form")
}
-func Edit(ctx *macaron.Context) {
- ctx.Data["Title"] = "编辑主机"
- hostModel := new(models.Host)
- id := ctx.ParamsInt(":id")
- err := hostModel.Find(id)
- if err != nil {
- logger.Errorf("获取主机详情失败#主机id-%d", id)
- }
- ctx.Data["Host"] = hostModel
- ctx.HTML(200, "host/host_form")
+func Edit(ctx *macaron.Context) {
+ ctx.Data["Title"] = "编辑主机"
+ hostModel := new(models.Host)
+ id := ctx.ParamsInt(":id")
+ err := hostModel.Find(id)
+ if err != nil {
+ logger.Errorf("获取主机详情失败#主机id-%d", id)
+ }
+ ctx.Data["Host"] = hostModel
+ ctx.HTML(200, "host/host_form")
}
type HostForm struct {
- Id int16
- Name string `binding:"Required;MaxSize(64)"`
- Alias string `binding:"Required;MaxSize(32)"`
- Port int `binding:"Required;Range(1-65535)"`
- Remark string
+ Id int16
+ Name string `binding:"Required;MaxSize(64)"`
+ Alias string `binding:"Required;MaxSize(32)"`
+ Port int `binding:"Required;Range(1-65535)"`
+ Remark string
}
func (f HostForm) Error(ctx *macaron.Context, errs binding.Errors) {
- if len(errs) == 0 {
- return
- }
- json := utils.JsonResponse{}
- content := json.CommonFailure("表单验证失败, 请检测输入")
+ if len(errs) == 0 {
+ return
+ }
+ json := utils.JsonResponse{}
+ content := json.CommonFailure("表单验证失败, 请检测输入")
- ctx.Resp.Write([]byte(content))
+ ctx.Resp.Write([]byte(content))
}
-func Store(ctx *macaron.Context, form HostForm) string {
- json := utils.JsonResponse{}
- hostModel := new(models.Host)
- id := form.Id
- nameExist, err := hostModel.NameExists(form.Name, form.Id)
- if err != nil {
- return json.CommonFailure("操作失败", err)
- }
- if nameExist {
- return json.CommonFailure("主机名已存在")
- }
+func Store(ctx *macaron.Context, form HostForm) string {
+ json := utils.JsonResponse{}
+ hostModel := new(models.Host)
+ id := form.Id
+ nameExist, err := hostModel.NameExists(form.Name, form.Id)
+ if err != nil {
+ return json.CommonFailure("操作失败", err)
+ }
+ if nameExist {
+ return json.CommonFailure("主机名已存在")
+ }
- hostModel.Name = strings.TrimSpace(form.Name)
- hostModel.Alias = strings.TrimSpace(form.Alias)
- hostModel.Port = form.Port
- hostModel.Remark = strings.TrimSpace(form.Remark)
- isCreate := false
- oldHostModel := new(models.Host)
- err = oldHostModel.Find(int(id))
- if err != nil {
- return json.CommonFailure("主机不存在")
- }
+ hostModel.Name = strings.TrimSpace(form.Name)
+ hostModel.Alias = strings.TrimSpace(form.Alias)
+ hostModel.Port = form.Port
+ hostModel.Remark = strings.TrimSpace(form.Remark)
+ isCreate := false
+ oldHostModel := new(models.Host)
+ err = oldHostModel.Find(int(id))
+ if err != nil {
+ return json.CommonFailure("主机不存在")
+ }
- if id > 0 {
- _, err = hostModel.UpdateBean(id)
- } else {
- isCreate = true
- id, err = hostModel.Create()
- }
- if err != nil {
- return json.CommonFailure("保存失败", err)
- }
+ if id > 0 {
+ _, err = hostModel.UpdateBean(id)
+ } else {
+ isCreate = true
+ id, err = hostModel.Create()
+ }
+ if err != nil {
+ return json.CommonFailure("保存失败", err)
+ }
- if !isCreate {
- oldAddr := fmt.Sprintf("%s:%d", oldHostModel.Name, oldHostModel.Port)
- newAddr := fmt.Sprintf("%s:%d", hostModel.Name, hostModel.Port)
- if oldAddr != newAddr {
- grpcpool.Pool.Release(oldAddr)
- }
+ if !isCreate {
+ oldAddr := fmt.Sprintf("%s:%d", oldHostModel.Name, oldHostModel.Port)
+ newAddr := fmt.Sprintf("%s:%d", hostModel.Name, hostModel.Port)
+ if oldAddr != newAddr {
+ grpcpool.Pool.Release(oldAddr)
+ }
- taskModel := new(models.Task)
- tasks, err := taskModel.ActiveListByHostId(id)
- if err != nil {
- return json.CommonFailure("刷新任务主机信息失败", err)
- }
- serviceTask := new(service.Task)
- serviceTask.BatchAdd(tasks)
- }
+ taskModel := new(models.Task)
+ tasks, err := taskModel.ActiveListByHostId(id)
+ if err != nil {
+ return json.CommonFailure("刷新任务主机信息失败", err)
+ }
+ serviceTask := new(service.Task)
+ serviceTask.BatchAdd(tasks)
+ }
- return json.Success("保存成功", nil)
+ return json.Success("保存成功", nil)
}
-func Remove(ctx *macaron.Context) string {
- id, err := strconv.Atoi(ctx.Params(":id"))
- json := utils.JsonResponse{}
- if err != nil {
- return json.CommonFailure("参数错误", err)
- }
- taskHostModel := new(models.TaskHost)
- exist,err := taskHostModel.HostIdExist(int16(id))
- if err != nil {
- return json.CommonFailure("操作失败", err)
- }
- if exist {
- return json.CommonFailure("有任务引用此主机,不能删除")
- }
+func Remove(ctx *macaron.Context) string {
+ id, err := strconv.Atoi(ctx.Params(":id"))
+ json := utils.JsonResponse{}
+ if err != nil {
+ return json.CommonFailure("参数错误", err)
+ }
+ taskHostModel := new(models.TaskHost)
+ exist, err := taskHostModel.HostIdExist(int16(id))
+ if err != nil {
+ return json.CommonFailure("操作失败", err)
+ }
+ if exist {
+ return json.CommonFailure("有任务引用此主机,不能删除")
+ }
- hostModel := new(models.Host)
- err = hostModel.Find(int(id))
- if err != nil {
- return json.CommonFailure("主机不存在")
- }
+ hostModel := new(models.Host)
+ err = hostModel.Find(int(id))
+ if err != nil {
+ return json.CommonFailure("主机不存在")
+ }
- _, err =hostModel.Delete(id)
- if err != nil {
- return json.CommonFailure("操作失败", err)
- }
+ _, err = hostModel.Delete(id)
+ if err != nil {
+ return json.CommonFailure("操作失败", err)
+ }
- addr := fmt.Sprintf("%s:%d", hostModel.Name, hostModel.Port)
- grpcpool.Pool.Release(addr)
+ addr := fmt.Sprintf("%s:%d", hostModel.Name, hostModel.Port)
+ grpcpool.Pool.Release(addr)
-
- return json.Success("操作成功", nil)
+ return json.Success("操作成功", nil)
}
-func Ping(ctx *macaron.Context) string {
- id := ctx.ParamsInt(":id")
- hostModel := new(models.Host)
- err := hostModel.Find(id)
- json := utils.JsonResponse{}
- if err != nil || hostModel.Id <= 0{
- return json.CommonFailure("主机不存在", err)
- }
+func Ping(ctx *macaron.Context) string {
+ id := ctx.ParamsInt(":id")
+ hostModel := new(models.Host)
+ err := hostModel.Find(id)
+ json := utils.JsonResponse{}
+ if err != nil || hostModel.Id <= 0 {
+ return json.CommonFailure("主机不存在", err)
+ }
+ taskReq := &rpc.TaskRequest{}
+ taskReq.Command = "echo hello"
+ taskReq.Timeout = 10
+ output, err := client.Exec(hostModel.Name, hostModel.Port, taskReq)
+ if err != nil {
+ return json.CommonFailure("连接失败-"+err.Error()+" "+output, err)
+ }
- taskReq := &rpc.TaskRequest{}
- taskReq.Command = "echo hello"
- taskReq.Timeout = 10
- output, err := client.Exec(hostModel.Name, hostModel.Port, taskReq)
- if err != nil {
- return json.CommonFailure("连接失败-" + err.Error() + " " + output, err)
- }
-
- return json.Success("连接成功", nil)
+ return json.Success("连接成功", nil)
}
// 解析查询参数
-func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
- var params models.CommonMap = models.CommonMap{}
- params["Id"] = ctx.QueryInt("id")
- params["Name"] = ctx.QueryTrim("name")
- base.ParsePageAndPageSize(ctx, params)
+func parseQueryParams(ctx *macaron.Context) models.CommonMap {
+ var params models.CommonMap = models.CommonMap{}
+ params["Id"] = ctx.QueryInt("id")
+ params["Name"] = ctx.QueryTrim("name")
+ base.ParsePageAndPageSize(ctx, params)
- return params
-}
\ No newline at end of file
+ return params
+}
diff --git a/routers/install/install.go b/routers/install/install.go
index 821839f..f9bc750 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -1,163 +1,163 @@
package install
import (
- "github.com/ouqiang/gocron/models"
- "github.com/ouqiang/gocron/modules/app"
- "github.com/ouqiang/gocron/modules/setting"
- "github.com/ouqiang/gocron/modules/utils"
- "gopkg.in/macaron.v1"
- "strconv"
- "fmt"
- "github.com/ouqiang/gocron/service"
- "github.com/go-macaron/binding"
+ "fmt"
+ "github.com/go-macaron/binding"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/app"
+ "github.com/ouqiang/gocron/modules/setting"
+ "github.com/ouqiang/gocron/modules/utils"
+ "github.com/ouqiang/gocron/service"
+ "gopkg.in/macaron.v1"
+ "strconv"
)
// 系统安装
type InstallForm struct {
- DbType string `binding:"In(mysql)"`
- DbHost string `binding:"Required;MaxSize(50)"`
- DbPort int `binding:"Required;Range(1,65535)"`
- DbUsername string `binding:"Required;MaxSize(50)"`
- DbPassword string `binding:"Required;MaxSize(30)"`
- DbName string `binding:"Required;MaxSize(50)"`
- DbTablePrefix string `binding:"MaxSize(20)"`
- AdminUsername string `binding:"Required;MinSize(3)"`
- AdminPassword string `binding:"Required;MinSize(6)"`
- ConfirmAdminPassword string `binding:"Required;MinSize(6)"`
- AdminEmail string `binding:"Required;Email;MaxSize(50)"`
+ DbType string `binding:"In(mysql)"`
+ DbHost string `binding:"Required;MaxSize(50)"`
+ DbPort int `binding:"Required;Range(1,65535)"`
+ DbUsername string `binding:"Required;MaxSize(50)"`
+ DbPassword string `binding:"Required;MaxSize(30)"`
+ DbName string `binding:"Required;MaxSize(50)"`
+ DbTablePrefix string `binding:"MaxSize(20)"`
+ AdminUsername string `binding:"Required;MinSize(3)"`
+ AdminPassword string `binding:"Required;MinSize(6)"`
+ ConfirmAdminPassword string `binding:"Required;MinSize(6)"`
+ AdminEmail string `binding:"Required;Email;MaxSize(50)"`
}
func (f InstallForm) Error(ctx *macaron.Context, errs binding.Errors) {
- if len(errs) == 0 {
- return
- }
- json := utils.JsonResponse{}
- content := json.CommonFailure("表单验证失败, 请检测输入")
+ if len(errs) == 0 {
+ return
+ }
+ json := utils.JsonResponse{}
+ content := json.CommonFailure("表单验证失败, 请检测输入")
- ctx.Resp.Write([]byte(content))
+ ctx.Resp.Write([]byte(content))
}
func Create(ctx *macaron.Context) {
- if app.Installed {
- ctx.Redirect("/")
- }
- ctx.Data["Title"] = "安装"
- ctx.Data["DisableNav"] = true
- ctx.HTML(200, "install/create")
+ if app.Installed {
+ ctx.Redirect("/")
+ }
+ ctx.Data["Title"] = "安装"
+ ctx.Data["DisableNav"] = true
+ ctx.HTML(200, "install/create")
}
// 安装
func Store(ctx *macaron.Context, form InstallForm) string {
- json := utils.JsonResponse{}
- if app.Installed {
- return json.CommonFailure("系统已安装!")
- }
- if form.AdminPassword != form.ConfirmAdminPassword {
- return json.CommonFailure("两次输入密码不匹配")
- }
- err := testDbConnection(form)
- if err != nil {
- return json.CommonFailure("数据库连接失败", err)
- }
- // 写入数据库配置
- err = writeConfig(form)
- if err != nil {
- return json.CommonFailure("数据库配置写入文件失败", err)
- }
+ json := utils.JsonResponse{}
+ if app.Installed {
+ return json.CommonFailure("系统已安装!")
+ }
+ if form.AdminPassword != form.ConfirmAdminPassword {
+ return json.CommonFailure("两次输入密码不匹配")
+ }
+ err := testDbConnection(form)
+ if err != nil {
+ return json.CommonFailure("数据库连接失败", err)
+ }
+ // 写入数据库配置
+ err = writeConfig(form)
+ if err != nil {
+ return json.CommonFailure("数据库配置写入文件失败", err)
+ }
- appConfig, err := setting.Read(app.AppConfig)
- if err != nil {
- return json.CommonFailure("读取应用配置失败", err)
- }
- app.Setting = appConfig
+ appConfig, err := setting.Read(app.AppConfig)
+ if err != nil {
+ return json.CommonFailure("读取应用配置失败", err)
+ }
+ app.Setting = appConfig
- models.Db = models.CreateDb()
- // 创建数据库表
- migration := new(models.Migration)
- err = migration.Install(form.DbName)
- if err != nil {
- return json.CommonFailure(fmt.Sprintf("创建数据库表失败-%s", err.Error()), err)
- }
+ models.Db = models.CreateDb()
+ // 创建数据库表
+ migration := new(models.Migration)
+ err = migration.Install(form.DbName)
+ if err != nil {
+ return json.CommonFailure(fmt.Sprintf("创建数据库表失败-%s", err.Error()), err)
+ }
- // 创建管理员账号
- err = createAdminUser(form)
- if err != nil {
- return json.CommonFailure("创建管理员账号失败", err)
- }
+ // 创建管理员账号
+ err = createAdminUser(form)
+ if err != nil {
+ return json.CommonFailure("创建管理员账号失败", err)
+ }
- // 创建安装锁
- err = app.CreateInstallLock()
- if err != nil {
- return json.CommonFailure("创建文件安装锁失败", err)
- }
+ // 创建安装锁
+ err = app.CreateInstallLock()
+ if err != nil {
+ return json.CommonFailure("创建文件安装锁失败", err)
+ }
- // 更新版本号文件
- app.UpdateVersionFile()
+ // 更新版本号文件
+ app.UpdateVersionFile()
- app.Installed = true
- // 初始化定时任务
- serviceTask := new(service.Task)
- serviceTask.Initialize()
+ app.Installed = true
+ // 初始化定时任务
+ serviceTask := new(service.Task)
+ serviceTask.Initialize()
- return json.Success("安装成功", nil)
+ return json.Success("安装成功", nil)
}
// 配置写入文件
func writeConfig(form InstallForm) error {
- dbConfig := []string{
- "db.engine", form.DbType,
- "db.host", form.DbHost,
- "db.port", strconv.Itoa(form.DbPort),
- "db.user", form.DbUsername,
- "db.password",form.DbPassword,
- "db.database", form.DbName,
- "db.prefix", form.DbTablePrefix,
- "db.charset", "utf8",
- "db.max.idle.conns", "30",
- "db.max.open.conns", "100",
- "allow_ips", "",
- "app.name", "定时任务管理系统", // 应用名称
- "api.key", "",
- "api.secret", "",
- "enable_tls", "false",
- "ca_file", "",
- "cert_file", "",
- "key_file", "",
- }
+ dbConfig := []string{
+ "db.engine", form.DbType,
+ "db.host", form.DbHost,
+ "db.port", strconv.Itoa(form.DbPort),
+ "db.user", form.DbUsername,
+ "db.password", form.DbPassword,
+ "db.database", form.DbName,
+ "db.prefix", form.DbTablePrefix,
+ "db.charset", "utf8",
+ "db.max.idle.conns", "30",
+ "db.max.open.conns", "100",
+ "allow_ips", "",
+ "app.name", "定时任务管理系统", // 应用名称
+ "api.key", "",
+ "api.secret", "",
+ "enable_tls", "false",
+ "ca_file", "",
+ "cert_file", "",
+ "key_file", "",
+ }
- return setting.Write(dbConfig, app.AppConfig)
+ return setting.Write(dbConfig, app.AppConfig)
}
// 创建管理员账号
func createAdminUser(form InstallForm) error {
- user := new(models.User)
- user.Name = form.AdminUsername
- user.Password = form.AdminPassword
- user.Email = form.AdminEmail
- user.IsAdmin = 1
- _, err := user.Create()
+ user := new(models.User)
+ user.Name = form.AdminUsername
+ user.Password = form.AdminPassword
+ user.Email = form.AdminEmail
+ user.IsAdmin = 1
+ _, err := user.Create()
- return err
+ return err
}
// 测试数据库连接
func testDbConnection(form InstallForm) error {
- var s setting.Setting
- s.Db.Engine = form.DbType
- s.Db.Host = form.DbHost
- s.Db.Port = form.DbPort
- s.Db.User = form.DbUsername
- s.Db.Password = form.DbPassword
- s.Db.Charset = "utf8"
- db, err := models.CreateTmpDb(&s)
- if err != nil {
- return err
- }
+ var s setting.Setting
+ s.Db.Engine = form.DbType
+ s.Db.Host = form.DbHost
+ s.Db.Port = form.DbPort
+ s.Db.User = form.DbUsername
+ s.Db.Password = form.DbPassword
+ s.Db.Charset = "utf8"
+ db, err := models.CreateTmpDb(&s)
+ if err != nil {
+ return err
+ }
- defer db.Close()
- err = db.Ping()
+ defer db.Close()
+ err = db.Ping()
- return err
+ return err
-}
\ No newline at end of file
+}
diff --git a/routers/loginlog/login_log.go b/routers/loginlog/login_log.go
index 1b6e1e2..e8c5a9f 100644
--- a/routers/loginlog/login_log.go
+++ b/routers/loginlog/login_log.go
@@ -1,30 +1,30 @@
package loginlog
import (
- "gopkg.in/macaron.v1"
- "github.com/Unknwon/paginater"
- "fmt"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/ouqiang/gocron/models"
- "github.com/ouqiang/gocron/routers/base"
- "html/template"
+ "fmt"
+ "github.com/Unknwon/paginater"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/routers/base"
+ "gopkg.in/macaron.v1"
+ "html/template"
)
-func Index(ctx *macaron.Context) {
- loginLogModel := new(models.LoginLog)
- params := models.CommonMap{}
- base.ParsePageAndPageSize(ctx, params)
- total, err := loginLogModel.Total()
- loginLogs, err := loginLogModel.List(params)
- if err != nil {
- logger.Error(err)
- }
- PageParams := fmt.Sprintf("page_size=%d", params["PageSize"]);
- params["PageParams"] = template.URL(PageParams)
- p := paginater.New(int(total), params["PageSize"].(int), params["Page"].(int), 5)
- ctx.Data["Pagination"] = p
- ctx.Data["Title"] = "登录日志"
- ctx.Data["LoginLogs"] = loginLogs
- ctx.Data["Params"] = params
- ctx.HTML(200, "manage/login_log")
-}
\ No newline at end of file
+func Index(ctx *macaron.Context) {
+ loginLogModel := new(models.LoginLog)
+ params := models.CommonMap{}
+ base.ParsePageAndPageSize(ctx, params)
+ total, err := loginLogModel.Total()
+ loginLogs, err := loginLogModel.List(params)
+ if err != nil {
+ logger.Error(err)
+ }
+ PageParams := fmt.Sprintf("page_size=%d", params["PageSize"])
+ params["PageParams"] = template.URL(PageParams)
+ p := paginater.New(int(total), params["PageSize"].(int), params["Page"].(int), 5)
+ ctx.Data["Pagination"] = p
+ ctx.Data["Title"] = "登录日志"
+ ctx.Data["LoginLogs"] = loginLogs
+ ctx.Data["Params"] = params
+ ctx.HTML(200, "manage/login_log")
+}
diff --git a/routers/manage/manage.go b/routers/manage/manage.go
index 1ea6290..eb1637e 100644
--- a/routers/manage/manage.go
+++ b/routers/manage/manage.go
@@ -1,138 +1,136 @@
package manage
import (
- "gopkg.in/macaron.v1"
- "github.com/ouqiang/gocron/modules/utils"
- "github.com/ouqiang/gocron/models"
- "github.com/ouqiang/gocron/modules/logger"
- "encoding/json"
+ "encoding/json"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/utils"
+ "gopkg.in/macaron.v1"
)
-
// region slack
-func EditSlack(ctx *macaron.Context) {
- ctx.Data["Title"] = "Slack配置"
- settingModel := new(models.Setting)
- slack, err := settingModel.Slack()
- if err != nil {
- logger.Error(err)
- }
- ctx.Data["Slack"] = slack
- ctx.HTML(200, "manage/slack")
+func EditSlack(ctx *macaron.Context) {
+ ctx.Data["Title"] = "Slack配置"
+ settingModel := new(models.Setting)
+ slack, err := settingModel.Slack()
+ if err != nil {
+ logger.Error(err)
+ }
+ ctx.Data["Slack"] = slack
+ ctx.HTML(200, "manage/slack")
}
func Slack(ctx *macaron.Context) string {
- settingModel := new(models.Setting)
- slack, err := settingModel.Slack()
- if err != nil {
- logger.Error(err)
- }
- json := utils.JsonResponse{}
+ settingModel := new(models.Setting)
+ slack, err := settingModel.Slack()
+ if err != nil {
+ logger.Error(err)
+ }
+ json := utils.JsonResponse{}
- return json.Success("", slack)
+ return json.Success("", slack)
}
func UpdateSlackUrl(ctx *macaron.Context) string {
- url := ctx.QueryTrim("url")
- settingModel := new(models.Setting)
- _, err := settingModel.UpdateSlackUrl(url)
+ url := ctx.QueryTrim("url")
+ settingModel := new(models.Setting)
+ _, err := settingModel.UpdateSlackUrl(url)
- return utils.JsonResponseByErr(err)
+ return utils.JsonResponseByErr(err)
}
-func CreateSlackChannel(ctx *macaron.Context) string {
- channel := ctx.QueryTrim("channel")
- settingModel := new(models.Setting)
- if settingModel.IsChannelExist(channel) {
- json := utils.JsonResponse{}
+func CreateSlackChannel(ctx *macaron.Context) string {
+ channel := ctx.QueryTrim("channel")
+ settingModel := new(models.Setting)
+ if settingModel.IsChannelExist(channel) {
+ json := utils.JsonResponse{}
- return json.CommonFailure("Channel已存在")
- }
- _, err := settingModel.CreateChannel(channel)
+ return json.CommonFailure("Channel已存在")
+ }
+ _, err := settingModel.CreateChannel(channel)
- return utils.JsonResponseByErr(err)
+ return utils.JsonResponseByErr(err)
}
-func RemoveSlackChannel(ctx *macaron.Context) string {
- id := ctx.ParamsInt(":id")
- settingModel := new(models.Setting)
- _, err := settingModel.RemoveChannel(id)
+func RemoveSlackChannel(ctx *macaron.Context) string {
+ id := ctx.ParamsInt(":id")
+ settingModel := new(models.Setting)
+ _, err := settingModel.RemoveChannel(id)
- return utils.JsonResponseByErr(err)
+ return utils.JsonResponseByErr(err)
}
// endregion
// region 邮件
-func EditMail(ctx *macaron.Context) {
- ctx.Data["Title"] = "邮件配置"
- settingModel := new(models.Setting)
- mail, err := settingModel.Mail()
- if err != nil {
- logger.Error(err)
- }
- ctx.Data["Mail"] = mail
- ctx.HTML(200, "manage/mail")
+func EditMail(ctx *macaron.Context) {
+ ctx.Data["Title"] = "邮件配置"
+ settingModel := new(models.Setting)
+ mail, err := settingModel.Mail()
+ if err != nil {
+ logger.Error(err)
+ }
+ ctx.Data["Mail"] = mail
+ ctx.HTML(200, "manage/mail")
}
func Mail(ctx *macaron.Context) string {
- settingModel := new(models.Setting)
- mail, err := settingModel.Mail()
- if err != nil {
- logger.Error(err)
- }
+ settingModel := new(models.Setting)
+ mail, err := settingModel.Mail()
+ if err != nil {
+ logger.Error(err)
+ }
- json := utils.JsonResponse{}
+ json := utils.JsonResponse{}
- return json.Success("", mail)
+ return json.Success("", mail)
}
-
type MailServerForm struct {
- Host string `binding:"Required;MaxSize(100)"`
- Port int `binding:"Required;Range(1-65535)"`
- User string `binding:"Required;MaxSize(64);Email"`
- Password string `binding:"Required;MaxSize(64)"`
+ Host string `binding:"Required;MaxSize(100)"`
+ Port int `binding:"Required;Range(1-65535)"`
+ User string `binding:"Required;MaxSize(64);Email"`
+ Password string `binding:"Required;MaxSize(64)"`
}
func UpdateMailServer(ctx *macaron.Context, form MailServerForm) string {
- jsonByte, _ := json.Marshal(form)
- settingModel := new(models.Setting)
- _, err := settingModel.UpdateMailServer(string(jsonByte))
+ jsonByte, _ := json.Marshal(form)
+ settingModel := new(models.Setting)
+ _, err := settingModel.UpdateMailServer(string(jsonByte))
- return utils.JsonResponseByErr(err)
+ return utils.JsonResponseByErr(err)
}
func ClearMailServer(ctx *macaron.Context) string {
- jsonByte, _ := json.Marshal(MailServerForm{})
- settingModel := new(models.Setting)
- _, err := settingModel.UpdateMailServer(string(jsonByte))
+ jsonByte, _ := json.Marshal(MailServerForm{})
+ settingModel := new(models.Setting)
+ _, err := settingModel.UpdateMailServer(string(jsonByte))
- return utils.JsonResponseByErr(err)
+ return utils.JsonResponseByErr(err)
}
-func CreateMailUser(ctx *macaron.Context) string {
- username := ctx.QueryTrim("username")
- email := ctx.QueryTrim("email")
- settingModel := new(models.Setting)
- if username == "" || email == "" {
- json := utils.JsonResponse{}
+func CreateMailUser(ctx *macaron.Context) string {
+ username := ctx.QueryTrim("username")
+ email := ctx.QueryTrim("email")
+ settingModel := new(models.Setting)
+ if username == "" || email == "" {
+ json := utils.JsonResponse{}
- return json.CommonFailure("用户名、邮箱均不能为空")
- }
- _, err := settingModel.CreateMailUser(username, email)
+ return json.CommonFailure("用户名、邮箱均不能为空")
+ }
+ _, err := settingModel.CreateMailUser(username, email)
- return utils.JsonResponseByErr(err)
+ return utils.JsonResponseByErr(err)
}
-func RemoveMailUser(ctx *macaron.Context) string {
- id := ctx.ParamsInt(":id")
- settingModel := new(models.Setting)
- _, err := settingModel.RemoveMailUser(id)
+func RemoveMailUser(ctx *macaron.Context) string {
+ id := ctx.ParamsInt(":id")
+ settingModel := new(models.Setting)
+ _, err := settingModel.RemoveMailUser(id)
- return utils.JsonResponseByErr(err)
+ return utils.JsonResponseByErr(err)
}
-// endregion
\ No newline at end of file
+// endregion
diff --git a/routers/routers.go b/routers/routers.go
index 4fd7a7f..1238dc5 100644
--- a/routers/routers.go
+++ b/routers/routers.go
@@ -1,27 +1,27 @@
package routers
import (
- "github.com/go-macaron/binding"
- "github.com/ouqiang/gocron/routers/install"
- "gopkg.in/macaron.v1"
- "github.com/ouqiang/gocron/routers/task"
- "github.com/ouqiang/gocron/routers/host"
- "github.com/ouqiang/gocron/routers/tasklog"
- "github.com/ouqiang/gocron/modules/utils"
- "github.com/go-macaron/session"
- "github.com/go-macaron/toolbox"
- "strings"
- "github.com/ouqiang/gocron/modules/app"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/ouqiang/gocron/routers/user"
- "github.com/go-macaron/gzip"
- "github.com/ouqiang/gocron/routers/manage"
- "github.com/ouqiang/gocron/routers/loginlog"
- "time"
- "strconv"
- "html/template"
- "github.com/go-macaron/cache"
- "github.com/go-macaron/captcha"
+ "github.com/go-macaron/binding"
+ "github.com/go-macaron/cache"
+ "github.com/go-macaron/captcha"
+ "github.com/go-macaron/gzip"
+ "github.com/go-macaron/session"
+ "github.com/go-macaron/toolbox"
+ "github.com/ouqiang/gocron/modules/app"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/utils"
+ "github.com/ouqiang/gocron/routers/host"
+ "github.com/ouqiang/gocron/routers/install"
+ "github.com/ouqiang/gocron/routers/loginlog"
+ "github.com/ouqiang/gocron/routers/manage"
+ "github.com/ouqiang/gocron/routers/task"
+ "github.com/ouqiang/gocron/routers/tasklog"
+ "github.com/ouqiang/gocron/routers/user"
+ "gopkg.in/macaron.v1"
+ "html/template"
+ "strconv"
+ "strings"
+ "time"
)
// 静态文件目录
@@ -29,261 +29,261 @@ const StaticDir = "public"
// 路由注册
func Register(m *macaron.Macaron) {
- // 所有GET方法,自动注册HEAD方法
- m.SetAutoHead(true)
- // 首页
- m.Get("/", Home)
- // 系统安装
- m.Group("/install", func() {
- m.Get("", install.Create)
- m.Post("/store", binding.Bind(install.InstallForm{}), install.Store)
- })
+ // 所有GET方法,自动注册HEAD方法
+ m.SetAutoHead(true)
+ // 首页
+ m.Get("/", Home)
+ // 系统安装
+ m.Group("/install", func() {
+ m.Get("", install.Create)
+ m.Post("/store", binding.Bind(install.InstallForm{}), install.Store)
+ })
- // 用户
- m.Group("/user", func() {
- m.Get("/login", user.Login)
- m.Post("/login", user.ValidateLogin)
- m.Get("/logout", user.Logout)
- m.Get("/editPassword", user.EditPassword)
- m.Post("/editPassword", user.UpdatePassword)
- })
+ // 用户
+ m.Group("/user", func() {
+ m.Get("/login", user.Login)
+ m.Post("/login", user.ValidateLogin)
+ m.Get("/logout", user.Logout)
+ m.Get("/editPassword", user.EditPassword)
+ m.Post("/editPassword", user.UpdatePassword)
+ })
- // 定时任务
- m.Group("/task", func() {
- m.Get("/create", task.Create)
- m.Post("/store", binding.Bind(task.TaskForm{}), task.Store)
- m.Get("/edit/:id", task.Edit)
- m.Get("", task.Index)
- m.Get("/log", tasklog.Index)
- m.Post("/log/clear", tasklog.Clear)
- m.Post("/remove/:id", task.Remove)
- m.Post("/enable/:id", task.Enable)
- m.Post("/disable/:id", task.Disable)
- m.Get("/run/:id", task.Run)
- })
+ // 定时任务
+ m.Group("/task", func() {
+ m.Get("/create", task.Create)
+ m.Post("/store", binding.Bind(task.TaskForm{}), task.Store)
+ m.Get("/edit/:id", task.Edit)
+ m.Get("", task.Index)
+ m.Get("/log", tasklog.Index)
+ m.Post("/log/clear", tasklog.Clear)
+ m.Post("/remove/:id", task.Remove)
+ m.Post("/enable/:id", task.Enable)
+ m.Post("/disable/:id", task.Disable)
+ m.Get("/run/:id", task.Run)
+ })
- // 主机
- m.Group("/host", func() {
- m.Get("/create", host.Create)
- m.Get("/edit/:id", host.Edit)
- m.Post("/store", binding.Bind(host.HostForm{}), host.Store)
- m.Get("", host.Index)
- m.Get("/ping/:id", host.Ping)
- m.Post("/remove/:id", host.Remove)
- })
+ // 主机
+ m.Group("/host", func() {
+ m.Get("/create", host.Create)
+ m.Get("/edit/:id", host.Edit)
+ m.Post("/store", binding.Bind(host.HostForm{}), host.Store)
+ m.Get("", host.Index)
+ m.Get("/ping/:id", host.Ping)
+ m.Post("/remove/:id", host.Remove)
+ })
- // 管理
- m.Group("/manage", func() {
- m.Group("/slack", func() {
- m.Get("/", manage.Slack)
- m.Get("/edit", manage.EditSlack)
- m.Post("/url", manage.UpdateSlackUrl)
- m.Post("/channel", manage.CreateSlackChannel)
- m.Post("/channel/remove/:id", manage.RemoveSlackChannel)
- })
- m.Group("/mail", func() {
- m.Get("/", manage.Mail)
- m.Get("/edit", manage.EditMail)
- m.Post("/server", binding.Bind(manage.MailServerForm{}), manage.UpdateMailServer)
- m.Post("/server/clear", manage.ClearMailServer)
- m.Post("/user", manage.CreateMailUser)
- m.Post("/user/remove/:id", manage.RemoveMailUser)
- })
- m.Get("/login-log", loginlog.Index)
- })
+ // 管理
+ m.Group("/manage", func() {
+ m.Group("/slack", func() {
+ m.Get("/", manage.Slack)
+ m.Get("/edit", manage.EditSlack)
+ m.Post("/url", manage.UpdateSlackUrl)
+ m.Post("/channel", manage.CreateSlackChannel)
+ m.Post("/channel/remove/:id", manage.RemoveSlackChannel)
+ })
+ m.Group("/mail", func() {
+ m.Get("/", manage.Mail)
+ m.Get("/edit", manage.EditMail)
+ m.Post("/server", binding.Bind(manage.MailServerForm{}), manage.UpdateMailServer)
+ m.Post("/server/clear", manage.ClearMailServer)
+ m.Post("/user", manage.CreateMailUser)
+ m.Post("/user/remove/:id", manage.RemoveMailUser)
+ })
+ m.Get("/login-log", loginlog.Index)
+ })
- // API
- m.Group("/api/v1", func() {
- m.Post("/tasklog/remove/:id", tasklog.Remove)
- m.Post("/task/enable/:id", task.Enable)
- m.Post("/task/disable/:id", task.Disable)
- }, apiAuth);
+ // API
+ m.Group("/api/v1", func() {
+ m.Post("/tasklog/remove/:id", tasklog.Remove)
+ m.Post("/task/enable/:id", task.Enable)
+ m.Post("/task/disable/:id", task.Disable)
+ }, apiAuth)
- // 404错误
- m.NotFound(func(ctx *macaron.Context) {
- if isGetRequest(ctx) && !isAjaxRequest(ctx) {
- ctx.Data["Title"] = "404 - NOT FOUND"
- ctx.HTML(404, "error/404")
- } else {
- json := utils.JsonResponse{}
- ctx.Resp.Write([]byte(json.Failure(utils.NotFound, "您访问的地址不存在")))
- }
- })
- // 50x错误
- m.InternalServerError(func(ctx *macaron.Context) {
- logger.Debug("500错误")
- if isGetRequest(ctx) && !isAjaxRequest(ctx) {
- ctx.Data["Title"] = "500 - INTERNAL SERVER ERROR"
- ctx.HTML(500, "error/500")
- } else {
- json := utils.JsonResponse{}
- ctx.Resp.Write([]byte(json.Failure(utils.ServerError, "网站暂时无法访问,请稍后再试")))
- }
- })
+ // 404错误
+ m.NotFound(func(ctx *macaron.Context) {
+ if isGetRequest(ctx) && !isAjaxRequest(ctx) {
+ ctx.Data["Title"] = "404 - NOT FOUND"
+ ctx.HTML(404, "error/404")
+ } else {
+ json := utils.JsonResponse{}
+ ctx.Resp.Write([]byte(json.Failure(utils.NotFound, "您访问的地址不存在")))
+ }
+ })
+ // 50x错误
+ m.InternalServerError(func(ctx *macaron.Context) {
+ logger.Debug("500错误")
+ if isGetRequest(ctx) && !isAjaxRequest(ctx) {
+ ctx.Data["Title"] = "500 - INTERNAL SERVER ERROR"
+ ctx.HTML(500, "error/500")
+ } else {
+ json := utils.JsonResponse{}
+ ctx.Resp.Write([]byte(json.Failure(utils.ServerError, "网站暂时无法访问,请稍后再试")))
+ }
+ })
}
// 中间件注册
func RegisterMiddleware(m *macaron.Macaron) {
- m.Use(macaron.Logger())
- m.Use(macaron.Recovery())
- if macaron.Env != macaron.DEV {
- m.Use(gzip.Gziper())
- }
- m.Use(macaron.Static(StaticDir))
- m.Use(macaron.Renderer(macaron.RenderOptions{
- Directory: "templates",
- Extensions: []string{".html"},
- // 模板语法分隔符,默认为 ["{{", "}}"]
- Delims: macaron.Delims{"{{{", "}}}"},
- // 追加的 Content-Type 头信息,默认为 "UTF-8"
- Charset: "UTF-8",
- // 渲染具有缩进格式的 JSON,默认为不缩进
- IndentJSON: true,
- // 渲染具有缩进格式的 XML,默认为不缩进
- IndentXML: true,
- Funcs: []template.FuncMap{map[string]interface{} {
- "HostFormat": func(index int) bool {
- return (index + 1) % 3 == 0
- },
- "unescape": func(str string) template.HTML {
- return template.HTML(str)
- },
- }},
- }))
- m.Use(cache.Cacher())
- m.Use(captcha.Captchaer())
- m.Use(session.Sessioner(session.Options{
- Provider: "file",
- ProviderConfig: app.DataDir + "/sessions",
- }))
- m.Use(toolbox.Toolboxer(m))
- checkAppInstall(m)
- m.Use(func(ctx *macaron.Context, sess session.Store){
- if app.Installed {
- ipAuth(ctx)
- userAuth(ctx, sess)
- setShareData(ctx, sess)
- }
- })
+ m.Use(macaron.Logger())
+ m.Use(macaron.Recovery())
+ if macaron.Env != macaron.DEV {
+ m.Use(gzip.Gziper())
+ }
+ m.Use(macaron.Static(StaticDir))
+ m.Use(macaron.Renderer(macaron.RenderOptions{
+ Directory: "templates",
+ Extensions: []string{".html"},
+ // 模板语法分隔符,默认为 ["{{", "}}"]
+ Delims: macaron.Delims{"{{{", "}}}"},
+ // 追加的 Content-Type 头信息,默认为 "UTF-8"
+ Charset: "UTF-8",
+ // 渲染具有缩进格式的 JSON,默认为不缩进
+ IndentJSON: true,
+ // 渲染具有缩进格式的 XML,默认为不缩进
+ IndentXML: true,
+ Funcs: []template.FuncMap{map[string]interface{}{
+ "HostFormat": func(index int) bool {
+ return (index+1)%3 == 0
+ },
+ "unescape": func(str string) template.HTML {
+ return template.HTML(str)
+ },
+ }},
+ }))
+ m.Use(cache.Cacher())
+ m.Use(captcha.Captchaer())
+ m.Use(session.Sessioner(session.Options{
+ Provider: "file",
+ ProviderConfig: app.DataDir + "/sessions",
+ }))
+ m.Use(toolbox.Toolboxer(m))
+ checkAppInstall(m)
+ m.Use(func(ctx *macaron.Context, sess session.Store) {
+ if app.Installed {
+ ipAuth(ctx)
+ userAuth(ctx, sess)
+ setShareData(ctx, sess)
+ }
+ })
}
// region 自定义中间件
/** 系统未安装,重定向到安装页面 **/
-func checkAppInstall(m *macaron.Macaron) {
- m.Use(func(ctx *macaron.Context) {
- installUrl := "/install"
- if strings.HasPrefix(ctx.Req.URL.Path, installUrl) {
- return
- }
- if !app.Installed {
- ctx.Redirect(installUrl)
- }
- })
+func checkAppInstall(m *macaron.Macaron) {
+ m.Use(func(ctx *macaron.Context) {
+ installUrl := "/install"
+ if strings.HasPrefix(ctx.Req.URL.Path, installUrl) {
+ return
+ }
+ if !app.Installed {
+ ctx.Redirect(installUrl)
+ }
+ })
}
// IP验证, 通过反向代理访问gocron,需设置Header X-Real-IP才能获取到客户端真实IP
-func ipAuth(ctx *macaron.Context) {
- allowIpsStr := app.Setting.AllowIps
- if allowIpsStr == "" {
- return
- }
- clientIp := ctx.RemoteAddr()
- allowIps := strings.Split(allowIpsStr, ",")
- if !utils.InStringSlice(allowIps, clientIp) {
- logger.Warnf("非法IP访问-%s", clientIp)
- ctx.Status(403)
- }
+func ipAuth(ctx *macaron.Context) {
+ allowIpsStr := app.Setting.AllowIps
+ if allowIpsStr == "" {
+ return
+ }
+ clientIp := ctx.RemoteAddr()
+ allowIps := strings.Split(allowIpsStr, ",")
+ if !utils.InStringSlice(allowIps, clientIp) {
+ logger.Warnf("非法IP访问-%s", clientIp)
+ ctx.Status(403)
+ }
}
// 用户认证
-func userAuth(ctx *macaron.Context, sess session.Store) {
- if user.IsLogin(sess) {
- return
- }
- uri := ctx.Req.URL.Path
- found := false
- excludePaths := []string{"/install", "/user/login", "/api"}
- for _, path := range excludePaths {
- if strings.HasPrefix(uri, path) {
- found = true
- break
- }
- }
- if !found {
- ctx.Redirect("/user/login")
- }
+func userAuth(ctx *macaron.Context, sess session.Store) {
+ if user.IsLogin(sess) {
+ return
+ }
+ uri := ctx.Req.URL.Path
+ found := false
+ excludePaths := []string{"/install", "/user/login", "/api"}
+ for _, path := range excludePaths {
+ if strings.HasPrefix(uri, path) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ ctx.Redirect("/user/login")
+ }
}
/** 设置共享数据 **/
-func setShareData(ctx *macaron.Context, sess session.Store) {
- ctx.Data["URI"] = ctx.Req.URL.Path
- urlPath := strings.TrimPrefix(ctx.Req.URL.Path, "/")
- paths := strings.Split(urlPath, "/")
- ctx.Data["Controller"] = ""
- ctx.Data["Action"] = ""
- if len(paths) > 0 {
- ctx.Data["Controller"] = paths[0]
- }
- if len(paths) > 1 {
- ctx.Data["Action"] = paths[1]
- }
- ctx.Data["LoginUsername"] = user.Username(sess)
- ctx.Data["LoginUid"] = user.Uid(sess)
- ctx.Data["AppName"] = app.Setting.AppName
+func setShareData(ctx *macaron.Context, sess session.Store) {
+ ctx.Data["URI"] = ctx.Req.URL.Path
+ urlPath := strings.TrimPrefix(ctx.Req.URL.Path, "/")
+ paths := strings.Split(urlPath, "/")
+ ctx.Data["Controller"] = ""
+ ctx.Data["Action"] = ""
+ if len(paths) > 0 {
+ ctx.Data["Controller"] = paths[0]
+ }
+ if len(paths) > 1 {
+ ctx.Data["Action"] = paths[1]
+ }
+ ctx.Data["LoginUsername"] = user.Username(sess)
+ ctx.Data["LoginUid"] = user.Uid(sess)
+ ctx.Data["AppName"] = app.Setting.AppName
}
/** API接口签名验证 **/
-func apiAuth(ctx *macaron.Context) {
- if !app.Setting.ApiSignEnable {
- return
- }
- apiKey := strings.TrimSpace(app.Setting.ApiKey)
- apiSecret := strings.TrimSpace(app.Setting.ApiSecret)
- json := utils.JsonResponse{}
- if apiKey == "" || apiSecret == "" {
- msg := json.CommonFailure("使用API前, 请先配置密钥")
- ctx.Write([]byte(msg))
- return
- }
- currentTimestamp := time.Now().Unix()
- time := ctx.QueryInt64("time")
- if time <= 0 {
- msg := json.CommonFailure("参数time不能为空")
- ctx.Write([]byte(msg))
- return
- }
- if time < (currentTimestamp - 1800) {
- msg := json.CommonFailure("time无效")
- ctx.Write([]byte(msg))
- return
- }
- sign := ctx.QueryTrim("sign")
- if sign == "" {
- msg := json.CommonFailure("参数sign不能为空")
- ctx.Write([]byte(msg))
- return
- }
- raw := apiKey + strconv.FormatInt(time, 10) + strings.TrimSpace(ctx.Req.URL.Path) + apiSecret
- realSign := utils.Md5(raw)
- if sign != realSign {
- msg := json.CommonFailure("签名验证失败")
- ctx.Write([]byte(msg))
- return
- }
+func apiAuth(ctx *macaron.Context) {
+ if !app.Setting.ApiSignEnable {
+ return
+ }
+ apiKey := strings.TrimSpace(app.Setting.ApiKey)
+ apiSecret := strings.TrimSpace(app.Setting.ApiSecret)
+ json := utils.JsonResponse{}
+ if apiKey == "" || apiSecret == "" {
+ msg := json.CommonFailure("使用API前, 请先配置密钥")
+ ctx.Write([]byte(msg))
+ return
+ }
+ currentTimestamp := time.Now().Unix()
+ time := ctx.QueryInt64("time")
+ if time <= 0 {
+ msg := json.CommonFailure("参数time不能为空")
+ ctx.Write([]byte(msg))
+ return
+ }
+ if time < (currentTimestamp - 1800) {
+ msg := json.CommonFailure("time无效")
+ ctx.Write([]byte(msg))
+ return
+ }
+ sign := ctx.QueryTrim("sign")
+ if sign == "" {
+ msg := json.CommonFailure("参数sign不能为空")
+ ctx.Write([]byte(msg))
+ return
+ }
+ raw := apiKey + strconv.FormatInt(time, 10) + strings.TrimSpace(ctx.Req.URL.Path) + apiSecret
+ realSign := utils.Md5(raw)
+ if sign != realSign {
+ msg := json.CommonFailure("签名验证失败")
+ ctx.Write([]byte(msg))
+ return
+ }
}
// endregion
func isAjaxRequest(ctx *macaron.Context) bool {
- req := ctx.Req.Header.Get("X-Requested-With")
- if req == "XMLHttpRequest" {
- return true
- }
+ req := ctx.Req.Header.Get("X-Requested-With")
+ if req == "XMLHttpRequest" {
+ return true
+ }
- return false
+ return false
}
func isGetRequest(ctx *macaron.Context) bool {
- return ctx.Req.Method == "GET"
-}
\ No newline at end of file
+ return ctx.Req.Method == "GET"
+}
diff --git a/routers/task/task.go b/routers/task/task.go
index b35cd8d..f8f6cc3 100644
--- a/routers/task/task.go
+++ b/routers/task/task.go
@@ -1,335 +1,334 @@
package task
import (
- "gopkg.in/macaron.v1"
- "github.com/ouqiang/gocron/models"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/ouqiang/gocron/modules/utils"
- "github.com/ouqiang/gocron/service"
- "strconv"
- "github.com/jakecoffman/cron"
- "github.com/Unknwon/paginater"
- "fmt"
- "html/template"
- "github.com/ouqiang/gocron/routers/base"
- "github.com/go-macaron/binding"
- "strings"
+ "fmt"
+ "github.com/Unknwon/paginater"
+ "github.com/go-macaron/binding"
+ "github.com/jakecoffman/cron"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/utils"
+ "github.com/ouqiang/gocron/routers/base"
+ "github.com/ouqiang/gocron/service"
+ "gopkg.in/macaron.v1"
+ "html/template"
+ "strconv"
+ "strings"
)
type TaskForm struct {
- Id int
- Level models.TaskLevel `binding:"Required;In(1,2)"`
- DependencyStatus models.TaskDependencyStatus
- DependencyTaskId string
- Name string `binding:"Required;MaxSize(32)"`
- Spec string
- Protocol models.TaskProtocol `binding:"In(1,2)"`
- Command string `binding:"Required;MaxSize(256)"`
- Timeout int `binding:"Range(0,86400)"`
- Multi int8 `binding:"In(1,2)"`
- RetryTimes int8
- HostId string
- Tag string
- Remark string
- NotifyStatus int8 `binding:"In(1,2,3)"`
- NotifyType int8 `binding:"In(1,2,3)"`
- NotifyReceiverId string
+ Id int
+ Level models.TaskLevel `binding:"Required;In(1,2)"`
+ DependencyStatus models.TaskDependencyStatus
+ DependencyTaskId string
+ Name string `binding:"Required;MaxSize(32)"`
+ Spec string
+ Protocol models.TaskProtocol `binding:"In(1,2)"`
+ Command string `binding:"Required;MaxSize(256)"`
+ Timeout int `binding:"Range(0,86400)"`
+ Multi int8 `binding:"In(1,2)"`
+ RetryTimes int8
+ HostId string
+ Tag string
+ Remark string
+ NotifyStatus int8 `binding:"In(1,2,3)"`
+ NotifyType int8 `binding:"In(1,2,3)"`
+ NotifyReceiverId string
}
-
func (f TaskForm) Error(ctx *macaron.Context, errs binding.Errors) {
- if len(errs) == 0 {
- return
- }
- json := utils.JsonResponse{}
- content := json.CommonFailure("表单验证失败, 请检测输入")
+ if len(errs) == 0 {
+ return
+ }
+ json := utils.JsonResponse{}
+ content := json.CommonFailure("表单验证失败, 请检测输入")
- ctx.Resp.Write([]byte(content))
+ ctx.Resp.Write([]byte(content))
}
// 首页
-func Index(ctx *macaron.Context) {
- taskModel := new(models.Task)
- queryParams := parseQueryParams(ctx)
- total, err := taskModel.Total(queryParams)
- if err != nil {
- logger.Error(err)
- }
- tasks, err := taskModel.List(queryParams)
- if err != nil {
- logger.Error(err)
- }
- name, ok := queryParams["name"].(string)
- var safeNameHTML = ""
- if ok {
- safeNameHTML = template.HTMLEscapeString(name)
- }
- PageParams := fmt.Sprintf("id=%d&host_id=%d&name=%s&protocol=%d&tag=%s&status=%d&page_size=%d",
- queryParams["Id"], queryParams["HostId"], safeNameHTML, queryParams["Protocol"], queryParams["Tag"], queryParams["Status"], queryParams["PageSize"]);
- queryParams["PageParams"] = template.URL(PageParams)
- p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
- ctx.Data["Pagination"] = p
- setHostsToTemplate(ctx)
- ctx.Data["Params"] = queryParams
- ctx.Data["Title"] = "任务列表"
- ctx.Data["Tasks"] = tasks
- ctx.HTML(200, "task/index")
+func Index(ctx *macaron.Context) {
+ taskModel := new(models.Task)
+ queryParams := parseQueryParams(ctx)
+ total, err := taskModel.Total(queryParams)
+ if err != nil {
+ logger.Error(err)
+ }
+ tasks, err := taskModel.List(queryParams)
+ if err != nil {
+ logger.Error(err)
+ }
+ name, ok := queryParams["name"].(string)
+ var safeNameHTML = ""
+ if ok {
+ safeNameHTML = template.HTMLEscapeString(name)
+ }
+ PageParams := fmt.Sprintf("id=%d&host_id=%d&name=%s&protocol=%d&tag=%s&status=%d&page_size=%d",
+ queryParams["Id"], queryParams["HostId"], safeNameHTML, queryParams["Protocol"], queryParams["Tag"], queryParams["Status"], queryParams["PageSize"])
+ queryParams["PageParams"] = template.URL(PageParams)
+ p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
+ ctx.Data["Pagination"] = p
+ setHostsToTemplate(ctx)
+ ctx.Data["Params"] = queryParams
+ ctx.Data["Title"] = "任务列表"
+ ctx.Data["Tasks"] = tasks
+ ctx.HTML(200, "task/index")
}
// 新增页面
-func Create(ctx *macaron.Context) {
- setHostsToTemplate(ctx)
- ctx.Data["Title"] = "添加任务"
- ctx.HTML(200, "task/task_form")
+func Create(ctx *macaron.Context) {
+ setHostsToTemplate(ctx)
+ ctx.Data["Title"] = "添加任务"
+ ctx.HTML(200, "task/task_form")
}
// 编辑页面
-func Edit(ctx *macaron.Context) {
- id := ctx.ParamsInt(":id")
- taskModel := new(models.Task)
- task, err := taskModel.Detail(id)
- if err != nil || task.Id != id {
- logger.Errorf("编辑任务#获取任务详情失败#任务ID-%d#%s", id, err.Error())
- ctx.Redirect("/task")
- }
- hostModel := new(models.Host)
- hostModel.PageSize = -1
- hosts, err := hostModel.List(models.CommonMap{})
- if err != nil {
- logger.Error(err)
- } else {
- for i, host := range(hosts) {
- if inHosts(task.Hosts, host.Id) {
- hosts[i].Selected = true
- }
- }
- }
+func Edit(ctx *macaron.Context) {
+ id := ctx.ParamsInt(":id")
+ taskModel := new(models.Task)
+ task, err := taskModel.Detail(id)
+ if err != nil || task.Id != id {
+ logger.Errorf("编辑任务#获取任务详情失败#任务ID-%d#%s", id, err.Error())
+ ctx.Redirect("/task")
+ }
+ hostModel := new(models.Host)
+ hostModel.PageSize = -1
+ hosts, err := hostModel.List(models.CommonMap{})
+ if err != nil {
+ logger.Error(err)
+ } else {
+ for i, host := range hosts {
+ if inHosts(task.Hosts, host.Id) {
+ hosts[i].Selected = true
+ }
+ }
+ }
- ctx.Data["Task"] = task
- ctx.Data["Hosts"] = hosts
- ctx.Data["Title"] = "编辑"
- ctx.HTML(200, "task/task_form")
+ ctx.Data["Task"] = task
+ ctx.Data["Hosts"] = hosts
+ ctx.Data["Title"] = "编辑"
+ ctx.HTML(200, "task/task_form")
}
// 保存任务
-func Store(ctx *macaron.Context, form TaskForm) string {
- json := utils.JsonResponse{}
- taskModel := models.Task{}
- var id int = form.Id
- nameExists, err := taskModel.NameExist(form.Name, form.Id)
- if err != nil {
- return json.CommonFailure(utils.FailureContent, err)
- }
- if nameExists {
- return json.CommonFailure("任务名称已存在")
- }
+func Store(ctx *macaron.Context, form TaskForm) string {
+ json := utils.JsonResponse{}
+ taskModel := models.Task{}
+ var id int = form.Id
+ nameExists, err := taskModel.NameExist(form.Name, form.Id)
+ if err != nil {
+ return json.CommonFailure(utils.FailureContent, err)
+ }
+ if nameExists {
+ return json.CommonFailure("任务名称已存在")
+ }
- if form.Protocol == models.TaskRPC && form.HostId == "" {
- return json.CommonFailure("请选择主机名")
- }
+ if form.Protocol == models.TaskRPC && form.HostId == "" {
+ return json.CommonFailure("请选择主机名")
+ }
- taskModel.Name = form.Name
- taskModel.Protocol = form.Protocol
- taskModel.Command = form.Command
- taskModel.Timeout = form.Timeout
- taskModel.Tag = form.Tag
- taskModel.Remark = form.Remark
- taskModel.Multi = form.Multi
- taskModel.RetryTimes = form.RetryTimes
- if taskModel.Multi != 1 {
- taskModel.Multi = 0
- }
- taskModel.NotifyStatus = form.NotifyStatus - 1
- taskModel.NotifyType = form.NotifyType - 1
- taskModel.NotifyReceiverId = form.NotifyReceiverId
- taskModel.Spec = form.Spec
- taskModel.Level = form.Level
- taskModel.DependencyStatus = form.DependencyStatus
- taskModel.DependencyTaskId = strings.TrimSpace(form.DependencyTaskId)
- if taskModel.NotifyStatus > 0 && taskModel.NotifyReceiverId == "" {
- return json.CommonFailure("至少选择一个通知接收者")
- }
- if taskModel.Protocol == models.TaskHTTP {
- command := strings.ToLower(taskModel.Command)
- if !strings.HasPrefix(command, "http://") && !strings.HasPrefix(command, "https://") {
- return json.CommonFailure("请输入正确的URL地址")
- }
- if taskModel.Timeout > 300 {
- return json.CommonFailure("HTTP任务超时时间不能超过300秒")
- }
- }
+ taskModel.Name = form.Name
+ taskModel.Protocol = form.Protocol
+ taskModel.Command = form.Command
+ taskModel.Timeout = form.Timeout
+ taskModel.Tag = form.Tag
+ taskModel.Remark = form.Remark
+ taskModel.Multi = form.Multi
+ taskModel.RetryTimes = form.RetryTimes
+ if taskModel.Multi != 1 {
+ taskModel.Multi = 0
+ }
+ taskModel.NotifyStatus = form.NotifyStatus - 1
+ taskModel.NotifyType = form.NotifyType - 1
+ taskModel.NotifyReceiverId = form.NotifyReceiverId
+ taskModel.Spec = form.Spec
+ taskModel.Level = form.Level
+ taskModel.DependencyStatus = form.DependencyStatus
+ taskModel.DependencyTaskId = strings.TrimSpace(form.DependencyTaskId)
+ if taskModel.NotifyStatus > 0 && taskModel.NotifyReceiverId == "" {
+ return json.CommonFailure("至少选择一个通知接收者")
+ }
+ if taskModel.Protocol == models.TaskHTTP {
+ command := strings.ToLower(taskModel.Command)
+ if !strings.HasPrefix(command, "http://") && !strings.HasPrefix(command, "https://") {
+ return json.CommonFailure("请输入正确的URL地址")
+ }
+ if taskModel.Timeout > 300 {
+ return json.CommonFailure("HTTP任务超时时间不能超过300秒")
+ }
+ }
- if taskModel.RetryTimes > 10 || taskModel.RetryTimes < 0 {
- return json.CommonFailure("任务重试次数取值0-10")
- }
+ if taskModel.RetryTimes > 10 || taskModel.RetryTimes < 0 {
+ return json.CommonFailure("任务重试次数取值0-10")
+ }
- if (taskModel.DependencyStatus != models.TaskDependencyStatusStrong &&
- taskModel.DependencyStatus != models.TaskDependencyStatusWeak) {
- return json.CommonFailure("请选择依赖关系")
- }
+ if taskModel.DependencyStatus != models.TaskDependencyStatusStrong &&
+ taskModel.DependencyStatus != models.TaskDependencyStatusWeak {
+ return json.CommonFailure("请选择依赖关系")
+ }
- if taskModel.Level == models.TaskLevelParent {
- _, err = cron.Parse(form.Spec)
- if err != nil {
- return json.CommonFailure("crontab表达式解析失败", err)
- }
- } else {
- taskModel.DependencyTaskId = ""
- taskModel.Spec = ""
- }
+ if taskModel.Level == models.TaskLevelParent {
+ _, err = cron.Parse(form.Spec)
+ if err != nil {
+ return json.CommonFailure("crontab表达式解析失败", err)
+ }
+ } else {
+ taskModel.DependencyTaskId = ""
+ taskModel.Spec = ""
+ }
- if id > 0 && taskModel.DependencyTaskId != "" {
- dependencyTaskIds := strings.Split(taskModel.DependencyTaskId, ",")
- if utils.InStringSlice(dependencyTaskIds, strconv.Itoa(id)) {
- return json.CommonFailure("不允许设置当前任务为子任务")
- }
- }
+ if id > 0 && taskModel.DependencyTaskId != "" {
+ dependencyTaskIds := strings.Split(taskModel.DependencyTaskId, ",")
+ if utils.InStringSlice(dependencyTaskIds, strconv.Itoa(id)) {
+ return json.CommonFailure("不允许设置当前任务为子任务")
+ }
+ }
- if id == 0 {
- // 任务添加后开始调度执行
- taskModel.Status = models.Running
- id, err = taskModel.Create()
- } else {
- _, err = taskModel.UpdateBean(id)
- }
+ if id == 0 {
+ // 任务添加后开始调度执行
+ taskModel.Status = models.Running
+ id, err = taskModel.Create()
+ } else {
+ _, err = taskModel.UpdateBean(id)
+ }
- if err != nil {
- return json.CommonFailure("保存失败", err)
- }
+ if err != nil {
+ return json.CommonFailure("保存失败", err)
+ }
- taskHostModel := new(models.TaskHost)
- if form.Protocol == models.TaskRPC {
- hostIdStrList := strings.Split(form.HostId, ",")
- hostIds := make([]int, len(hostIdStrList))
- for i, hostIdStr := range hostIdStrList {
- hostIds[i], _ = strconv.Atoi(hostIdStr)
- }
- taskHostModel.Add(id, hostIds)
- } else {
- taskHostModel.Remove(id)
- }
+ taskHostModel := new(models.TaskHost)
+ if form.Protocol == models.TaskRPC {
+ hostIdStrList := strings.Split(form.HostId, ",")
+ hostIds := make([]int, len(hostIdStrList))
+ for i, hostIdStr := range hostIdStrList {
+ hostIds[i], _ = strconv.Atoi(hostIdStr)
+ }
+ taskHostModel.Add(id, hostIds)
+ } else {
+ taskHostModel.Remove(id)
+ }
- status, err := taskModel.GetStatus(id)
- if status == models.Enabled && taskModel.Level == models.TaskLevelParent {
- addTaskToTimer(id)
- }
+ status, err := taskModel.GetStatus(id)
+ if status == models.Enabled && taskModel.Level == models.TaskLevelParent {
+ addTaskToTimer(id)
+ }
- return json.Success("保存成功", nil)
+ return json.Success("保存成功", nil)
}
// 删除任务
func Remove(ctx *macaron.Context) string {
- id := ctx.ParamsInt(":id")
- json := utils.JsonResponse{}
- taskModel := new(models.Task)
- _, err := taskModel.Delete(id)
- if err != nil {
- return json.CommonFailure(utils.FailureContent, err)
- }
+ id := ctx.ParamsInt(":id")
+ json := utils.JsonResponse{}
+ taskModel := new(models.Task)
+ _, err := taskModel.Delete(id)
+ if err != nil {
+ return json.CommonFailure(utils.FailureContent, err)
+ }
- taskHostModel := new(models.TaskHost)
- taskHostModel.Remove(id)
+ taskHostModel := new(models.TaskHost)
+ taskHostModel.Remove(id)
- service.Cron.RemoveJob(strconv.Itoa(id))
+ service.Cron.RemoveJob(strconv.Itoa(id))
- return json.Success(utils.SuccessContent, nil)
+ return json.Success(utils.SuccessContent, nil)
}
// 激活任务
func Enable(ctx *macaron.Context) string {
- return changeStatus(ctx, models.Enabled)
+ return changeStatus(ctx, models.Enabled)
}
// 暂停任务
func Disable(ctx *macaron.Context) string {
- return changeStatus(ctx, models.Disabled)
+ return changeStatus(ctx, models.Disabled)
}
// 手动运行任务
func Run(ctx *macaron.Context) string {
- id := ctx.ParamsInt(":id")
- json := utils.JsonResponse{}
- taskModel := new(models.Task)
- task , err := taskModel.Detail(id)
- if err != nil || task.Id <= 0 {
- return json.CommonFailure("获取任务详情失败", err)
- }
+ id := ctx.ParamsInt(":id")
+ json := utils.JsonResponse{}
+ taskModel := new(models.Task)
+ task, err := taskModel.Detail(id)
+ if err != nil || task.Id <= 0 {
+ return json.CommonFailure("获取任务详情失败", err)
+ }
- task.Spec = "手动运行"
- serviceTask := new(service.Task)
- serviceTask.Run(task)
+ task.Spec = "手动运行"
+ serviceTask := new(service.Task)
+ serviceTask.Run(task)
- return json.Success("任务已开始运行, 请到任务日志中查看结果", nil);
+ return json.Success("任务已开始运行, 请到任务日志中查看结果", nil)
}
// 改变任务状态
func changeStatus(ctx *macaron.Context, status models.Status) string {
- id := ctx.ParamsInt(":id")
- json := utils.JsonResponse{}
- taskModel := new(models.Task)
- _, err := taskModel.Update(id, models.CommonMap{
- "Status": status,
- })
- if err != nil {
- return json.CommonFailure(utils.FailureContent, err)
- }
+ id := ctx.ParamsInt(":id")
+ json := utils.JsonResponse{}
+ taskModel := new(models.Task)
+ _, err := taskModel.Update(id, models.CommonMap{
+ "Status": status,
+ })
+ if err != nil {
+ return json.CommonFailure(utils.FailureContent, err)
+ }
- if status == models.Enabled {
- addTaskToTimer(id)
- } else {
- service.Cron.RemoveJob(strconv.Itoa(id))
- }
+ if status == models.Enabled {
+ addTaskToTimer(id)
+ } else {
+ service.Cron.RemoveJob(strconv.Itoa(id))
+ }
- return json.Success(utils.SuccessContent, nil)
+ return json.Success(utils.SuccessContent, nil)
}
// 添加任务到定时器
-func addTaskToTimer(id int) {
- taskModel := new(models.Task)
- task, err := taskModel.Detail(id)
- if err != nil {
- logger.Error(err)
- return
- }
+func addTaskToTimer(id int) {
+ taskModel := new(models.Task)
+ task, err := taskModel.Detail(id)
+ if err != nil {
+ logger.Error(err)
+ return
+ }
- taskService := service.Task{}
- taskService.Add(task)
+ taskService := service.Task{}
+ taskService.Add(task)
}
// 解析查询参数
-func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
- var params models.CommonMap = models.CommonMap{}
- params["Id"] = ctx.QueryInt("id")
- params["HostId"] = ctx.QueryInt("host_id")
- params["Name"] = ctx.QueryTrim("name")
- params["Protocol"] = ctx.QueryInt("protocol")
- params["Tag"] = ctx.QueryTrim("tag")
- status := ctx.QueryInt("status")
- if status >=0 {
- status -= 1
- }
- params["Status"] = status
- base.ParsePageAndPageSize(ctx, params)
+func parseQueryParams(ctx *macaron.Context) models.CommonMap {
+ var params models.CommonMap = models.CommonMap{}
+ params["Id"] = ctx.QueryInt("id")
+ params["HostId"] = ctx.QueryInt("host_id")
+ params["Name"] = ctx.QueryTrim("name")
+ params["Protocol"] = ctx.QueryInt("protocol")
+ params["Tag"] = ctx.QueryTrim("tag")
+ status := ctx.QueryInt("status")
+ if status >= 0 {
+ status -= 1
+ }
+ params["Status"] = status
+ base.ParsePageAndPageSize(ctx, params)
- return params
+ return params
}
-func setHostsToTemplate(ctx *macaron.Context) {
- hostModel := new(models.Host)
- hostModel.PageSize = -1
- hosts, err := hostModel.List(models.CommonMap{})
- if err != nil {
- logger.Error(err)
- }
- ctx.Data["Hosts"] = hosts
+func setHostsToTemplate(ctx *macaron.Context) {
+ hostModel := new(models.Host)
+ hostModel.PageSize = -1
+ hosts, err := hostModel.List(models.CommonMap{})
+ if err != nil {
+ logger.Error(err)
+ }
+ ctx.Data["Hosts"] = hosts
}
func inHosts(slice []models.TaskHostDetail, element int16) bool {
- for _, v := range slice {
- if v.HostId == element {
- return true
- }
- }
+ for _, v := range slice {
+ if v.HostId == element {
+ return true
+ }
+ }
- return false
-}
\ No newline at end of file
+ return false
+}
diff --git a/routers/tasklog/task_log.go b/routers/tasklog/task_log.go
index dc7dfb3..6fa5d79 100644
--- a/routers/tasklog/task_log.go
+++ b/routers/tasklog/task_log.go
@@ -3,78 +3,78 @@ package tasklog
// 任务日志
import (
- "gopkg.in/macaron.v1"
- "github.com/ouqiang/gocron/models"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/ouqiang/gocron/modules/utils"
- "github.com/Unknwon/paginater"
- "fmt"
- "html/template"
- "github.com/ouqiang/gocron/routers/base"
+ "fmt"
+ "github.com/Unknwon/paginater"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/utils"
+ "github.com/ouqiang/gocron/routers/base"
+ "gopkg.in/macaron.v1"
+ "html/template"
)
-func Index(ctx *macaron.Context) {
- logModel := new(models.TaskLog)
- queryParams := parseQueryParams(ctx)
- total, err := logModel.Total(queryParams)
- if err != nil {
- logger.Error(err)
- }
- logs, err := logModel.List(queryParams)
- if err != nil {
- logger.Error(err)
- }
- PageParams := fmt.Sprintf("task_id=%d&protocol=%d&status=%d&page_size=%d",
- queryParams["TaskId"], queryParams["Protocol"], queryParams["Status"],
- queryParams["PageSize"]);
- queryParams["PageParams"] = template.URL(PageParams)
- p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
- ctx.Data["Pagination"] = p
- ctx.Data["Title"] = "任务日志"
- ctx.Data["Logs"] = logs
- ctx.Data["Params"] = queryParams
- ctx.HTML(200, "task/log")
+func Index(ctx *macaron.Context) {
+ logModel := new(models.TaskLog)
+ queryParams := parseQueryParams(ctx)
+ total, err := logModel.Total(queryParams)
+ if err != nil {
+ logger.Error(err)
+ }
+ logs, err := logModel.List(queryParams)
+ if err != nil {
+ logger.Error(err)
+ }
+ PageParams := fmt.Sprintf("task_id=%d&protocol=%d&status=%d&page_size=%d",
+ queryParams["TaskId"], queryParams["Protocol"], queryParams["Status"],
+ queryParams["PageSize"])
+ queryParams["PageParams"] = template.URL(PageParams)
+ p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
+ ctx.Data["Pagination"] = p
+ ctx.Data["Title"] = "任务日志"
+ ctx.Data["Logs"] = logs
+ ctx.Data["Params"] = queryParams
+ ctx.HTML(200, "task/log")
}
// 清空日志
-func Clear(ctx *macaron.Context) string {
- taskLogModel := new(models.TaskLog)
- _, err := taskLogModel.Clear()
- json := utils.JsonResponse{}
- if err != nil {
- return json.CommonFailure(utils.FailureContent)
- }
+func Clear(ctx *macaron.Context) string {
+ taskLogModel := new(models.TaskLog)
+ _, err := taskLogModel.Clear()
+ json := utils.JsonResponse{}
+ if err != nil {
+ return json.CommonFailure(utils.FailureContent)
+ }
- return json.Success(utils.SuccessContent, nil)
+ return json.Success(utils.SuccessContent, nil)
}
// 删除N个月前的日志
func Remove(ctx *macaron.Context) string {
- month := ctx.ParamsInt(":id")
- json := utils.JsonResponse{}
- if month < 1 || month > 12 {
- return json.CommonFailure("参数取值范围1-12")
- }
- taskLogModel := new(models.TaskLog)
- _, err := taskLogModel.Remove(month)
- if err != nil {
- return json.CommonFailure("删除失败", err)
- }
+ month := ctx.ParamsInt(":id")
+ json := utils.JsonResponse{}
+ if month < 1 || month > 12 {
+ return json.CommonFailure("参数取值范围1-12")
+ }
+ taskLogModel := new(models.TaskLog)
+ _, err := taskLogModel.Remove(month)
+ if err != nil {
+ return json.CommonFailure("删除失败", err)
+ }
- return json.Success("删除成功", nil)
+ return json.Success("删除成功", nil)
}
// 解析查询参数
-func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
- var params models.CommonMap = models.CommonMap{}
- params["TaskId"] = ctx.QueryInt("task_id")
- params["Protocol"] = ctx.QueryInt("protocol")
- status := ctx.QueryInt("status")
- if status >=0 {
- status -= 1
- }
- params["Status"] = status
- base.ParsePageAndPageSize(ctx, params)
+func parseQueryParams(ctx *macaron.Context) models.CommonMap {
+ var params models.CommonMap = models.CommonMap{}
+ params["TaskId"] = ctx.QueryInt("task_id")
+ params["Protocol"] = ctx.QueryInt("protocol")
+ status := ctx.QueryInt("status")
+ if status >= 0 {
+ status -= 1
+ }
+ params["Status"] = status
+ base.ParsePageAndPageSize(ctx, params)
- return params
-}
\ No newline at end of file
+ return params
+}
diff --git a/routers/user/user.go b/routers/user/user.go
index 45707d3..5aa89aa 100644
--- a/routers/user/user.go
+++ b/routers/user/user.go
@@ -1,127 +1,126 @@
package user
import (
- "gopkg.in/macaron.v1"
- "github.com/ouqiang/gocron/modules/utils"
- "github.com/ouqiang/gocron/models"
- "github.com/go-macaron/session"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/go-macaron/captcha"
+ "github.com/go-macaron/captcha"
+ "github.com/go-macaron/session"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/utils"
+ "gopkg.in/macaron.v1"
)
// @author qiang.ou
// @date 2017/4/23-14:16
-func Login(ctx *macaron.Context) {
- ctx.Data["Title"] = "用户登录"
- ctx.HTML(200, "user/login")
+func Login(ctx *macaron.Context) {
+ ctx.Data["Title"] = "用户登录"
+ ctx.HTML(200, "user/login")
}
-func EditPassword(ctx *macaron.Context) {
- ctx.Data["Title"] = "修改密码"
- ctx.HTML(200, "user/editPassword")
+func EditPassword(ctx *macaron.Context) {
+ ctx.Data["Title"] = "修改密码"
+ ctx.HTML(200, "user/editPassword")
}
-func UpdatePassword(ctx *macaron.Context, sess session.Store) string {
- oldPassword := ctx.QueryTrim("old_password")
- newPassword := ctx.QueryTrim("new_password")
- confirmNewPassword := ctx.QueryTrim("confirm_new_password")
- json := utils.JsonResponse{}
- if oldPassword == "" || newPassword == "" || confirmNewPassword == "" {
- return json.CommonFailure("原密码和新密码均不能为空")
- }
- if newPassword != confirmNewPassword {
- return json.CommonFailure("两次输入密码不一致")
- }
- if oldPassword == newPassword {
- return json.CommonFailure("原密码与新密码不能相同")
- }
- userModel := new(models.User)
- if !userModel.Match(Username(sess), oldPassword) {
- return json.CommonFailure("原密码输入错误")
- }
- _, err := userModel.UpdatePassword(Uid(sess), newPassword)
- if err != nil {
- return json.CommonFailure("修改失败")
- }
+func UpdatePassword(ctx *macaron.Context, sess session.Store) string {
+ oldPassword := ctx.QueryTrim("old_password")
+ newPassword := ctx.QueryTrim("new_password")
+ confirmNewPassword := ctx.QueryTrim("confirm_new_password")
+ json := utils.JsonResponse{}
+ if oldPassword == "" || newPassword == "" || confirmNewPassword == "" {
+ return json.CommonFailure("原密码和新密码均不能为空")
+ }
+ if newPassword != confirmNewPassword {
+ return json.CommonFailure("两次输入密码不一致")
+ }
+ if oldPassword == newPassword {
+ return json.CommonFailure("原密码与新密码不能相同")
+ }
+ userModel := new(models.User)
+ if !userModel.Match(Username(sess), oldPassword) {
+ return json.CommonFailure("原密码输入错误")
+ }
+ _, err := userModel.UpdatePassword(Uid(sess), newPassword)
+ if err != nil {
+ return json.CommonFailure("修改失败")
+ }
- return json.Success("修改成功", nil)
+ return json.Success("修改成功", nil)
}
func ValidateLogin(ctx *macaron.Context, sess session.Store, cpt *captcha.Captcha) string {
- username := ctx.QueryTrim("username")
- password := ctx.QueryTrim("password")
- json := utils.JsonResponse{}
- if username == "" || password == "" {
- return json.CommonFailure("用户名、密码不能为空")
- }
- userModel := new (models.User)
- if !userModel.Match(username, password) {
- return json.CommonFailure("用户名或密码错误")
- }
- if !cpt.VerifyReq(ctx.Req) {
- return json.Failure(utils.CaptchaError, "验证码错误")
- }
+ username := ctx.QueryTrim("username")
+ password := ctx.QueryTrim("password")
+ json := utils.JsonResponse{}
+ if username == "" || password == "" {
+ return json.CommonFailure("用户名、密码不能为空")
+ }
+ userModel := new(models.User)
+ if !userModel.Match(username, password) {
+ return json.CommonFailure("用户名或密码错误")
+ }
+ if !cpt.VerifyReq(ctx.Req) {
+ return json.Failure(utils.CaptchaError, "验证码错误")
+ }
- loginLogModel := new(models.LoginLog)
- loginLogModel.Username = userModel.Name
- loginLogModel.Ip = ctx.RemoteAddr()
- _, err := loginLogModel.Create()
- if err != nil {
- logger.Error("记录用户登录日志失败", err)
- }
+ loginLogModel := new(models.LoginLog)
+ loginLogModel.Username = userModel.Name
+ loginLogModel.Ip = ctx.RemoteAddr()
+ _, err := loginLogModel.Create()
+ if err != nil {
+ logger.Error("记录用户登录日志失败", err)
+ }
+ sess.Set("username", userModel.Name)
+ sess.Set("uid", userModel.Id)
+ sess.Set("isAdmin", userModel.IsAdmin)
- sess.Set("username", userModel.Name)
- sess.Set("uid", userModel.Id)
- sess.Set("isAdmin", userModel.IsAdmin)
-
- return json.Success("登录成功", nil)
+ return json.Success("登录成功", nil)
}
func Logout(ctx *macaron.Context, sess session.Store) {
- if IsLogin(sess) {
- err := sess.Destory(ctx)
- if err != nil {
- logger.Error("用户退出登录失败", err)
- }
- }
+ if IsLogin(sess) {
+ err := sess.Destory(ctx)
+ if err != nil {
+ logger.Error("用户退出登录失败", err)
+ }
+ }
- Login(ctx)
+ Login(ctx)
}
-func Username(sess session.Store) string {
- username,ok := sess.Get("username").(string)
- if ok {
- return username
- }
+func Username(sess session.Store) string {
+ username, ok := sess.Get("username").(string)
+ if ok {
+ return username
+ }
- return ""
+ return ""
}
-func Uid(sess session.Store) int {
- uid,ok := sess.Get("uid").(int)
- if ok {
- return uid
- }
+func Uid(sess session.Store) int {
+ uid, ok := sess.Get("uid").(int)
+ if ok {
+ return uid
+ }
- return 0
+ return 0
}
-func IsLogin(sess session.Store) bool {
- uid, ok := sess.Get("uid").(int)
- if ok && uid > 0 {
- return true
- }
+func IsLogin(sess session.Store) bool {
+ uid, ok := sess.Get("uid").(int)
+ if ok && uid > 0 {
+ return true
+ }
- return false
+ return false
}
-func IsAdmin(sess session.Store) bool {
- isAdmin, ok := sess.Get("isAdmin").(int8)
- if ok && isAdmin > 0 {
- return true
- }
+func IsAdmin(sess session.Store) bool {
+ isAdmin, ok := sess.Get("isAdmin").(int8)
+ if ok && isAdmin > 0 {
+ return true
+ }
- return false
-}
\ No newline at end of file
+ return false
+}
diff --git a/service/task.go b/service/task.go
index ca2d403..2ce94f6 100644
--- a/service/task.go
+++ b/service/task.go
@@ -1,154 +1,155 @@
package service
import (
- "github.com/ouqiang/gocron/models"
- "strconv"
- "time"
- "github.com/ouqiang/gocron/modules/logger"
- "github.com/jakecoffman/cron"
- "errors"
- "fmt"
- "github.com/ouqiang/gocron/modules/httpclient"
- "github.com/ouqiang/gocron/modules/notify"
- "sync"
- rpcClient "github.com/ouqiang/gocron/modules/rpc/client"
- pb "github.com/ouqiang/gocron/modules/rpc/proto"
- "strings"
+ "errors"
+ "fmt"
+ "github.com/jakecoffman/cron"
+ "github.com/ouqiang/gocron/models"
+ "github.com/ouqiang/gocron/modules/httpclient"
+ "github.com/ouqiang/gocron/modules/logger"
+ "github.com/ouqiang/gocron/modules/notify"
+ rpcClient "github.com/ouqiang/gocron/modules/rpc/client"
+ pb "github.com/ouqiang/gocron/modules/rpc/proto"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
)
// 定时任务调度管理器
var Cron *cron.Cron
+
// 同一任务是否有实例处于运行中
var runInstance Instance
+
// 任务计数-正在运行中的任务
var TaskNum TaskCount
// 任务计数
type TaskCount struct {
- num int
- sync.RWMutex
+ num int
+ sync.RWMutex
}
-func (c *TaskCount) Add() {
- c.Lock()
- defer c.Unlock()
- c.num += 1
+func (c *TaskCount) Add() {
+ c.Lock()
+ defer c.Unlock()
+ c.num += 1
}
-func (c *TaskCount) Done() {
- c.Lock()
- defer c.Unlock()
- c.num -= 1
+func (c *TaskCount) Done() {
+ c.Lock()
+ defer c.Unlock()
+ c.num -= 1
}
-func (c *TaskCount) Num() int {
- c.RLock()
- defer c.RUnlock()
+func (c *TaskCount) Num() int {
+ c.RLock()
+ defer c.RUnlock()
- return c.num
+ return c.num
}
// 任务ID作为Key
type Instance struct {
- Status map[int]bool
- sync.RWMutex
+ Status map[int]bool
+ sync.RWMutex
}
// 是否有任务处于运行中
func (i *Instance) has(key int) bool {
- i.RLock()
- defer i.RUnlock()
- running, ok := i.Status[key]
- if ok && running {
- return true
- }
+ i.RLock()
+ defer i.RUnlock()
+ running, ok := i.Status[key]
+ if ok && running {
+ return true
+ }
- return false
+ return false
}
-func (i *Instance) add(key int) {
- i.Lock()
- defer i.Unlock()
- i.Status[key] = true
+func (i *Instance) add(key int) {
+ i.Lock()
+ defer i.Unlock()
+ i.Status[key] = true
}
-func (i *Instance) done(key int) {
- i.Lock()
- defer i.Unlock()
- delete(i.Status, key)
+func (i *Instance) done(key int) {
+ i.Lock()
+ defer i.Unlock()
+ delete(i.Status, key)
}
type Task struct{}
type TaskResult struct {
- Result string
- Err error
- RetryTimes int8
+ Result string
+ Err error
+ RetryTimes int8
}
// 初始化任务, 从数据库取出所有任务, 添加到定时任务并运行
func (task *Task) Initialize() {
- Cron = cron.New()
- Cron.Start()
- runInstance = Instance{make(map[int]bool), sync.RWMutex{}}
- TaskNum = TaskCount{0, sync.RWMutex{}}
+ Cron = cron.New()
+ Cron.Start()
+ runInstance = Instance{make(map[int]bool), sync.RWMutex{}}
+ TaskNum = TaskCount{0, sync.RWMutex{}}
- taskModel := new(models.Task)
- taskList, err := taskModel.ActiveList()
- if err != nil {
- logger.Error("定时任务初始化#获取任务列表错误-", err.Error())
- return
- }
- if len(taskList) == 0 {
- logger.Debug("任务列表为空")
- return
- }
- task.BatchAdd(taskList)
+ taskModel := new(models.Task)
+ taskList, err := taskModel.ActiveList()
+ if err != nil {
+ logger.Error("定时任务初始化#获取任务列表错误-", err.Error())
+ return
+ }
+ if len(taskList) == 0 {
+ logger.Debug("任务列表为空")
+ return
+ }
+ task.BatchAdd(taskList)
}
// 批量添加任务
-func (task *Task) BatchAdd(tasks []models.Task) {
- for _, item := range tasks {
- task.Add(item)
- }
+func (task *Task) BatchAdd(tasks []models.Task) {
+ for _, item := range tasks {
+ task.Add(item)
+ }
}
// 添加任务
func (task *Task) Add(taskModel models.Task) {
- if taskModel.Level == models.TaskLevelChild {
- logger.Errorf("添加任务失败#不允许添加子任务到调度器#任务Id-%d", taskModel.Id);
- return
- }
- taskFunc := createJob(taskModel)
- if taskFunc == nil {
- logger.Error("创建任务处理Job失败,不支持的任务协议#", taskModel.Protocol)
- return
- }
+ if taskModel.Level == models.TaskLevelChild {
+ logger.Errorf("添加任务失败#不允许添加子任务到调度器#任务Id-%d", taskModel.Id)
+ return
+ }
+ taskFunc := createJob(taskModel)
+ if taskFunc == nil {
+ logger.Error("创建任务处理Job失败,不支持的任务协议#", taskModel.Protocol)
+ return
+ }
- cronName := strconv.Itoa(taskModel.Id)
- // Cron任务采用数组存储, 删除任务需遍历数组, 并对数组重新赋值, 任务较多时,有性能问题
- Cron.RemoveJob(cronName)
- err := Cron.AddFunc(taskModel.Spec, taskFunc, cronName)
- if err != nil {
- logger.Error("添加任务到调度器失败#", err)
- }
+ cronName := strconv.Itoa(taskModel.Id)
+ // Cron任务采用数组存储, 删除任务需遍历数组, 并对数组重新赋值, 任务较多时,有性能问题
+ Cron.RemoveJob(cronName)
+ err := Cron.AddFunc(taskModel.Spec, taskFunc, cronName)
+ if err != nil {
+ logger.Error("添加任务到调度器失败#", err)
+ }
}
// 停止所有任务
-func (task *Task) StopAll() {
- Cron.Stop()
+func (task *Task) StopAll() {
+ Cron.Stop()
}
// 直接运行任务
-func (task *Task) Run(taskModel models.Task) {
- go createJob(taskModel)()
+func (task *Task) Run(taskModel models.Task) {
+ go createJob(taskModel)()
}
type Handler interface {
- Run(taskModel models.Task) (string, error)
+ Run(taskModel models.Task) (string, error)
}
-
// HTTP任务
type HTTPHandler struct{}
@@ -156,259 +157,257 @@ type HTTPHandler struct{}
const HttpExecTimeout = 300
func (h *HTTPHandler) Run(taskModel models.Task) (result string, err error) {
- if taskModel.Timeout <= 0 || taskModel.Timeout > HttpExecTimeout {
- taskModel.Timeout = HttpExecTimeout
- }
- resp := httpclient.Get(taskModel.Command, taskModel.Timeout)
- // 返回状态码非200,均为失败
- if resp.StatusCode != 200 {
- return resp.Body, errors.New(fmt.Sprintf("HTTP状态码非200-->%d", resp.StatusCode))
- }
+ if taskModel.Timeout <= 0 || taskModel.Timeout > HttpExecTimeout {
+ taskModel.Timeout = HttpExecTimeout
+ }
+ resp := httpclient.Get(taskModel.Command, taskModel.Timeout)
+ // 返回状态码非200,均为失败
+ if resp.StatusCode != 200 {
+ return resp.Body, errors.New(fmt.Sprintf("HTTP状态码非200-->%d", resp.StatusCode))
+ }
- return resp.Body, err
+ return resp.Body, err
}
// RPC调用执行任务
-type RPCHandler struct {}
+type RPCHandler struct{}
-func (h *RPCHandler) Run(taskModel models.Task) (result string, err error) {
- taskRequest := new(pb.TaskRequest)
- taskRequest.Timeout = int32(taskModel.Timeout)
- taskRequest.Command = taskModel.Command
- var resultChan chan TaskResult = make(chan TaskResult, len(taskModel.Hosts))
- for _, taskHost := range taskModel.Hosts {
- go func(th models.TaskHostDetail) {
- output, err := rpcClient.ExecWithRetry(th.Name, th.Port, taskRequest)
- var errorMessage string = ""
- if err != nil {
- errorMessage = err.Error()
- }
- outputMessage := fmt.Sprintf("主机: [%s-%s]\n%s\n%s\n\n",
- th.Alias, th.Name, errorMessage, output,
- )
- resultChan <- TaskResult{Err:err, Result: outputMessage}
- }(taskHost)
- }
+func (h *RPCHandler) Run(taskModel models.Task) (result string, err error) {
+ taskRequest := new(pb.TaskRequest)
+ taskRequest.Timeout = int32(taskModel.Timeout)
+ taskRequest.Command = taskModel.Command
+ var resultChan chan TaskResult = make(chan TaskResult, len(taskModel.Hosts))
+ for _, taskHost := range taskModel.Hosts {
+ go func(th models.TaskHostDetail) {
+ output, err := rpcClient.Exec(th.Name, th.Port, taskRequest)
+ var errorMessage string = ""
+ if err != nil {
+ errorMessage = err.Error()
+ }
+ outputMessage := fmt.Sprintf("主机: [%s-%s]\n%s\n%s\n\n",
+ th.Alias, th.Name, errorMessage, output,
+ )
+ resultChan <- TaskResult{Err: err, Result: outputMessage}
+ }(taskHost)
+ }
- var aggregationErr error = nil
- var aggregationResult string = ""
- for i := 0; i < len(taskModel.Hosts); i++ {
- taskResult := <- resultChan
- aggregationResult += taskResult.Result
- if taskResult.Err != nil {
- aggregationErr = taskResult.Err
- }
- }
+ var aggregationErr error = nil
+ var aggregationResult string = ""
+ for i := 0; i < len(taskModel.Hosts); i++ {
+ taskResult := <-resultChan
+ aggregationResult += taskResult.Result
+ if taskResult.Err != nil {
+ aggregationErr = taskResult.Err
+ }
+ }
- return aggregationResult, aggregationErr
+ return aggregationResult, aggregationErr
}
-
// 创建任务日志
func createTaskLog(taskModel models.Task, status models.Status) (int64, error) {
- taskLogModel := new(models.TaskLog)
- taskLogModel.TaskId = taskModel.Id
- taskLogModel.Name = taskModel.Name
- taskLogModel.Spec = taskModel.Spec
- taskLogModel.Protocol = taskModel.Protocol
- taskLogModel.Command = taskModel.Command
- taskLogModel.Timeout = taskModel.Timeout
- if taskModel.Protocol == models.TaskRPC {
- var aggregationHost string = ""
- for _, host := range taskModel.Hosts {
- aggregationHost += fmt.Sprintf("%s-%s
", host.Alias, host.Name)
- }
- taskLogModel.Hostname = aggregationHost
- }
- taskLogModel.StartTime = time.Now()
- taskLogModel.Status = status
- insertId, err := taskLogModel.Create()
+ taskLogModel := new(models.TaskLog)
+ taskLogModel.TaskId = taskModel.Id
+ taskLogModel.Name = taskModel.Name
+ taskLogModel.Spec = taskModel.Spec
+ taskLogModel.Protocol = taskModel.Protocol
+ taskLogModel.Command = taskModel.Command
+ taskLogModel.Timeout = taskModel.Timeout
+ if taskModel.Protocol == models.TaskRPC {
+ var aggregationHost string = ""
+ for _, host := range taskModel.Hosts {
+ aggregationHost += fmt.Sprintf("%s-%s
", host.Alias, host.Name)
+ }
+ taskLogModel.Hostname = aggregationHost
+ }
+ taskLogModel.StartTime = time.Now()
+ taskLogModel.Status = status
+ insertId, err := taskLogModel.Create()
- return insertId, err
+ return insertId, err
}
// 更新任务日志
func updateTaskLog(taskLogId int64, taskResult TaskResult) (int64, error) {
- taskLogModel := new(models.TaskLog)
- var status models.Status
- var result string = taskResult.Result
- if taskResult.Err != nil {
- status = models.Failure
- } else {
- status = models.Finish
- }
- return taskLogModel.Update(taskLogId, models.CommonMap{
- "retry_times": taskResult.RetryTimes,
- "status": status,
- "result": result,
- })
+ taskLogModel := new(models.TaskLog)
+ var status models.Status
+ var result string = taskResult.Result
+ if taskResult.Err != nil {
+ status = models.Failure
+ } else {
+ status = models.Finish
+ }
+ return taskLogModel.Update(taskLogId, models.CommonMap{
+ "retry_times": taskResult.RetryTimes,
+ "status": status,
+ "result": result,
+ })
}
func createJob(taskModel models.Task) cron.FuncJob {
- var handler Handler = createHandler(taskModel)
- if handler == nil {
- return nil
- }
- taskFunc := func() {
- TaskNum.Add()
- defer TaskNum.Done()
- taskLogId := beforeExecJob(taskModel)
- if taskLogId <= 0 {
- return
- }
- logger.Infof("开始执行任务#%s#命令-%s", taskModel.Name, taskModel.Command)
- taskResult := execJob(handler, taskModel)
- logger.Infof("任务完成#%s#命令-%s", taskModel.Name, taskModel.Command)
- afterExecJob(taskModel, taskResult, taskLogId)
- }
+ var handler Handler = createHandler(taskModel)
+ if handler == nil {
+ return nil
+ }
+ taskFunc := func() {
+ TaskNum.Add()
+ defer TaskNum.Done()
+ taskLogId := beforeExecJob(taskModel)
+ if taskLogId <= 0 {
+ return
+ }
+ logger.Infof("开始执行任务#%s#命令-%s", taskModel.Name, taskModel.Command)
+ taskResult := execJob(handler, taskModel)
+ logger.Infof("任务完成#%s#命令-%s", taskModel.Name, taskModel.Command)
+ afterExecJob(taskModel, taskResult, taskLogId)
+ }
- return taskFunc
+ return taskFunc
}
-func createHandler(taskModel models.Task) Handler {
- var handler Handler = nil
- switch taskModel.Protocol {
- case models.TaskHTTP:
- handler = new(HTTPHandler)
- case models.TaskRPC:
- handler = new(RPCHandler)
- }
+func createHandler(taskModel models.Task) Handler {
+ var handler Handler = nil
+ switch taskModel.Protocol {
+ case models.TaskHTTP:
+ handler = new(HTTPHandler)
+ case models.TaskRPC:
+ handler = new(RPCHandler)
+ }
-
- return handler;
+ return handler
}
// 任务前置操作
-func beforeExecJob(taskModel models.Task) (taskLogId int64) {
- if taskModel.Multi == 0 && runInstance.has(taskModel.Id) {
- createTaskLog(taskModel, models.Cancel)
- return
- }
- if taskModel.Multi == 0 {
- runInstance.add(taskModel.Id)
- }
- taskLogId, err := createTaskLog(taskModel, models.Running)
- if err != nil {
- logger.Error("任务开始执行#写入任务日志失败-", err)
- return
- }
+func beforeExecJob(taskModel models.Task) (taskLogId int64) {
+ if taskModel.Multi == 0 && runInstance.has(taskModel.Id) {
+ createTaskLog(taskModel, models.Cancel)
+ return
+ }
+ if taskModel.Multi == 0 {
+ runInstance.add(taskModel.Id)
+ }
+ taskLogId, err := createTaskLog(taskModel, models.Running)
+ if err != nil {
+ logger.Error("任务开始执行#写入任务日志失败-", err)
+ return
+ }
- logger.Debugf("任务命令-%s", taskModel.Command)
+ logger.Debugf("任务命令-%s", taskModel.Command)
- return taskLogId
+ return taskLogId
}
// 任务执行后置操作
-func afterExecJob(taskModel models.Task, taskResult TaskResult, taskLogId int64) {
- _, err := updateTaskLog(taskLogId, taskResult)
- if err != nil {
- logger.Error("任务结束#更新任务日志失败-", err)
- }
+func afterExecJob(taskModel models.Task, taskResult TaskResult, taskLogId int64) {
+ _, err := updateTaskLog(taskLogId, taskResult)
+ if err != nil {
+ logger.Error("任务结束#更新任务日志失败-", err)
+ }
- // 发送邮件
- go SendNotification(taskModel, taskResult)
- // 执行依赖任务
- go execDependencyTask(taskModel, taskResult)
+ // 发送邮件
+ go SendNotification(taskModel, taskResult)
+ // 执行依赖任务
+ go execDependencyTask(taskModel, taskResult)
}
// 执行依赖任务, 多个任务并发执行
-func execDependencyTask(taskModel models.Task, taskResult TaskResult) {
- // 父任务才能执行子任务
- if taskModel.Level != models.TaskLevelParent {
- return
- }
+func execDependencyTask(taskModel models.Task, taskResult TaskResult) {
+ // 父任务才能执行子任务
+ if taskModel.Level != models.TaskLevelParent {
+ return
+ }
- // 是否存在子任务
- dependencyTaskId := strings.TrimSpace(taskModel.DependencyTaskId)
- if dependencyTaskId == "" {
- return
- }
+ // 是否存在子任务
+ dependencyTaskId := strings.TrimSpace(taskModel.DependencyTaskId)
+ if dependencyTaskId == "" {
+ return
+ }
- // 父子任务关系为强依赖, 父任务执行失败, 不执行依赖任务
- if taskModel.DependencyStatus == models.TaskDependencyStatusStrong && taskResult.Err != nil {
- logger.Infof("父子任务为强依赖关系, 父任务执行失败, 不运行依赖任务#主任务ID-%d", taskModel.Id)
- return
- }
+ // 父子任务关系为强依赖, 父任务执行失败, 不执行依赖任务
+ if taskModel.DependencyStatus == models.TaskDependencyStatusStrong && taskResult.Err != nil {
+ logger.Infof("父子任务为强依赖关系, 父任务执行失败, 不运行依赖任务#主任务ID-%d", taskModel.Id)
+ return
+ }
- // 获取子任务
- model := new(models.Task)
- tasks , err := model.GetDependencyTaskList(dependencyTaskId)
- if err != nil {
- logger.Errorf("获取依赖任务失败#主任务ID-%d#%s", taskModel.Id, err.Error())
- return
- }
- if len(tasks) == 0 {
- logger.Errorf("依赖任务列表为空#主任务ID-%d", taskModel.Id)
- }
- serviceTask := new(Task)
- for _, task := range tasks {
- task.Spec = fmt.Sprintf("依赖任务(主任务ID-%d)", taskModel.Id)
- serviceTask.Run(task)
- }
+ // 获取子任务
+ model := new(models.Task)
+ tasks, err := model.GetDependencyTaskList(dependencyTaskId)
+ if err != nil {
+ logger.Errorf("获取依赖任务失败#主任务ID-%d#%s", taskModel.Id, err.Error())
+ return
+ }
+ if len(tasks) == 0 {
+ logger.Errorf("依赖任务列表为空#主任务ID-%d", taskModel.Id)
+ }
+ serviceTask := new(Task)
+ for _, task := range tasks {
+ task.Spec = fmt.Sprintf("依赖任务(主任务ID-%d)", taskModel.Id)
+ serviceTask.Run(task)
+ }
}
// 发送任务结果通知
-func SendNotification(taskModel models.Task, taskResult TaskResult) {
- var statusName string
- // 未开启通知
- if taskModel.NotifyStatus == 0 {
- return
- }
- if taskModel.NotifyStatus == 1 && taskResult.Err == nil {
- // 执行失败才发送通知
- return
- }
- if taskModel.NotifyReceiverId == "" {
- return
- }
- if taskResult.Err != nil {
- statusName = "失败"
- } else {
- statusName = "成功"
- }
- // 发送通知
- msg := notify.Message{
- "task_type": taskModel.NotifyType,
- "task_receiver_id": taskModel.NotifyReceiverId,
- "name": taskModel.Name,
- "output": taskResult.Result,
- "status": statusName,
- "taskId": taskModel.Id,
- };
- notify.Push(msg)
+func SendNotification(taskModel models.Task, taskResult TaskResult) {
+ var statusName string
+ // 未开启通知
+ if taskModel.NotifyStatus == 0 {
+ return
+ }
+ if taskModel.NotifyStatus == 1 && taskResult.Err == nil {
+ // 执行失败才发送通知
+ return
+ }
+ if taskModel.NotifyReceiverId == "" {
+ return
+ }
+ if taskResult.Err != nil {
+ statusName = "失败"
+ } else {
+ statusName = "成功"
+ }
+ // 发送通知
+ msg := notify.Message{
+ "task_type": taskModel.NotifyType,
+ "task_receiver_id": taskModel.NotifyReceiverId,
+ "name": taskModel.Name,
+ "output": taskResult.Result,
+ "status": statusName,
+ "taskId": taskModel.Id,
+ }
+ notify.Push(msg)
}
// 执行具体任务
-func execJob(handler Handler, taskModel models.Task) TaskResult {
- defer func() {
- if err := recover(); err != nil {
- logger.Error("panic#service/task.go:execJob#", err)
- }
- } ()
- if taskModel.Multi == 0 {
- defer runInstance.done(taskModel.Id)
- }
- // 默认只运行任务一次
- var execTimes int8 = 1
- if (taskModel.RetryTimes > 0) {
- execTimes += taskModel.RetryTimes
- }
- var i int8 = 0
- var output string
- var err error
- for i < execTimes {
- output, err = handler.Run(taskModel)
- if err == nil {
- return TaskResult{Result: output, Err: err, RetryTimes: i}
- }
- i++
- if i < execTimes {
- logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error())
- // 重试间隔时间,每次递增1分钟
- time.Sleep( time.Duration(i) * time.Minute)
- }
- }
+func execJob(handler Handler, taskModel models.Task) TaskResult {
+ defer func() {
+ if err := recover(); err != nil {
+ logger.Error("panic#service/task.go:execJob#", err)
+ }
+ }()
+ if taskModel.Multi == 0 {
+ defer runInstance.done(taskModel.Id)
+ }
+ // 默认只运行任务一次
+ var execTimes int8 = 1
+ if taskModel.RetryTimes > 0 {
+ execTimes += taskModel.RetryTimes
+ }
+ var i int8 = 0
+ var output string
+ var err error
+ for i < execTimes {
+ output, err = handler.Run(taskModel)
+ if err == nil {
+ return TaskResult{Result: output, Err: err, RetryTimes: i}
+ }
+ i++
+ if i < execTimes {
+ logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error())
+ // 重试间隔时间,每次递增1分钟
+ time.Sleep(time.Duration(i) * time.Minute)
+ }
+ }
- return TaskResult{Result: output, Err: err, RetryTimes: taskModel.RetryTimes}
-}
\ No newline at end of file
+ return TaskResult{Result: output, Err: err, RetryTimes: taskModel.RetryTimes}
+}
diff --git a/vendor/github.com/Unknwon/com/math.go b/vendor/github.com/Unknwon/com/math.go
index 99c56b6..62b77e8 100644
--- a/vendor/github.com/Unknwon/com/math.go
+++ b/vendor/github.com/Unknwon/com/math.go
@@ -14,12 +14,12 @@
package com
-// PowInt is int type of math.Pow function.
+// PowInt is int type of math.Pow function.
func PowInt(x int, y int) int {
if y <= 0 {
return 1
} else {
- if y % 2 == 0 {
+ if y%2 == 0 {
sqrt := PowInt(x, y/2)
return sqrt * sqrt
} else {
diff --git a/vendor/github.com/go-macaron/csrf/csrf.go b/vendor/github.com/go-macaron/csrf/csrf.go
index 9c1e38b..d9c9685 100644
--- a/vendor/github.com/go-macaron/csrf/csrf.go
+++ b/vendor/github.com/go-macaron/csrf/csrf.go
@@ -124,7 +124,7 @@ type Options struct {
// Cookie value used to set and get token.
Cookie string
// Cookie path.
- CookiePath string
+ CookiePath string
CookieHttpOnly bool
// Key used for getting the unique ID per user.
SessionKey string
diff --git a/vendor/github.com/go-macaron/session/memory.go b/vendor/github.com/go-macaron/session/memory.go
index 4ad9293..f76f159 100644
--- a/vendor/github.com/go-macaron/session/memory.go
+++ b/vendor/github.com/go-macaron/session/memory.go
@@ -1,217 +1,217 @@
-// Copyright 2013 Beego Authors
-// Copyright 2014 The Macaron Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License"): you may
-// not use this file except in compliance with the License. You may obtain
-// a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations
-// under the License.
-
-package session
-
-import (
- "container/list"
- "fmt"
- "sync"
- "time"
-)
-
-// MemStore represents a in-memory session store implementation.
-type MemStore struct {
- sid string
- lock sync.RWMutex
- data map[interface{}]interface{}
- lastAccess time.Time
-}
-
-// NewMemStore creates and returns a memory session store.
-func NewMemStore(sid string) *MemStore {
- return &MemStore{
- sid: sid,
- data: make(map[interface{}]interface{}),
- lastAccess: time.Now(),
- }
-}
-
-// Set sets value to given key in session.
-func (s *MemStore) Set(key, val interface{}) error {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- s.data[key] = val
- return nil
-}
-
-// Get gets value by given key in session.
-func (s *MemStore) Get(key interface{}) interface{} {
- s.lock.RLock()
- defer s.lock.RUnlock()
-
- return s.data[key]
-}
-
-// Delete deletes a key from session.
-func (s *MemStore) Delete(key interface{}) error {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- delete(s.data, key)
- return nil
-}
-
-// ID returns current session ID.
-func (s *MemStore) ID() string {
- return s.sid
-}
-
-// Release releases resource and save data to provider.
-func (_ *MemStore) Release() error {
- return nil
-}
-
-// Flush deletes all session data.
-func (s *MemStore) Flush() error {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- s.data = make(map[interface{}]interface{})
- return nil
-}
-
-// MemProvider represents a in-memory session provider implementation.
-type MemProvider struct {
- lock sync.RWMutex
- maxLifetime int64
- data map[string]*list.Element
- // A priority list whose lastAccess newer gets higer priority.
- list *list.List
-}
-
-// Init initializes memory session provider.
-func (p *MemProvider) Init(maxLifetime int64, _ string) error {
- p.lock.Lock()
- p.maxLifetime = maxLifetime
- p.lock.Unlock()
- return nil
-}
-
-// update expands time of session store by given ID.
-func (p *MemProvider) update(sid string) error {
- p.lock.Lock()
- defer p.lock.Unlock()
-
- if e, ok := p.data[sid]; ok {
- e.Value.(*MemStore).lastAccess = time.Now()
- p.list.MoveToFront(e)
- return nil
- }
- return nil
-}
-
-// Read returns raw session store by session ID.
-func (p *MemProvider) Read(sid string) (_ RawStore, err error) {
- p.lock.RLock()
- e, ok := p.data[sid]
- p.lock.RUnlock()
-
- if ok {
- if err = p.update(sid); err != nil {
- return nil, err
- }
- return e.Value.(*MemStore), nil
- }
-
- // Create a new session.
- p.lock.Lock()
- defer p.lock.Unlock()
-
- s := NewMemStore(sid)
- p.data[sid] = p.list.PushBack(s)
- return s, nil
-}
-
-// Exist returns true if session with given ID exists.
-func (p *MemProvider) Exist(sid string) bool {
- p.lock.RLock()
- defer p.lock.RUnlock()
-
- _, ok := p.data[sid]
- return ok
-}
-
-// Destory deletes a session by session ID.
-func (p *MemProvider) Destory(sid string) error {
- p.lock.Lock()
- defer p.lock.Unlock()
-
- e, ok := p.data[sid]
- if !ok {
- return nil
- }
-
- p.list.Remove(e)
- delete(p.data, sid)
- return nil
-}
-
-// Regenerate regenerates a session store from old session ID to new one.
-func (p *MemProvider) Regenerate(oldsid, sid string) (RawStore, error) {
- if p.Exist(sid) {
- return nil, fmt.Errorf("new sid '%s' already exists", sid)
- }
-
- s, err := p.Read(oldsid)
- if err != nil {
- return nil, err
- }
-
- if err = p.Destory(oldsid); err != nil {
- return nil, err
- }
-
- s.(*MemStore).sid = sid
-
- p.lock.Lock()
- defer p.lock.Unlock()
- p.data[sid] = p.list.PushBack(s)
- return s, nil
-}
-
-// Count counts and returns number of sessions.
-func (p *MemProvider) Count() int {
- return p.list.Len()
-}
-
-// GC calls GC to clean expired sessions.
-func (p *MemProvider) GC() {
- p.lock.RLock()
- for {
- // No session in the list.
- e := p.list.Back()
- if e == nil {
- break
- }
-
- if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
- p.lock.RUnlock()
- p.lock.Lock()
- p.list.Remove(e)
- delete(p.data, e.Value.(*MemStore).sid)
- p.lock.Unlock()
- p.lock.RLock()
- } else {
- break
- }
- }
- p.lock.RUnlock()
-}
-
-func init() {
- Register("memory", &MemProvider{list: list.New(), data: make(map[string]*list.Element)})
-}
+// Copyright 2013 Beego Authors
+// Copyright 2014 The Macaron Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License"): you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+
+package session
+
+import (
+ "container/list"
+ "fmt"
+ "sync"
+ "time"
+)
+
+// MemStore represents a in-memory session store implementation.
+type MemStore struct {
+ sid string
+ lock sync.RWMutex
+ data map[interface{}]interface{}
+ lastAccess time.Time
+}
+
+// NewMemStore creates and returns a memory session store.
+func NewMemStore(sid string) *MemStore {
+ return &MemStore{
+ sid: sid,
+ data: make(map[interface{}]interface{}),
+ lastAccess: time.Now(),
+ }
+}
+
+// Set sets value to given key in session.
+func (s *MemStore) Set(key, val interface{}) error {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+
+ s.data[key] = val
+ return nil
+}
+
+// Get gets value by given key in session.
+func (s *MemStore) Get(key interface{}) interface{} {
+ s.lock.RLock()
+ defer s.lock.RUnlock()
+
+ return s.data[key]
+}
+
+// Delete deletes a key from session.
+func (s *MemStore) Delete(key interface{}) error {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+
+ delete(s.data, key)
+ return nil
+}
+
+// ID returns current session ID.
+func (s *MemStore) ID() string {
+ return s.sid
+}
+
+// Release releases resource and save data to provider.
+func (_ *MemStore) Release() error {
+ return nil
+}
+
+// Flush deletes all session data.
+func (s *MemStore) Flush() error {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+
+ s.data = make(map[interface{}]interface{})
+ return nil
+}
+
+// MemProvider represents a in-memory session provider implementation.
+type MemProvider struct {
+ lock sync.RWMutex
+ maxLifetime int64
+ data map[string]*list.Element
+ // A priority list whose lastAccess newer gets higer priority.
+ list *list.List
+}
+
+// Init initializes memory session provider.
+func (p *MemProvider) Init(maxLifetime int64, _ string) error {
+ p.lock.Lock()
+ p.maxLifetime = maxLifetime
+ p.lock.Unlock()
+ return nil
+}
+
+// update expands time of session store by given ID.
+func (p *MemProvider) update(sid string) error {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ if e, ok := p.data[sid]; ok {
+ e.Value.(*MemStore).lastAccess = time.Now()
+ p.list.MoveToFront(e)
+ return nil
+ }
+ return nil
+}
+
+// Read returns raw session store by session ID.
+func (p *MemProvider) Read(sid string) (_ RawStore, err error) {
+ p.lock.RLock()
+ e, ok := p.data[sid]
+ p.lock.RUnlock()
+
+ if ok {
+ if err = p.update(sid); err != nil {
+ return nil, err
+ }
+ return e.Value.(*MemStore), nil
+ }
+
+ // Create a new session.
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ s := NewMemStore(sid)
+ p.data[sid] = p.list.PushBack(s)
+ return s, nil
+}
+
+// Exist returns true if session with given ID exists.
+func (p *MemProvider) Exist(sid string) bool {
+ p.lock.RLock()
+ defer p.lock.RUnlock()
+
+ _, ok := p.data[sid]
+ return ok
+}
+
+// Destory deletes a session by session ID.
+func (p *MemProvider) Destory(sid string) error {
+ p.lock.Lock()
+ defer p.lock.Unlock()
+
+ e, ok := p.data[sid]
+ if !ok {
+ return nil
+ }
+
+ p.list.Remove(e)
+ delete(p.data, sid)
+ return nil
+}
+
+// Regenerate regenerates a session store from old session ID to new one.
+func (p *MemProvider) Regenerate(oldsid, sid string) (RawStore, error) {
+ if p.Exist(sid) {
+ return nil, fmt.Errorf("new sid '%s' already exists", sid)
+ }
+
+ s, err := p.Read(oldsid)
+ if err != nil {
+ return nil, err
+ }
+
+ if err = p.Destory(oldsid); err != nil {
+ return nil, err
+ }
+
+ s.(*MemStore).sid = sid
+
+ p.lock.Lock()
+ defer p.lock.Unlock()
+ p.data[sid] = p.list.PushBack(s)
+ return s, nil
+}
+
+// Count counts and returns number of sessions.
+func (p *MemProvider) Count() int {
+ return p.list.Len()
+}
+
+// GC calls GC to clean expired sessions.
+func (p *MemProvider) GC() {
+ p.lock.RLock()
+ for {
+ // No session in the list.
+ e := p.list.Back()
+ if e == nil {
+ break
+ }
+
+ if (e.Value.(*MemStore).lastAccess.Unix() + p.maxLifetime) < time.Now().Unix() {
+ p.lock.RUnlock()
+ p.lock.Lock()
+ p.list.Remove(e)
+ delete(p.data, e.Value.(*MemStore).sid)
+ p.lock.Unlock()
+ p.lock.RLock()
+ } else {
+ break
+ }
+ }
+ p.lock.RUnlock()
+}
+
+func init() {
+ Register("memory", &MemProvider{list: list.New(), data: make(map[string]*list.Element)})
+}
diff --git a/vendor/github.com/go-xorm/core/cache.go b/vendor/github.com/go-xorm/core/cache.go
index bf81bd5..cd95e54 100644
--- a/vendor/github.com/go-xorm/core/cache.go
+++ b/vendor/github.com/go-xorm/core/cache.go
@@ -1,11 +1,11 @@
package core
import (
+ "bytes"
+ "encoding/gob"
"errors"
"fmt"
"time"
- "bytes"
- "encoding/gob"
)
const (
@@ -55,7 +55,6 @@ func encodeIds(ids []PK) (string, error) {
return buf.String(), err
}
-
func decodeIds(s string) ([]PK, error) {
pks := make([]PK, 0)
diff --git a/vendor/github.com/jakecoffman/cron/cron.go b/vendor/github.com/jakecoffman/cron/cron.go
index 3b4af82..e42c7e5 100644
--- a/vendor/github.com/jakecoffman/cron/cron.go
+++ b/vendor/github.com/jakecoffman/cron/cron.go
@@ -90,7 +90,7 @@ type FuncJob func()
func (f FuncJob) Run() { f() }
// AddFunc adds a func to the Cron to be run on the given schedule.
-func (c *Cron) AddFunc(spec string, cmd func(), name string) error {
+func (c *Cron) AddFunc(spec string, cmd func(), name string) error {
return c.AddJob(spec, FuncJob(cmd), name)
}
diff --git a/vendor/github.com/jakecoffman/cron/parser.go b/vendor/github.com/jakecoffman/cron/parser.go
index 28326c5..dcde409 100644
--- a/vendor/github.com/jakecoffman/cron/parser.go
+++ b/vendor/github.com/jakecoffman/cron/parser.go
@@ -1,12 +1,12 @@
package cron
import (
+ "fmt"
"log"
"math"
"strconv"
"strings"
"time"
- "fmt"
)
// Parse returns a new crontab schedule representing the given spec.
@@ -160,7 +160,7 @@ func all(r bounds) uint64 {
// parseDescriptor returns a pre-defined schedule for the expression, or panics
// if none matches.
-func parseDescriptor(spec string) (Schedule,error) {
+func parseDescriptor(spec string) (Schedule, error) {
switch spec {
case "@yearly", "@annually":
return &SpecSchedule{
@@ -217,10 +217,10 @@ func parseDescriptor(spec string) (Schedule,error) {
if strings.HasPrefix(spec, every) {
duration, err := time.ParseDuration(spec[len(every):])
if err != nil {
- return nil, fmt.Errorf("Failed to parse duration %s: %s", spec, err)
- }
- return Every(duration),nil
+ return nil, fmt.Errorf("Failed to parse duration %s: %s", spec, err)
+ }
+ return Every(duration), nil
}
- return nil, fmt.Errorf("Unrecognized descriptor: %s", spec)
+ return nil, fmt.Errorf("Unrecognized descriptor: %s", spec)
}
diff --git a/vendor/golang.org/x/crypto/ssh/kex.go b/vendor/golang.org/x/crypto/ssh/kex.go
index c87fbeb..f91c277 100644
--- a/vendor/golang.org/x/crypto/ssh/kex.go
+++ b/vendor/golang.org/x/crypto/ssh/kex.go
@@ -383,8 +383,8 @@ func init() {
// 4253 and Oakley Group 2 in RFC 2409.
p, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH1SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
+ g: new(big.Int).SetInt64(2),
+ p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}
@@ -393,8 +393,8 @@ func init() {
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
kexAlgoMap[kexAlgoDH14SHA1] = &dhGroup{
- g: new(big.Int).SetInt64(2),
- p: p,
+ g: new(big.Int).SetInt64(2),
+ p: p,
pMinus1: new(big.Int).Sub(p, bigOne),
}