mirror of https://github.com/ouqiang/gocron
style: 代码格式化
parent
21028ec6f0
commit
f0ff9a88a7
16
cmd/web.go
16
cmd/web.go
|
@ -1,25 +1,24 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"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"
|
||||
"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"
|
||||
)
|
||||
|
||||
// web服务器默认端口
|
||||
const DefaultPort = 5920
|
||||
|
||||
|
||||
var CmdWeb = cli.Command{
|
||||
Name: "web",
|
||||
Usage: "run web server",
|
||||
|
@ -128,7 +127,7 @@ func catchSignal() {
|
|||
// todo 配置热更新, windows 不支持 syscall.SIGUSR1, syscall.SIGUSR2
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
|
||||
for {
|
||||
s := <- c
|
||||
s := <-c
|
||||
logger.Info("收到信号 -- ", s)
|
||||
switch s {
|
||||
case syscall.SIGHUP:
|
||||
|
@ -139,7 +138,6 @@ func catchSignal() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// 应用退出
|
||||
func shutdown() {
|
||||
defer func() {
|
||||
|
@ -178,7 +176,7 @@ func upgradeIfNeed() {
|
|||
currentVersionId := app.GetCurrentVersionId()
|
||||
// 没有版本号文件
|
||||
if currentVersionId == 0 {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if currentVersionId >= app.VersionId {
|
||||
return
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/ouqiang/gocron/modules/rpc/server"
|
||||
"flag"
|
||||
"runtime"
|
||||
"os"
|
||||
"fmt"
|
||||
"strings"
|
||||
"github.com/ouqiang/gocron/modules/rpc/auth"
|
||||
"github.com/ouqiang/gocron/modules/rpc/server"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const AppVersion = "1.2.2"
|
||||
|
@ -38,7 +38,7 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
if (enableTLS) {
|
||||
if enableTLS {
|
||||
if !utils.FileExist(CAFile) {
|
||||
fmt.Printf("failed to read ca cert file: %s", CAFile)
|
||||
return
|
||||
|
@ -59,12 +59,10 @@ func main() {
|
|||
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)
|
||||
}
|
|
@ -29,7 +29,6 @@ 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)
|
||||
|
@ -48,11 +47,11 @@ func (host *Host) Find(id int) error {
|
|||
|
||||
func (host *Host) NameExists(name string, id int16) (bool, error) {
|
||||
if id == 0 {
|
||||
count, err := Db.Where("name = ?", name).Count(host);
|
||||
count, err := Db.Where("name = ?", name).Count(host)
|
||||
return count > 0, err
|
||||
}
|
||||
|
||||
count, err := Db.Where("name = ? AND id != ?", name, id).Count(host);
|
||||
count, err := Db.Where("name = ? AND id != ?", name, id).Count(host)
|
||||
return count > 0, err
|
||||
}
|
||||
|
||||
|
|
|
@ -3,12 +3,11 @@ package models
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
||||
type Migration struct{}
|
||||
|
||||
// 首次安装, 创建数据库表
|
||||
|
@ -19,10 +18,10 @@ func (migration *Migration) Install(dbName string) error {
|
|||
setting := new(Setting)
|
||||
task := new(Task)
|
||||
tables := []interface{}{
|
||||
&User{}, task, &TaskLog{}, &Host{}, setting,&LoginLog{},&TaskHost{},
|
||||
&User{}, task, &TaskLog{}, &Host{}, setting, &LoginLog{}, &TaskHost{},
|
||||
}
|
||||
for _, table := range tables {
|
||||
exist, err:= Db.IsTableExist(table)
|
||||
exist, err := Db.IsTableExist(table)
|
||||
if exist {
|
||||
return errors.New("数据表已存在")
|
||||
}
|
||||
|
@ -55,7 +54,7 @@ func (migration *Migration) Upgrade(oldVersionId int) {
|
|||
}
|
||||
|
||||
versionIds := []int{110, 122}
|
||||
upgradeFuncs := []func(*xorm.Session) error {
|
||||
upgradeFuncs := []func(*xorm.Session) error{
|
||||
migration.upgradeFor110,
|
||||
migration.upgradeFor122,
|
||||
}
|
||||
|
@ -65,7 +64,7 @@ func (migration *Migration) Upgrade(oldVersionId int) {
|
|||
for i, value := range versionIds {
|
||||
if value > oldVersionId {
|
||||
startIndex = i
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +90,7 @@ func (migration *Migration) Upgrade(oldVersionId int) {
|
|||
}
|
||||
dbErr := session.Rollback()
|
||||
if dbErr != nil {
|
||||
logger.Fatalf("事务回滚失败-%s",dbErr.Error())
|
||||
logger.Fatalf("事务回滚失败-%s", dbErr.Error())
|
||||
}
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
@ -136,7 +135,6 @@ func (migration *Migration) upgradeFor110(session *xorm.Session) error {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// 删除task表host_id字段
|
||||
_, err = session.Exec(fmt.Sprintf("ALTER TABLE %s DROP COLUMN host_id", tableName))
|
||||
|
||||
|
|
|
@ -5,12 +5,12 @@ import (
|
|||
_ "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"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"github.com/ouqiang/gocron/modules/app"
|
||||
"time"
|
||||
"github.com/ouqiang/gocron/modules/setting"
|
||||
)
|
||||
|
||||
type Status int8
|
||||
|
@ -107,7 +107,7 @@ func getDbEngineDSN(setting *setting.Setting) string {
|
|||
setting.Db.User,
|
||||
setting.Db.Password,
|
||||
setting.Db.Host,
|
||||
setting.Db.Port ,
|
||||
setting.Db.Port,
|
||||
setting.Db.Database,
|
||||
setting.Db.Charset)
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ func getDbEngineDSN(setting *setting.Setting) string {
|
|||
func keepDbAlived(engine *xorm.Engine) {
|
||||
t := time.Tick(180 * time.Second)
|
||||
for {
|
||||
<- t
|
||||
<-t
|
||||
engine.Ping()
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ const MailUserKey = "user"
|
|||
|
||||
// 初始化基本字段 邮件、slack等
|
||||
func (setting *Setting) InitBasicField() {
|
||||
setting.Code = SlackCode;
|
||||
setting.Code = SlackCode
|
||||
setting.Key = SlackUrlKey
|
||||
Db.Insert(setting)
|
||||
|
||||
|
@ -46,7 +46,7 @@ type Channel struct {
|
|||
func (setting *Setting) Slack() (Slack, error) {
|
||||
list := make([]Setting, 0)
|
||||
err := Db.Where("code = ?", SlackCode).Find(&list)
|
||||
slack := Slack{Url:"", Channels:make([]Channel, 0)}
|
||||
slack := Slack{Url: "", Channels: make([]Channel, 0)}
|
||||
if err != nil {
|
||||
return slack, err
|
||||
}
|
||||
|
@ -73,10 +73,9 @@ func (setting *Setting) formatSlack(list []Setting, slack *Slack) {
|
|||
func (setting *Setting) UpdateSlackUrl(url string) (int64, error) {
|
||||
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
|
||||
|
@ -86,7 +85,7 @@ func (setting *Setting) CreateChannel(channel string) (int64, error) {
|
|||
return Db.Insert(setting)
|
||||
}
|
||||
|
||||
func (setting *Setting) IsChannelExist(channel string) (bool) {
|
||||
func (setting *Setting) IsChannelExist(channel string) bool {
|
||||
setting.Code = SlackCode
|
||||
setting.Key = SlackChannelKey
|
||||
setting.Value = channel
|
||||
|
@ -124,7 +123,7 @@ type MailUser struct {
|
|||
func (setting *Setting) Mail() (Mail, error) {
|
||||
list := make([]Setting, 0)
|
||||
err := Db.Where("code = ?", MailCode).Find(&list)
|
||||
mail := Mail{MailUsers:make([]MailUser, 0)}
|
||||
mail := Mail{MailUsers: make([]MailUser, 0)}
|
||||
if err != nil {
|
||||
return mail, err
|
||||
}
|
||||
|
@ -149,7 +148,7 @@ func (setting *Setting) formatMail(list []Setting, mail *Mail) {
|
|||
|
||||
func (setting *Setting) UpdateMailServer(config string) (int64, error) {
|
||||
setting.Value = config
|
||||
return Db.Cols("value").Update(setting, Setting{Code:MailCode, Key:MailServerKey})
|
||||
return Db.Cols("value").Update(setting, Setting{Code: MailCode, Key: MailServerKey})
|
||||
}
|
||||
|
||||
func (setting *Setting) CreateMailUser(username, email string) (int64, error) {
|
||||
|
@ -171,4 +170,5 @@ func (setting *Setting) RemoveMailUser(id int) (int64, error) {
|
|||
setting.Id = id
|
||||
return Db.Delete(setting)
|
||||
}
|
||||
|
||||
// endregion
|
|
@ -1,10 +1,10 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
"github.com/go-xorm/xorm"
|
||||
"errors"
|
||||
"github.com/go-xorm/xorm"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TaskProtocol int8
|
||||
|
@ -155,10 +155,10 @@ func (task *Task) setHostsForTasks(tasks []Task) ([]Task, error) {
|
|||
// 判断任务名称是否存在
|
||||
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);
|
||||
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);
|
||||
count, err := Db.Where("name = ? AND status = ?", name, Enabled).Count(task)
|
||||
|
||||
return count > 0, err
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ func (task *Task) GetStatus(id int) (Status, error) {
|
|||
return task.Status, nil
|
||||
}
|
||||
|
||||
func(task *Task) Detail(id int) (Task, error) {
|
||||
func (task *Task) Detail(id int) (Task, error) {
|
||||
t := Task{}
|
||||
_, err := Db.Where("id=?", id).Get(&t)
|
||||
|
||||
|
@ -253,7 +253,7 @@ func (task *Task) parseWhere(session *xorm.Session, params CommonMap) {
|
|||
}
|
||||
name, ok := params["Name"]
|
||||
if ok && name.(string) != "" {
|
||||
session.And("t.name LIKE ?", "%" + name.(string) + "%")
|
||||
session.And("t.name LIKE ?", "%"+name.(string)+"%")
|
||||
}
|
||||
protocol, ok := params["Protocol"]
|
||||
if ok && protocol.(int) > 0 {
|
||||
|
@ -269,4 +269,3 @@ func (task *Task) parseWhere(session *xorm.Session, params CommonMap) {
|
|||
session.And("tag = ? ", tag)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package models
|
||||
|
||||
|
||||
type TaskHost struct {
|
||||
Id int `xorm:"int pk autoincr"`
|
||||
TaskId int `xorm:"int not null index"`
|
||||
|
@ -75,7 +74,7 @@ func (th *TaskHost) GetTaskIdsByHostId(hostId int16) ([]interface{}, error) {
|
|||
|
||||
// 判断主机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
|
||||
}
|
|
@ -1,13 +1,12 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
"github.com/go-xorm/xorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
type TaskType int8
|
||||
|
||||
|
||||
// 任务执行日志
|
||||
type TaskLog struct {
|
||||
Id int64 `xorm:"bigint pk autoincr"`
|
||||
|
@ -63,7 +62,7 @@ func (taskLog *TaskLog) List(params CommonMap) ([]TaskLog, error) {
|
|||
|
||||
// 清空表
|
||||
func (taskLog *TaskLog) Clear() (int64, error) {
|
||||
return Db.Where("1=1").Delete(taskLog);
|
||||
return Db.Where("1=1").Delete(taskLog)
|
||||
}
|
||||
|
||||
// 删除N个月前的日志
|
||||
|
|
|
@ -4,11 +4,11 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"github.com/ouqiang/gocron/modules/setting"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"github.com/ouqiang/gocron/modules/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -23,7 +23,6 @@ var (
|
|||
VersionFile string // 版本号文件
|
||||
)
|
||||
|
||||
|
||||
func InitEnv(versionString string) {
|
||||
logger.InitLogger()
|
||||
wd, err := os.Getwd()
|
||||
|
@ -76,7 +75,7 @@ func UpdateVersionFile() {
|
|||
// 获取应用当前版本号, 从版本号文件中读取
|
||||
func GetCurrentVersionId() int {
|
||||
if !utils.FileExist(VersionFile) {
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
|
||||
bytes, err := ioutil.ReadFile(VersionFile)
|
||||
|
|
|
@ -3,11 +3,11 @@ package httpclient
|
|||
// http-client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
"fmt"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
type ResponseWrapper struct {
|
||||
|
@ -25,7 +25,7 @@ func Get(url string, timeout int) ResponseWrapper {
|
|||
return request(req, timeout)
|
||||
}
|
||||
|
||||
func PostParams(url string,params string, timeout int) ResponseWrapper {
|
||||
func PostParams(url string, params string, timeout int) ResponseWrapper {
|
||||
buf := bytes.NewBufferString(params)
|
||||
req, err := http.NewRequest("POST", url, buf)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cihub/seelog"
|
||||
"gopkg.in/macaron.v1"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
package notify
|
||||
|
||||
import (
|
||||
"github.com/go-gomail/gomail"
|
||||
"github.com/ouqiang/gocron/models"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"strconv"
|
||||
"strings"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"time"
|
||||
"github.com/go-gomail/gomail"
|
||||
)
|
||||
|
||||
// @author qiang.ou<qingqianludao@gmail.com>
|
||||
// @date 2017/5/1-00:19
|
||||
|
||||
|
||||
type Mail struct {
|
||||
|
||||
}
|
||||
|
||||
func (mail *Mail) Send(msg Message) {
|
||||
|
@ -61,7 +59,7 @@ func (mail *Mail) send(mailSetting models.Mail, toUsers []string, msg Message)
|
|||
for i < maxTimes {
|
||||
err := mailer.DialAndSend(gomailMessage)
|
||||
if err == nil {
|
||||
break;
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
time.Sleep(2 * time.Second)
|
||||
|
@ -74,7 +72,7 @@ func (mail *Mail) send(mailSetting models.Mail, toUsers []string, msg Message)
|
|||
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) {
|
||||
for _, v := range mailSetting.MailUsers {
|
||||
if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) {
|
||||
users = append(users, v.Email)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package notify
|
||||
|
||||
import (
|
||||
"time"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"fmt"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Message map[string]interface{}
|
||||
|
@ -37,7 +37,7 @@ func run() {
|
|||
}
|
||||
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)) {
|
||||
switch taskType.(int8) {
|
||||
case 1:
|
||||
// 邮件
|
||||
mail := Mail{}
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
package notify
|
||||
|
||||
// 发送消息到slack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ouqiang/gocron/models"
|
||||
"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"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Slack struct {}
|
||||
type Slack struct{}
|
||||
|
||||
func (slack *Slack) Send(msg Message) {
|
||||
model := new(models.Setting)
|
||||
|
@ -32,7 +33,7 @@ func (slack *Slack) Send(msg Message) {
|
|||
logger.Debugf("%+v", slackSetting)
|
||||
channels := slack.getActiveSlackChannels(slackSetting, msg)
|
||||
logger.Debugf("%+v", channels)
|
||||
for _, channel := range(channels) {
|
||||
for _, channel := range channels {
|
||||
slack.send(msg, slackSetting.Url, channel)
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +46,7 @@ func (slack *Slack) send(msg Message, slackUrl string, channel string) {
|
|||
for i < maxTimes {
|
||||
resp := httpclient.PostJson(slackUrl, formatBody, timeout)
|
||||
if resp.StatusCode == 200 {
|
||||
break;
|
||||
break
|
||||
}
|
||||
i += 1
|
||||
time.Sleep(2 * time.Second)
|
||||
|
@ -58,7 +59,7 @@ func (slack *Slack) send(msg Message, slackUrl string, channel string) {
|
|||
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) {
|
||||
for _, v := range slackSetting.Channels {
|
||||
if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) {
|
||||
channels = append(channels, v.Name)
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@ package auth
|
|||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"io/ioutil"
|
||||
"errors"
|
||||
"fmt"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
type Certificate struct {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -1,42 +1,27 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"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"
|
||||
"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"
|
||||
"google.golang.org/grpc/codes"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
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)
|
||||
}
|
||||
|
||||
return "", errUnavailable
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
package grpcpool
|
||||
|
||||
import (
|
||||
"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"
|
||||
"google.golang.org/grpc"
|
||||
"errors"
|
||||
"github.com/ouqiang/gocron/modules/rpc/auth"
|
||||
"github.com/ouqiang/gocron/modules/app"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
||||
var (
|
||||
Pool GRPCPool
|
||||
)
|
||||
|
@ -66,7 +65,6 @@ func (p *GRPCPool) Put(addr string, conn *grpc.ClientConn) error {
|
|||
return ErrInvalidConn
|
||||
}
|
||||
|
||||
|
||||
// 释放连接池
|
||||
func (p *GRPCPool) Release(addr string) {
|
||||
p.Lock()
|
||||
|
@ -83,13 +81,13 @@ func (p *GRPCPool) Release(addr string) {
|
|||
func (p *GRPCPool) ReleaseAll() {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
for _, pool := range(p.conns) {
|
||||
for _, pool := range p.conns {
|
||||
pool.Release()
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化底层连接池
|
||||
func (p *GRPCPool) newCommonPool(addr string) (error) {
|
||||
func (p *GRPCPool) newCommonPool(addr string) error {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
commonPool, ok := p.conns[addr]
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"net"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
"google.golang.org/grpc"
|
||||
"github.com/ouqiang/gocron/modules/rpc/auth"
|
||||
pb "github.com/ouqiang/gocron/modules/rpc/proto"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"github.com/ouqiang/gocron/modules/rpc/auth"
|
||||
"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
|
||||
|
@ -36,7 +36,7 @@ func Start(addr string, enableTLS bool, certificate auth.Certificate) {
|
|||
if err := recover(); err != nil {
|
||||
grpclog.Println("panic", err)
|
||||
}
|
||||
} ()
|
||||
}()
|
||||
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
|
@ -62,4 +62,3 @@ func Start(addr string, enableTLS bool, certificate auth.Certificate) {
|
|||
err = s.Serve(l)
|
||||
grpclog.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,15 +2,15 @@ package setting
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"gopkg.in/ini.v1"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
const DefaultSection = "default"
|
||||
|
||||
type Setting struct {
|
||||
Db struct{
|
||||
Db struct {
|
||||
Engine string
|
||||
Host string
|
||||
Port int
|
||||
|
@ -35,7 +35,7 @@ type Setting struct {
|
|||
}
|
||||
|
||||
// 读取配置
|
||||
func Read(filename string) (*Setting,error) {
|
||||
func Read(filename string) (*Setting, error) {
|
||||
config, err := ini.Load(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -88,7 +88,7 @@ func Write(config []string, filename string) error {
|
|||
if len(config) == 0 {
|
||||
return errors.New("参数不能为空")
|
||||
}
|
||||
if len(config) % 2 != 0 {
|
||||
if len(config)%2 != 0 {
|
||||
return errors.New("参数不匹配")
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ func Write(config []string, filename string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0 ;i < len(config); {
|
||||
for i := 0; i < len(config); {
|
||||
_, err = section.NewKey(config[i], config[i+1])
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
"errors"
|
||||
"fmt"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"net"
|
||||
"time"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type HostAuthType int8 // 认证方式
|
||||
|
@ -17,7 +17,6 @@ const (
|
|||
|
||||
const SSHConnectTimeout = 10
|
||||
|
||||
|
||||
type SSHConfig struct {
|
||||
AuthType HostAuthType
|
||||
User string
|
||||
|
@ -25,7 +24,7 @@ type SSHConfig struct {
|
|||
PrivateKey string
|
||||
Host string
|
||||
Port int
|
||||
ExecTimeout int// 执行超时时间
|
||||
ExecTimeout int // 执行超时时间
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
|
@ -43,7 +42,7 @@ func parseSSHConfig(sshConfig SSHConfig) (config *ssh.ClientConfig, err error) {
|
|||
ssh.Password(sshConfig.Password),
|
||||
},
|
||||
Timeout: timeout,
|
||||
HostKeyCallback:func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -63,7 +62,7 @@ func parseSSHConfig(sshConfig SSHConfig) (config *ssh.ClientConfig, err error) {
|
|||
ssh.PublicKeys(signer),
|
||||
},
|
||||
Timeout: timeout,
|
||||
HostKeyCallback:func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
@ -71,7 +70,6 @@ func parseSSHConfig(sshConfig SSHConfig) (config *ssh.ClientConfig, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
|
||||
// 执行shell命令
|
||||
func Exec(sshConfig SSHConfig, cmd string) (output string, err error) {
|
||||
client, err := getClient(sshConfig)
|
||||
|
@ -110,10 +108,10 @@ func Exec(sshConfig SSHConfig, cmd string) (output string, err error) {
|
|||
// todo 等待超时后,如何停止远程正在执行的任务, 使用timeout命令,但不具有通用性
|
||||
go triggerTimeout(timeoutChan, sshConfig.ExecTimeout)
|
||||
select {
|
||||
case result := <- resultChan:
|
||||
case result := <-resultChan:
|
||||
output = result.Output
|
||||
err = result.Err
|
||||
case <- timeoutChan:
|
||||
case <-timeoutChan:
|
||||
output = ""
|
||||
err = errors.New("timeout")
|
||||
}
|
||||
|
@ -131,8 +129,7 @@ func getClient(sshConfig SSHConfig) (*ssh.Client, error) {
|
|||
return ssh.Dial("tcp", addr, config)
|
||||
}
|
||||
|
||||
|
||||
func triggerTimeout(ch chan bool, timeout int){
|
||||
func triggerTimeout(ch chan bool, timeout int) {
|
||||
// 最长执行时间不能超过24小时
|
||||
if timeout <= 0 || timeout > 86400 {
|
||||
timeout = 86400
|
||||
|
@ -140,4 +137,3 @@ func triggerTimeout(ch chan bool, timeout int){
|
|||
time.Sleep(time.Duration(timeout) * time.Second)
|
||||
close(ch)
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ func (j *JsonResponse) Failure(code int, message string) string {
|
|||
return j.response(code, message, nil)
|
||||
}
|
||||
|
||||
func (j *JsonResponse) CommonFailure(message string, err... error) string {
|
||||
func (j *JsonResponse) CommonFailure(message string, err ...error) string {
|
||||
if len(err) > 0 {
|
||||
logger.Warn(err)
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ package utils
|
|||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
"time"
|
||||
"runtime"
|
||||
"github.com/Tang-RoseChild/mahonia"
|
||||
"strings"
|
||||
"os"
|
||||
"fmt"
|
||||
"github.com/Tang-RoseChild/mahonia"
|
||||
"math/rand"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 生成长度为length的随机字符串
|
||||
|
@ -72,7 +72,7 @@ func ReplaceStrings(s string, old []string, replace []string) string {
|
|||
func InStringSlice(slice []string, element string) bool {
|
||||
element = strings.TrimSpace(element)
|
||||
for _, v := range slice {
|
||||
if strings.TrimSpace(v) == element{
|
||||
if strings.TrimSpace(v) == element {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -82,8 +82,8 @@ func InStringSlice(slice []string, element string) bool {
|
|||
|
||||
// 转义json特殊字符
|
||||
func EscapeJson(s string) string {
|
||||
specialChars := []string{"\\", "\b","\f", "\n", "\r", "\t", "\"",}
|
||||
replaceChars := []string{ "\\\\", "\\b", "\\f", "\\n", "\\r", "\\t", "\\\"",}
|
||||
specialChars := []string{"\\", "\b", "\f", "\n", "\r", "\t", "\""}
|
||||
replaceChars := []string{"\\\\", "\\b", "\\f", "\\n", "\\r", "\\t", "\\\""}
|
||||
|
||||
return ReplaceStrings(s, specialChars, replaceChars)
|
||||
}
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"golang.org/x/net/context"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"golang.org/x/net/context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
|
@ -22,16 +22,16 @@ func ExecShell(ctx context.Context, command string) (string, error) {
|
|||
}
|
||||
var resultChan chan Result = make(chan Result)
|
||||
go func() {
|
||||
output ,err := cmd.CombinedOutput()
|
||||
output, err := cmd.CombinedOutput()
|
||||
resultChan <- Result{string(output), err}
|
||||
}()
|
||||
select {
|
||||
case <- ctx.Done():
|
||||
case <-ctx.Done():
|
||||
if cmd.Process.Pid > 0 {
|
||||
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
}
|
||||
return "", errors.New("timeout killed")
|
||||
case result := <- resultChan:
|
||||
case result := <-resultChan:
|
||||
return result.output, result.err
|
||||
}
|
||||
}
|
|
@ -3,11 +3,11 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"errors"
|
||||
"golang.org/x/net/context"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"golang.org/x/net/context"
|
||||
"errors"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
|
@ -24,25 +24,22 @@ func ExecShell(ctx context.Context, command string) (string, error) {
|
|||
}
|
||||
var resultChan chan Result = make(chan Result)
|
||||
go func() {
|
||||
output ,err := cmd.CombinedOutput()
|
||||
output, err := cmd.CombinedOutput()
|
||||
resultChan <- Result{string(output), err}
|
||||
}()
|
||||
select {
|
||||
case <- ctx.Done():
|
||||
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:
|
||||
case result := <-resultChan:
|
||||
return ConvertEncoding(result.output), result.err
|
||||
}
|
||||
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func ConvertEncoding(outputGBK string) (string) {
|
||||
func ConvertEncoding(outputGBK string) string {
|
||||
// windows平台编码为gbk,需转换为utf8才能入库
|
||||
outputUTF8, ok := GBK2UTF8(outputGBK)
|
||||
if ok {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"gopkg.in/macaron.v1"
|
||||
"github.com/ouqiang/gocron/models"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
func ParsePageAndPageSize(ctx *macaron.Context, params models.CommonMap) {
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
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/Unknwon/paginater"
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/ouqiang/gocron/modules/rpc/grpcpool"
|
||||
"strings"
|
||||
"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) {
|
||||
|
@ -32,7 +32,7 @@ func Index(ctx *macaron.Context) {
|
|||
safeNameHTML = template.HTMLEscapeString(name)
|
||||
}
|
||||
PageParams := fmt.Sprintf("id=%d&name=%s&page_size=%d",
|
||||
queryParams["Id"], safeNameHTML, queryParams["PageSize"]);
|
||||
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
|
||||
|
@ -136,7 +136,7 @@ func Remove(ctx *macaron.Context) string {
|
|||
return json.CommonFailure("参数错误", err)
|
||||
}
|
||||
taskHostModel := new(models.TaskHost)
|
||||
exist,err := taskHostModel.HostIdExist(int16(id))
|
||||
exist, err := taskHostModel.HostIdExist(int16(id))
|
||||
if err != nil {
|
||||
return json.CommonFailure("操作失败", err)
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ func Remove(ctx *macaron.Context) string {
|
|||
return json.CommonFailure("主机不存在")
|
||||
}
|
||||
|
||||
_, err =hostModel.Delete(id)
|
||||
_, err = hostModel.Delete(id)
|
||||
if err != nil {
|
||||
return json.CommonFailure("操作失败", err)
|
||||
}
|
||||
|
@ -158,7 +158,6 @@ func Remove(ctx *macaron.Context) string {
|
|||
addr := fmt.Sprintf("%s:%d", hostModel.Name, hostModel.Port)
|
||||
grpcpool.Pool.Release(addr)
|
||||
|
||||
|
||||
return json.Success("操作成功", nil)
|
||||
}
|
||||
|
||||
|
@ -167,24 +166,23 @@ func Ping(ctx *macaron.Context) string {
|
|||
hostModel := new(models.Host)
|
||||
err := hostModel.Find(id)
|
||||
json := utils.JsonResponse{}
|
||||
if err != nil || hostModel.Id <= 0{
|
||||
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)
|
||||
return json.CommonFailure("连接失败-"+err.Error()+" "+output, err)
|
||||
}
|
||||
|
||||
return json.Success("连接成功", nil)
|
||||
}
|
||||
|
||||
// 解析查询参数
|
||||
func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
|
||||
func parseQueryParams(ctx *macaron.Context) models.CommonMap {
|
||||
var params models.CommonMap = models.CommonMap{}
|
||||
params["Id"] = ctx.QueryInt("id")
|
||||
params["Name"] = ctx.QueryTrim("name")
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package install
|
||||
|
||||
import (
|
||||
"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"
|
||||
"fmt"
|
||||
"github.com/ouqiang/gocron/service"
|
||||
"github.com/go-macaron/binding"
|
||||
)
|
||||
|
||||
// 系统安装
|
||||
|
@ -110,7 +110,7 @@ func writeConfig(form InstallForm) error {
|
|||
"db.host", form.DbHost,
|
||||
"db.port", strconv.Itoa(form.DbPort),
|
||||
"db.user", form.DbUsername,
|
||||
"db.password",form.DbPassword,
|
||||
"db.password", form.DbPassword,
|
||||
"db.database", form.DbName,
|
||||
"db.prefix", form.DbTablePrefix,
|
||||
"db.charset", "utf8",
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package loginlog
|
||||
|
||||
import (
|
||||
"gopkg.in/macaron.v1"
|
||||
"github.com/Unknwon/paginater"
|
||||
"fmt"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"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"
|
||||
)
|
||||
|
||||
|
@ -19,7 +19,7 @@ func Index(ctx *macaron.Context) {
|
|||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
PageParams := fmt.Sprintf("page_size=%d", params["PageSize"]);
|
||||
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
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
package manage
|
||||
|
||||
import (
|
||||
"gopkg.in/macaron.v1"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"encoding/json"
|
||||
"github.com/ouqiang/gocron/models"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"encoding/json"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
|
||||
// region slack
|
||||
|
||||
func EditSlack(ctx *macaron.Context) {
|
||||
|
@ -89,7 +88,6 @@ func Mail(ctx *macaron.Context) string {
|
|||
return json.Success("", mail)
|
||||
}
|
||||
|
||||
|
||||
type MailServerForm struct {
|
||||
Host string `binding:"Required;MaxSize(100)"`
|
||||
Port int `binding:"Required;Range(1-65535)"`
|
||||
|
|
|
@ -2,26 +2,26 @@ 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/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"
|
||||
)
|
||||
|
||||
// 静态文件目录
|
||||
|
@ -97,7 +97,7 @@ func Register(m *macaron.Macaron) {
|
|||
m.Post("/tasklog/remove/:id", tasklog.Remove)
|
||||
m.Post("/task/enable/:id", task.Enable)
|
||||
m.Post("/task/disable/:id", task.Disable)
|
||||
}, apiAuth);
|
||||
}, apiAuth)
|
||||
|
||||
// 404错误
|
||||
m.NotFound(func(ctx *macaron.Context) {
|
||||
|
@ -141,9 +141,9 @@ func RegisterMiddleware(m *macaron.Macaron) {
|
|||
IndentJSON: true,
|
||||
// 渲染具有缩进格式的 XML,默认为不缩进
|
||||
IndentXML: true,
|
||||
Funcs: []template.FuncMap{map[string]interface{} {
|
||||
Funcs: []template.FuncMap{map[string]interface{}{
|
||||
"HostFormat": func(index int) bool {
|
||||
return (index + 1) % 3 == 0
|
||||
return (index+1)%3 == 0
|
||||
},
|
||||
"unescape": func(str string) template.HTML {
|
||||
return template.HTML(str)
|
||||
|
@ -158,7 +158,7 @@ func RegisterMiddleware(m *macaron.Macaron) {
|
|||
}))
|
||||
m.Use(toolbox.Toolboxer(m))
|
||||
checkAppInstall(m)
|
||||
m.Use(func(ctx *macaron.Context, sess session.Store){
|
||||
m.Use(func(ctx *macaron.Context, sess session.Store) {
|
||||
if app.Installed {
|
||||
ipAuth(ctx)
|
||||
userAuth(ctx, sess)
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
package task
|
||||
|
||||
import (
|
||||
"gopkg.in/macaron.v1"
|
||||
"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/service"
|
||||
"strconv"
|
||||
"github.com/jakecoffman/cron"
|
||||
"github.com/Unknwon/paginater"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"github.com/ouqiang/gocron/routers/base"
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/ouqiang/gocron/service"
|
||||
"gopkg.in/macaron.v1"
|
||||
"html/template"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -36,7 +36,6 @@ type TaskForm struct {
|
|||
NotifyReceiverId string
|
||||
}
|
||||
|
||||
|
||||
func (f TaskForm) Error(ctx *macaron.Context, errs binding.Errors) {
|
||||
if len(errs) == 0 {
|
||||
return
|
||||
|
@ -65,7 +64,7 @@ func Index(ctx *macaron.Context) {
|
|||
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["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
|
||||
|
@ -98,7 +97,7 @@ func Edit(ctx *macaron.Context) {
|
|||
if err != nil {
|
||||
logger.Error(err)
|
||||
} else {
|
||||
for i, host := range(hosts) {
|
||||
for i, host := range hosts {
|
||||
if inHosts(task.Hosts, host.Id) {
|
||||
hosts[i].Selected = true
|
||||
}
|
||||
|
@ -163,8 +162,8 @@ func Store(ctx *macaron.Context, form TaskForm) string {
|
|||
return json.CommonFailure("任务重试次数取值0-10")
|
||||
}
|
||||
|
||||
if (taskModel.DependencyStatus != models.TaskDependencyStatusStrong &&
|
||||
taskModel.DependencyStatus != models.TaskDependencyStatusWeak) {
|
||||
if taskModel.DependencyStatus != models.TaskDependencyStatusStrong &&
|
||||
taskModel.DependencyStatus != models.TaskDependencyStatusWeak {
|
||||
return json.CommonFailure("请选择依赖关系")
|
||||
}
|
||||
|
||||
|
@ -250,7 +249,7 @@ func Run(ctx *macaron.Context) string {
|
|||
id := ctx.ParamsInt(":id")
|
||||
json := utils.JsonResponse{}
|
||||
taskModel := new(models.Task)
|
||||
task , err := taskModel.Detail(id)
|
||||
task, err := taskModel.Detail(id)
|
||||
if err != nil || task.Id <= 0 {
|
||||
return json.CommonFailure("获取任务详情失败", err)
|
||||
}
|
||||
|
@ -259,7 +258,7 @@ func Run(ctx *macaron.Context) string {
|
|||
serviceTask := new(service.Task)
|
||||
serviceTask.Run(task)
|
||||
|
||||
return json.Success("任务已开始运行, 请到任务日志中查看结果", nil);
|
||||
return json.Success("任务已开始运行, 请到任务日志中查看结果", nil)
|
||||
}
|
||||
|
||||
// 改变任务状态
|
||||
|
@ -297,7 +296,7 @@ func addTaskToTimer(id int) {
|
|||
}
|
||||
|
||||
// 解析查询参数
|
||||
func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
|
||||
func parseQueryParams(ctx *macaron.Context) models.CommonMap {
|
||||
var params models.CommonMap = models.CommonMap{}
|
||||
params["Id"] = ctx.QueryInt("id")
|
||||
params["HostId"] = ctx.QueryInt("host_id")
|
||||
|
@ -305,7 +304,7 @@ func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
|
|||
params["Protocol"] = ctx.QueryInt("protocol")
|
||||
params["Tag"] = ctx.QueryTrim("tag")
|
||||
status := ctx.QueryInt("status")
|
||||
if status >=0 {
|
||||
if status >= 0 {
|
||||
status -= 1
|
||||
}
|
||||
params["Status"] = status
|
||||
|
|
|
@ -3,14 +3,14 @@ package tasklog
|
|||
// 任务日志
|
||||
|
||||
import (
|
||||
"gopkg.in/macaron.v1"
|
||||
"fmt"
|
||||
"github.com/Unknwon/paginater"
|
||||
"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"
|
||||
"gopkg.in/macaron.v1"
|
||||
"html/template"
|
||||
)
|
||||
|
||||
func Index(ctx *macaron.Context) {
|
||||
|
@ -26,7 +26,7 @@ func Index(ctx *macaron.Context) {
|
|||
}
|
||||
PageParams := fmt.Sprintf("task_id=%d&protocol=%d&status=%d&page_size=%d",
|
||||
queryParams["TaskId"], queryParams["Protocol"], queryParams["Status"],
|
||||
queryParams["PageSize"]);
|
||||
queryParams["PageSize"])
|
||||
queryParams["PageParams"] = template.URL(PageParams)
|
||||
p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
|
||||
ctx.Data["Pagination"] = p
|
||||
|
@ -65,12 +65,12 @@ func Remove(ctx *macaron.Context) string {
|
|||
}
|
||||
|
||||
// 解析查询参数
|
||||
func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
|
||||
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 {
|
||||
if status >= 0 {
|
||||
status -= 1
|
||||
}
|
||||
params["Status"] = status
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
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/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<qingqianludao@gmail.com>
|
||||
|
@ -55,7 +55,7 @@ func ValidateLogin(ctx *macaron.Context, sess session.Store, cpt *captcha.Captch
|
|||
if username == "" || password == "" {
|
||||
return json.CommonFailure("用户名、密码不能为空")
|
||||
}
|
||||
userModel := new (models.User)
|
||||
userModel := new(models.User)
|
||||
if !userModel.Match(username, password) {
|
||||
return json.CommonFailure("用户名或密码错误")
|
||||
}
|
||||
|
@ -71,7 +71,6 @@ func ValidateLogin(ctx *macaron.Context, sess session.Store, cpt *captcha.Captch
|
|||
logger.Error("记录用户登录日志失败", err)
|
||||
}
|
||||
|
||||
|
||||
sess.Set("username", userModel.Name)
|
||||
sess.Set("uid", userModel.Id)
|
||||
sess.Set("isAdmin", userModel.IsAdmin)
|
||||
|
@ -91,7 +90,7 @@ func Logout(ctx *macaron.Context, sess session.Store) {
|
|||
}
|
||||
|
||||
func Username(sess session.Store) string {
|
||||
username,ok := sess.Get("username").(string)
|
||||
username, ok := sess.Get("username").(string)
|
||||
if ok {
|
||||
return username
|
||||
}
|
||||
|
@ -100,7 +99,7 @@ func Username(sess session.Store) string {
|
|||
}
|
||||
|
||||
func Uid(sess session.Store) int {
|
||||
uid,ok := sess.Get("uid").(int)
|
||||
uid, ok := sess.Get("uid").(int)
|
||||
if ok {
|
||||
return uid
|
||||
}
|
||||
|
|
|
@ -1,25 +1,27 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/ouqiang/gocron/models"
|
||||
"strconv"
|
||||
"time"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"github.com/jakecoffman/cron"
|
||||
"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"
|
||||
"sync"
|
||||
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
|
||||
|
||||
|
@ -116,7 +118,7 @@ func (task *Task) BatchAdd(tasks []models.Task) {
|
|||
// 添加任务
|
||||
func (task *Task) Add(taskModel models.Task) {
|
||||
if taskModel.Level == models.TaskLevelChild {
|
||||
logger.Errorf("添加任务失败#不允许添加子任务到调度器#任务Id-%d", taskModel.Id);
|
||||
logger.Errorf("添加任务失败#不允许添加子任务到调度器#任务Id-%d", taskModel.Id)
|
||||
return
|
||||
}
|
||||
taskFunc := createJob(taskModel)
|
||||
|
@ -148,7 +150,6 @@ type Handler interface {
|
|||
Run(taskModel models.Task) (string, error)
|
||||
}
|
||||
|
||||
|
||||
// HTTP任务
|
||||
type HTTPHandler struct{}
|
||||
|
||||
|
@ -169,7 +170,7 @@ func (h *HTTPHandler) Run(taskModel models.Task) (result string, err error) {
|
|||
}
|
||||
|
||||
// RPC调用执行任务
|
||||
type RPCHandler struct {}
|
||||
type RPCHandler struct{}
|
||||
|
||||
func (h *RPCHandler) Run(taskModel models.Task) (result string, err error) {
|
||||
taskRequest := new(pb.TaskRequest)
|
||||
|
@ -178,7 +179,7 @@ func (h *RPCHandler) Run(taskModel models.Task) (result string, err error) {
|
|||
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)
|
||||
output, err := rpcClient.Exec(th.Name, th.Port, taskRequest)
|
||||
var errorMessage string = ""
|
||||
if err != nil {
|
||||
errorMessage = err.Error()
|
||||
|
@ -186,14 +187,14 @@ func (h *RPCHandler) Run(taskModel models.Task) (result string, 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}
|
||||
resultChan <- TaskResult{Err: err, Result: outputMessage}
|
||||
}(taskHost)
|
||||
}
|
||||
|
||||
var aggregationErr error = nil
|
||||
var aggregationResult string = ""
|
||||
for i := 0; i < len(taskModel.Hosts); i++ {
|
||||
taskResult := <- resultChan
|
||||
taskResult := <-resultChan
|
||||
aggregationResult += taskResult.Result
|
||||
if taskResult.Err != nil {
|
||||
aggregationErr = taskResult.Err
|
||||
|
@ -203,7 +204,6 @@ func (h *RPCHandler) Run(taskModel models.Task) (result string, err error) {
|
|||
return aggregationResult, aggregationErr
|
||||
}
|
||||
|
||||
|
||||
// 创建任务日志
|
||||
func createTaskLog(taskModel models.Task, status models.Status) (int64, error) {
|
||||
taskLogModel := new(models.TaskLog)
|
||||
|
@ -275,8 +275,7 @@ func createHandler(taskModel models.Task) Handler {
|
|||
handler = new(RPCHandler)
|
||||
}
|
||||
|
||||
|
||||
return handler;
|
||||
return handler
|
||||
}
|
||||
|
||||
// 任务前置操作
|
||||
|
@ -333,7 +332,7 @@ func execDependencyTask(taskModel models.Task, taskResult TaskResult) {
|
|||
|
||||
// 获取子任务
|
||||
model := new(models.Task)
|
||||
tasks , err := model.GetDependencyTaskList(dependencyTaskId)
|
||||
tasks, err := model.GetDependencyTaskList(dependencyTaskId)
|
||||
if err != nil {
|
||||
logger.Errorf("获取依赖任务失败#主任务ID-%d#%s", taskModel.Id, err.Error())
|
||||
return
|
||||
|
@ -375,7 +374,7 @@ func SendNotification(taskModel models.Task, taskResult TaskResult) {
|
|||
"output": taskResult.Result,
|
||||
"status": statusName,
|
||||
"taskId": taskModel.Id,
|
||||
};
|
||||
}
|
||||
notify.Push(msg)
|
||||
}
|
||||
|
||||
|
@ -385,13 +384,13 @@ func execJob(handler Handler, taskModel models.Task) TaskResult {
|
|||
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) {
|
||||
if taskModel.RetryTimes > 0 {
|
||||
execTimes += taskModel.RetryTimes
|
||||
}
|
||||
var i int8 = 0
|
||||
|
@ -406,7 +405,7 @@ func execJob(handler Handler, taskModel models.Task) TaskResult {
|
|||
if i < execTimes {
|
||||
logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error())
|
||||
// 重试间隔时间,每次递增1分钟
|
||||
time.Sleep( time.Duration(i) * time.Minute)
|
||||
time.Sleep(time.Duration(i) * time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ 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 {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
@ -219,7 +219,7 @@ func parseDescriptor(spec string) (Schedule,error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse duration %s: %s", spec, err)
|
||||
}
|
||||
return Every(duration),nil
|
||||
return Every(duration), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Unrecognized descriptor: %s", spec)
|
||||
|
|
Loading…
Reference in New Issue