style: 代码格式化

pull/21/merge
ouqiang 2017-09-16 17:58:33 +08:00
parent 21028ec6f0
commit f0ff9a88a7
47 changed files with 3411 additions and 3458 deletions

View File

@ -1,25 +1,24 @@
package cmd package cmd
import ( import (
"github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/app" "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/routers"
"github.com/ouqiang/gocron/service"
"github.com/urfave/cli" "github.com/urfave/cli"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
"github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/service"
"github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/setting"
"time" "time"
"github.com/ouqiang/gocron/modules/rpc/grpcpool"
) )
// web服务器默认端口 // web服务器默认端口
const DefaultPort = 5920 const DefaultPort = 5920
var CmdWeb = cli.Command{ var CmdWeb = cli.Command{
Name: "web", Name: "web",
Usage: "run web server", Usage: "run web server",
@ -128,7 +127,7 @@ func catchSignal() {
// todo 配置热更新, windows 不支持 syscall.SIGUSR1, syscall.SIGUSR2 // todo 配置热更新, windows 不支持 syscall.SIGUSR1, syscall.SIGUSR2
signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
for { for {
s := <- c s := <-c
logger.Info("收到信号 -- ", s) logger.Info("收到信号 -- ", s)
switch s { switch s {
case syscall.SIGHUP: case syscall.SIGHUP:
@ -139,7 +138,6 @@ func catchSignal() {
} }
} }
// 应用退出 // 应用退出
func shutdown() { func shutdown() {
defer func() { defer func() {
@ -178,7 +176,7 @@ func upgradeIfNeed() {
currentVersionId := app.GetCurrentVersionId() currentVersionId := app.GetCurrentVersionId()
// 没有版本号文件 // 没有版本号文件
if currentVersionId == 0 { if currentVersionId == 0 {
return; return
} }
if currentVersionId >= app.VersionId { if currentVersionId >= app.VersionId {
return return

View File

@ -4,14 +4,14 @@
package main package main
import ( import (
"github.com/ouqiang/gocron/modules/rpc/server"
"flag" "flag"
"runtime"
"os"
"fmt" "fmt"
"strings"
"github.com/ouqiang/gocron/modules/rpc/auth" "github.com/ouqiang/gocron/modules/rpc/auth"
"github.com/ouqiang/gocron/modules/rpc/server"
"github.com/ouqiang/gocron/modules/utils" "github.com/ouqiang/gocron/modules/utils"
"os"
"runtime"
"strings"
) )
const AppVersion = "1.2.2" const AppVersion = "1.2.2"
@ -38,7 +38,7 @@ func main() {
return return
} }
if (enableTLS) { if enableTLS {
if !utils.FileExist(CAFile) { if !utils.FileExist(CAFile) {
fmt.Printf("failed to read ca cert file: %s", CAFile) fmt.Printf("failed to read ca cert file: %s", CAFile)
return return
@ -59,12 +59,10 @@ func main() {
KeyFile: strings.TrimSpace(keyFile), KeyFile: strings.TrimSpace(keyFile),
} }
if runtime.GOOS != "windows" && os.Getuid() == 0 && !allowRoot { if runtime.GOOS != "windows" && os.Getuid() == 0 && !allowRoot {
fmt.Println("Do not run gocron-node as root user") fmt.Println("Do not run gocron-node as root user")
return return
} }
server.Start(serverAddr, enableTLS, certificate) server.Start(serverAddr, enableTLS, certificate)
} }

View File

@ -29,7 +29,6 @@ func (host *Host) UpdateBean(id int16) (int64, error) {
return Db.ID(id).Cols("name,alias,port,remark").Update(host) return Db.ID(id).Cols("name,alias,port,remark").Update(host)
} }
// 更新 // 更新
func (host *Host) Update(id int, data CommonMap) (int64, error) { 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)
@ -48,11 +47,11 @@ func (host *Host) Find(id int) error {
func (host *Host) NameExists(name string, id int16) (bool, error) { func (host *Host) NameExists(name string, id int16) (bool, error) {
if id == 0 { if id == 0 {
count, err := Db.Where("name = ?", name).Count(host); count, err := Db.Where("name = ?", name).Count(host)
return count > 0, err 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 return count > 0, err
} }

View File

@ -3,12 +3,11 @@ package models
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/ouqiang/gocron/modules/logger"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"github.com/ouqiang/gocron/modules/logger"
"strconv" "strconv"
) )
type Migration struct{} type Migration struct{}
// 首次安装, 创建数据库表 // 首次安装, 创建数据库表
@ -19,10 +18,10 @@ func (migration *Migration) Install(dbName string) error {
setting := new(Setting) setting := new(Setting)
task := new(Task) task := new(Task)
tables := []interface{}{ tables := []interface{}{
&User{}, task, &TaskLog{}, &Host{}, setting,&LoginLog{},&TaskHost{}, &User{}, task, &TaskLog{}, &Host{}, setting, &LoginLog{}, &TaskHost{},
} }
for _, table := range tables { for _, table := range tables {
exist, err:= Db.IsTableExist(table) exist, err := Db.IsTableExist(table)
if exist { if exist {
return errors.New("数据表已存在") return errors.New("数据表已存在")
} }
@ -55,7 +54,7 @@ func (migration *Migration) Upgrade(oldVersionId int) {
} }
versionIds := []int{110, 122} versionIds := []int{110, 122}
upgradeFuncs := []func(*xorm.Session) error { upgradeFuncs := []func(*xorm.Session) error{
migration.upgradeFor110, migration.upgradeFor110,
migration.upgradeFor122, migration.upgradeFor122,
} }
@ -65,7 +64,7 @@ func (migration *Migration) Upgrade(oldVersionId int) {
for i, value := range versionIds { for i, value := range versionIds {
if value > oldVersionId { if value > oldVersionId {
startIndex = i startIndex = i
break; break
} }
} }
@ -91,7 +90,7 @@ func (migration *Migration) Upgrade(oldVersionId int) {
} }
dbErr := session.Rollback() dbErr := session.Rollback()
if dbErr != nil { if dbErr != nil {
logger.Fatalf("事务回滚失败-%s",dbErr.Error()) logger.Fatalf("事务回滚失败-%s", dbErr.Error())
} }
logger.Fatal(err) logger.Fatal(err)
} }
@ -136,7 +135,6 @@ func (migration *Migration) upgradeFor110(session *xorm.Session) error {
} }
} }
// 删除task表host_id字段 // 删除task表host_id字段
_, err = session.Exec(fmt.Sprintf("ALTER TABLE %s DROP COLUMN host_id", tableName)) _, err = session.Exec(fmt.Sprintf("ALTER TABLE %s DROP COLUMN host_id", tableName))

View File

@ -5,12 +5,12 @@ import (
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/core" "github.com/go-xorm/core"
"github.com/go-xorm/xorm" "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" "gopkg.in/macaron.v1"
"strings" "strings"
"github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/app"
"time" "time"
"github.com/ouqiang/gocron/modules/setting"
) )
type Status int8 type Status int8
@ -107,7 +107,7 @@ func getDbEngineDSN(setting *setting.Setting) string {
setting.Db.User, setting.Db.User,
setting.Db.Password, setting.Db.Password,
setting.Db.Host, setting.Db.Host,
setting.Db.Port , setting.Db.Port,
setting.Db.Database, setting.Db.Database,
setting.Db.Charset) setting.Db.Charset)
} }
@ -118,7 +118,7 @@ func getDbEngineDSN(setting *setting.Setting) string {
func keepDbAlived(engine *xorm.Engine) { func keepDbAlived(engine *xorm.Engine) {
t := time.Tick(180 * time.Second) t := time.Tick(180 * time.Second)
for { for {
<- t <-t
engine.Ping() engine.Ping()
} }
} }

View File

@ -21,7 +21,7 @@ const MailUserKey = "user"
// 初始化基本字段 邮件、slack等 // 初始化基本字段 邮件、slack等
func (setting *Setting) InitBasicField() { func (setting *Setting) InitBasicField() {
setting.Code = SlackCode; setting.Code = SlackCode
setting.Key = SlackUrlKey setting.Key = SlackUrlKey
Db.Insert(setting) Db.Insert(setting)
@ -46,7 +46,7 @@ type Channel struct {
func (setting *Setting) Slack() (Slack, error) { func (setting *Setting) Slack() (Slack, error) {
list := make([]Setting, 0) list := make([]Setting, 0)
err := Db.Where("code = ?", SlackCode).Find(&list) err := Db.Where("code = ?", SlackCode).Find(&list)
slack := Slack{Url:"", Channels:make([]Channel, 0)} slack := Slack{Url: "", Channels: make([]Channel, 0)}
if err != nil { if err != nil {
return slack, err return slack, err
} }
@ -73,10 +73,9 @@ func (setting *Setting) formatSlack(list []Setting, slack *Slack) {
func (setting *Setting) UpdateSlackUrl(url string) (int64, error) { 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渠道 // 创建slack渠道
func (setting *Setting) CreateChannel(channel string) (int64, error) { func (setting *Setting) CreateChannel(channel string) (int64, error) {
setting.Code = SlackCode setting.Code = SlackCode
@ -86,7 +85,7 @@ func (setting *Setting) CreateChannel(channel string) (int64, error) {
return Db.Insert(setting) return Db.Insert(setting)
} }
func (setting *Setting) IsChannelExist(channel string) (bool) { func (setting *Setting) IsChannelExist(channel string) bool {
setting.Code = SlackCode setting.Code = SlackCode
setting.Key = SlackChannelKey setting.Key = SlackChannelKey
setting.Value = channel setting.Value = channel
@ -124,7 +123,7 @@ type MailUser struct {
func (setting *Setting) Mail() (Mail, error) { func (setting *Setting) Mail() (Mail, error) {
list := make([]Setting, 0) list := make([]Setting, 0)
err := Db.Where("code = ?", MailCode).Find(&list) err := Db.Where("code = ?", MailCode).Find(&list)
mail := Mail{MailUsers:make([]MailUser, 0)} mail := Mail{MailUsers: make([]MailUser, 0)}
if err != nil { if err != nil {
return mail, err return mail, err
} }
@ -149,7 +148,7 @@ func (setting *Setting) formatMail(list []Setting, mail *Mail) {
func (setting *Setting) UpdateMailServer(config string) (int64, error) { func (setting *Setting) UpdateMailServer(config string) (int64, error) {
setting.Value = config 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) { func (setting *Setting) CreateMailUser(username, email string) (int64, error) {
@ -171,4 +170,5 @@ func (setting *Setting) RemoveMailUser(id int) (int64, error) {
setting.Id = id setting.Id = id
return Db.Delete(setting) return Db.Delete(setting)
} }
// endregion // endregion

View File

@ -1,10 +1,10 @@
package models package models
import ( import (
"time"
"github.com/go-xorm/xorm"
"errors" "errors"
"github.com/go-xorm/xorm"
"strings" "strings"
"time"
) )
type TaskProtocol int8 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) { func (task *Task) NameExist(name string, id int) (bool, error) {
if id > 0 { 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 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 return count > 0, err
} }
@ -175,7 +175,7 @@ func (task *Task) GetStatus(id int) (Status, error) {
return task.Status, nil return task.Status, nil
} }
func(task *Task) Detail(id int) (Task, error) { func (task *Task) Detail(id int) (Task, error) {
t := Task{} t := Task{}
_, err := Db.Where("id=?", id).Get(&t) _, err := Db.Where("id=?", id).Get(&t)
@ -253,7 +253,7 @@ func (task *Task) parseWhere(session *xorm.Session, params CommonMap) {
} }
name, ok := params["Name"] name, ok := params["Name"]
if ok && name.(string) != "" { if ok && name.(string) != "" {
session.And("t.name LIKE ?", "%" + name.(string) + "%") session.And("t.name LIKE ?", "%"+name.(string)+"%")
} }
protocol, ok := params["Protocol"] protocol, ok := params["Protocol"]
if ok && protocol.(int) > 0 { if ok && protocol.(int) > 0 {
@ -269,4 +269,3 @@ func (task *Task) parseWhere(session *xorm.Session, params CommonMap) {
session.And("tag = ? ", tag) session.And("tag = ? ", tag)
} }
} }

View File

@ -1,6 +1,5 @@
package models package models
type TaskHost struct { type TaskHost struct {
Id int `xorm:"int pk autoincr"` Id int `xorm:"int pk autoincr"`
TaskId int `xorm:"int not null index"` TaskId int `xorm:"int not null index"`
@ -75,7 +74,7 @@ func (th *TaskHost) GetTaskIdsByHostId(hostId int16) ([]interface{}, error) {
// 判断主机id是否有引用 // 判断主机id是否有引用
func (th *TaskHost) HostIdExist(hostId int16) (bool, error) { 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 return count > 0, err
} }

View File

@ -1,13 +1,12 @@
package models package models
import ( import (
"time"
"github.com/go-xorm/xorm" "github.com/go-xorm/xorm"
"time"
) )
type TaskType int8 type TaskType int8
// 任务执行日志 // 任务执行日志
type TaskLog struct { type TaskLog struct {
Id int64 `xorm:"bigint pk autoincr"` Id int64 `xorm:"bigint pk autoincr"`
@ -63,7 +62,7 @@ func (taskLog *TaskLog) List(params CommonMap) ([]TaskLog, error) {
// 清空表 // 清空表
func (taskLog *TaskLog) Clear() (int64, error) { func (taskLog *TaskLog) Clear() (int64, error) {
return Db.Where("1=1").Delete(taskLog); return Db.Where("1=1").Delete(taskLog)
} }
// 删除N个月前的日志 // 删除N个月前的日志

View File

@ -4,11 +4,11 @@ import (
"os" "os"
"github.com/ouqiang/gocron/modules/logger" "github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/setting"
"github.com/ouqiang/gocron/modules/utils" "github.com/ouqiang/gocron/modules/utils"
"io/ioutil" "io/ioutil"
"strconv" "strconv"
"strings" "strings"
"github.com/ouqiang/gocron/modules/setting"
) )
var ( var (
@ -23,7 +23,6 @@ var (
VersionFile string // 版本号文件 VersionFile string // 版本号文件
) )
func InitEnv(versionString string) { func InitEnv(versionString string) {
logger.InitLogger() logger.InitLogger()
wd, err := os.Getwd() wd, err := os.Getwd()
@ -76,7 +75,7 @@ func UpdateVersionFile() {
// 获取应用当前版本号, 从版本号文件中读取 // 获取应用当前版本号, 从版本号文件中读取
func GetCurrentVersionId() int { func GetCurrentVersionId() int {
if !utils.FileExist(VersionFile) { if !utils.FileExist(VersionFile) {
return 0; return 0
} }
bytes, err := ioutil.ReadFile(VersionFile) bytes, err := ioutil.ReadFile(VersionFile)

View File

@ -3,11 +3,11 @@ package httpclient
// http-client // http-client
import ( import (
"bytes"
"fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"time" "time"
"fmt"
"bytes"
) )
type ResponseWrapper struct { type ResponseWrapper struct {
@ -25,7 +25,7 @@ func Get(url string, timeout int) ResponseWrapper {
return request(req, timeout) 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) buf := bytes.NewBufferString(params)
req, err := http.NewRequest("POST", url, buf) req, err := http.NewRequest("POST", url, buf)
if err != nil { if err != nil {

View File

@ -1,9 +1,9 @@
package logger package logger
import ( import (
"fmt"
"github.com/cihub/seelog" "github.com/cihub/seelog"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
"fmt"
"os" "os"
"runtime" "runtime"
) )

View File

@ -1,21 +1,19 @@
package notify package notify
import ( import (
"github.com/go-gomail/gomail"
"github.com/ouqiang/gocron/models" "github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/logger" "github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/utils"
"strconv" "strconv"
"strings" "strings"
"github.com/ouqiang/gocron/modules/utils"
"time" "time"
"github.com/go-gomail/gomail"
) )
// @author qiang.ou<qingqianludao@gmail.com> // @author qiang.ou<qingqianludao@gmail.com>
// @date 2017/5/1-00:19 // @date 2017/5/1-00:19
type Mail struct { type Mail struct {
} }
func (mail *Mail) Send(msg Message) { func (mail *Mail) Send(msg Message) {
@ -61,7 +59,7 @@ func (mail *Mail) send(mailSetting models.Mail, toUsers []string, msg Message)
for i < maxTimes { for i < maxTimes {
err := mailer.DialAndSend(gomailMessage) err := mailer.DialAndSend(gomailMessage)
if err == nil { if err == nil {
break; break
} }
i += 1 i += 1
time.Sleep(2 * time.Second) 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 { func (mail *Mail) getActiveMailUsers(mailSetting models.Mail, msg Message) []string {
taskReceiverIds := strings.Split(msg["task_receiver_id"].(string), ",") taskReceiverIds := strings.Split(msg["task_receiver_id"].(string), ",")
users := []string{} users := []string{}
for _, v := range(mailSetting.MailUsers) { for _, v := range mailSetting.MailUsers {
if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) { if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) {
users = append(users, v.Email) users = append(users, v.Email)
} }

View File

@ -1,9 +1,9 @@
package notify package notify
import ( import (
"time"
"github.com/ouqiang/gocron/modules/logger"
"fmt" "fmt"
"github.com/ouqiang/gocron/modules/logger"
"time"
) )
type Message map[string]interface{} 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"]) msg["content"] = fmt.Sprintf("============\n============\n============\n任务名称: %s\n状态: %s\n输出:\n %s\n", msg["name"], msg["status"], msg["output"])
logger.Debugf("%+v", msg) logger.Debugf("%+v", msg)
switch(taskType.(int8)) { switch taskType.(int8) {
case 1: case 1:
// 邮件 // 邮件
mail := Mail{} mail := Mail{}

View File

@ -1,18 +1,19 @@
package notify package notify
// 发送消息到slack // 发送消息到slack
import ( import (
"fmt" "fmt"
"github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/httpclient" "github.com/ouqiang/gocron/modules/httpclient"
"github.com/ouqiang/gocron/modules/logger" "github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/utils" "github.com/ouqiang/gocron/modules/utils"
"strings"
"github.com/ouqiang/gocron/models"
"strconv" "strconv"
"strings"
"time" "time"
) )
type Slack struct {} type Slack struct{}
func (slack *Slack) Send(msg Message) { func (slack *Slack) Send(msg Message) {
model := new(models.Setting) model := new(models.Setting)
@ -32,7 +33,7 @@ func (slack *Slack) Send(msg Message) {
logger.Debugf("%+v", slackSetting) logger.Debugf("%+v", slackSetting)
channels := slack.getActiveSlackChannels(slackSetting, msg) channels := slack.getActiveSlackChannels(slackSetting, msg)
logger.Debugf("%+v", channels) logger.Debugf("%+v", channels)
for _, channel := range(channels) { for _, channel := range channels {
slack.send(msg, slackSetting.Url, channel) slack.send(msg, slackSetting.Url, channel)
} }
} }
@ -45,7 +46,7 @@ func (slack *Slack) send(msg Message, slackUrl string, channel string) {
for i < maxTimes { for i < maxTimes {
resp := httpclient.PostJson(slackUrl, formatBody, timeout) resp := httpclient.PostJson(slackUrl, formatBody, timeout)
if resp.StatusCode == 200 { if resp.StatusCode == 200 {
break; break
} }
i += 1 i += 1
time.Sleep(2 * time.Second) 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 { func (slack *Slack) getActiveSlackChannels(slackSetting models.Slack, msg Message) []string {
taskReceiverIds := strings.Split(msg["task_receiver_id"].(string), ",") taskReceiverIds := strings.Split(msg["task_receiver_id"].(string), ",")
channels := []string{} channels := []string{}
for _, v := range(slackSetting.Channels) { for _, v := range slackSetting.Channels {
if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) { if utils.InStringSlice(taskReceiverIds, strconv.Itoa(v.Id)) {
channels = append(channels, v.Name) channels = append(channels, v.Name)
} }

View File

@ -3,10 +3,10 @@ package auth
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"io/ioutil"
"errors" "errors"
"fmt" "fmt"
"google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials"
"io/ioutil"
) )
type Certificate struct { type Certificate struct {
@ -33,14 +33,12 @@ func (c Certificate) GetTLSConfigForServer() (*tls.Config, error) {
return nil, errors.New("failed to append client certs") return nil, errors.New("failed to append client certs")
} }
tlsConfig := &tls.Config{ tlsConfig := &tls.Config{
ClientAuth: tls.RequireAndVerifyClientCert, ClientAuth: tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{certificate}, Certificates: []tls.Certificate{certificate},
ClientCAs: certPool, ClientCAs: certPool,
} }
return tlsConfig, nil return tlsConfig, nil
} }

View File

@ -1,42 +1,27 @@
package client package client
import ( import (
"errors"
"fmt"
"github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/rpc/grpcpool"
pb "github.com/ouqiang/gocron/modules/rpc/proto" pb "github.com/ouqiang/gocron/modules/rpc/proto"
"golang.org/x/net/context" "golang.org/x/net/context"
"fmt"
"time"
"errors"
"github.com/ouqiang/gocron/modules/rpc/grpcpool"
"google.golang.org/grpc/codes"
"google.golang.org/grpc" "google.golang.org/grpc"
"github.com/ouqiang/gocron/modules/logger" "google.golang.org/grpc/codes"
"time"
) )
var ( 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)
}
return "", errUnavailable
}
func Exec(ip string, port int, taskReq *pb.TaskRequest) (string, error) { func Exec(ip string, port int, taskReq *pb.TaskRequest) (string, error) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
logger.Error("panic#rpc/client.go:Exec#", err) logger.Error("panic#rpc/client.go:Exec#", err)
} }
} () }()
addr := fmt.Sprintf("%s:%d", ip, port) addr := fmt.Sprintf("%s:%d", ip, port)
conn, err := grpcpool.Pool.Get(addr) conn, err := grpcpool.Pool.Get(addr)
if err != nil { if err != nil {

View File

@ -1,17 +1,16 @@
package grpcpool package grpcpool
import ( import (
"errors"
"github.com/ouqiang/gocron/modules/app"
"github.com/ouqiang/gocron/modules/rpc/auth"
"github.com/silenceper/pool" "github.com/silenceper/pool"
"google.golang.org/grpc"
"strings"
"sync" "sync"
"time" "time"
"google.golang.org/grpc"
"errors"
"github.com/ouqiang/gocron/modules/rpc/auth"
"github.com/ouqiang/gocron/modules/app"
"strings"
) )
var ( var (
Pool GRPCPool Pool GRPCPool
) )
@ -66,7 +65,6 @@ func (p *GRPCPool) Put(addr string, conn *grpc.ClientConn) error {
return ErrInvalidConn return ErrInvalidConn
} }
// 释放连接池 // 释放连接池
func (p *GRPCPool) Release(addr string) { func (p *GRPCPool) Release(addr string) {
p.Lock() p.Lock()
@ -83,13 +81,13 @@ func (p *GRPCPool) Release(addr string) {
func (p *GRPCPool) ReleaseAll() { func (p *GRPCPool) ReleaseAll() {
p.Lock() p.Lock()
defer p.Unlock() defer p.Unlock()
for _, pool := range(p.conns) { for _, pool := range p.conns {
pool.Release() pool.Release()
} }
} }
// 初始化底层连接池 // 初始化底层连接池
func (p *GRPCPool) newCommonPool(addr string) (error) { func (p *GRPCPool) newCommonPool(addr string) error {
p.Lock() p.Lock()
defer p.Unlock() defer p.Unlock()
commonPool, ok := p.conns[addr] commonPool, ok := p.conns[addr]

View File

@ -1,24 +1,24 @@
package server package server
import ( import (
"golang.org/x/net/context" "github.com/ouqiang/gocron/modules/rpc/auth"
"net"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc"
pb "github.com/ouqiang/gocron/modules/rpc/proto" pb "github.com/ouqiang/gocron/modules/rpc/proto"
"github.com/ouqiang/gocron/modules/utils" "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/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) { func (s Server) Run(ctx context.Context, req *pb.TaskRequest) (*pb.TaskResponse, error) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
grpclog.Println(err) grpclog.Println(err)
} }
} () }()
output, err := utils.ExecShell(ctx, req.Command) output, err := utils.ExecShell(ctx, req.Command)
resp := new(pb.TaskResponse) resp := new(pb.TaskResponse)
resp.Output = output resp.Output = output
@ -36,7 +36,7 @@ func Start(addr string, enableTLS bool, certificate auth.Certificate) {
if err := recover(); err != nil { if err := recover(); err != nil {
grpclog.Println("panic", err) grpclog.Println("panic", err)
} }
} () }()
l, err := net.Listen("tcp", addr) l, err := net.Listen("tcp", addr)
if err != nil { if err != nil {
@ -62,4 +62,3 @@ func Start(addr string, enableTLS bool, certificate auth.Certificate) {
err = s.Serve(l) err = s.Serve(l)
grpclog.Fatal(err) grpclog.Fatal(err)
} }

View File

@ -2,15 +2,15 @@ package setting
import ( import (
"errors" "errors"
"gopkg.in/ini.v1"
"github.com/ouqiang/gocron/modules/utils"
"github.com/ouqiang/gocron/modules/logger" "github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/utils"
"gopkg.in/ini.v1"
) )
const DefaultSection = "default" const DefaultSection = "default"
type Setting struct { type Setting struct {
Db struct{ Db struct {
Engine string Engine string
Host string Host string
Port int 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) config, err := ini.Load(filename)
if err != nil { if err != nil {
return nil, err return nil, err
@ -88,7 +88,7 @@ func Write(config []string, filename string) error {
if len(config) == 0 { if len(config) == 0 {
return errors.New("参数不能为空") return errors.New("参数不能为空")
} }
if len(config) % 2 != 0 { if len(config)%2 != 0 {
return errors.New("参数不匹配") return errors.New("参数不匹配")
} }
@ -98,7 +98,7 @@ func Write(config []string, filename string) error {
if err != nil { if err != nil {
return err return err
} }
for i := 0 ;i < len(config); { for i := 0; i < len(config); {
_, err = section.NewKey(config[i], config[i+1]) _, err = section.NewKey(config[i], config[i+1])
if err != nil { if err != nil {
return err return err

View File

@ -1,11 +1,11 @@
package ssh package ssh
import ( import (
"golang.org/x/crypto/ssh" "errors"
"fmt" "fmt"
"golang.org/x/crypto/ssh"
"net" "net"
"time" "time"
"errors"
) )
type HostAuthType int8 // 认证方式 type HostAuthType int8 // 认证方式
@ -17,7 +17,6 @@ const (
const SSHConnectTimeout = 10 const SSHConnectTimeout = 10
type SSHConfig struct { type SSHConfig struct {
AuthType HostAuthType AuthType HostAuthType
User string User string
@ -25,7 +24,7 @@ type SSHConfig struct {
PrivateKey string PrivateKey string
Host string Host string
Port int Port int
ExecTimeout int// 执行超时时间 ExecTimeout int // 执行超时时间
} }
type Result struct { type Result struct {
@ -43,7 +42,7 @@ func parseSSHConfig(sshConfig SSHConfig) (config *ssh.ClientConfig, err error) {
ssh.Password(sshConfig.Password), ssh.Password(sshConfig.Password),
}, },
Timeout: timeout, 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 return nil
}, },
} }
@ -63,7 +62,7 @@ func parseSSHConfig(sshConfig SSHConfig) (config *ssh.ClientConfig, err error) {
ssh.PublicKeys(signer), ssh.PublicKeys(signer),
}, },
Timeout: timeout, 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 return nil
}, },
} }
@ -71,7 +70,6 @@ func parseSSHConfig(sshConfig SSHConfig) (config *ssh.ClientConfig, err error) {
return return
} }
// 执行shell命令 // 执行shell命令
func Exec(sshConfig SSHConfig, cmd string) (output string, err error) { func Exec(sshConfig SSHConfig, cmd string) (output string, err error) {
client, err := getClient(sshConfig) client, err := getClient(sshConfig)
@ -110,10 +108,10 @@ func Exec(sshConfig SSHConfig, cmd string) (output string, err error) {
// todo 等待超时后,如何停止远程正在执行的任务, 使用timeout命令但不具有通用性 // todo 等待超时后,如何停止远程正在执行的任务, 使用timeout命令但不具有通用性
go triggerTimeout(timeoutChan, sshConfig.ExecTimeout) go triggerTimeout(timeoutChan, sshConfig.ExecTimeout)
select { select {
case result := <- resultChan: case result := <-resultChan:
output = result.Output output = result.Output
err = result.Err err = result.Err
case <- timeoutChan: case <-timeoutChan:
output = "" output = ""
err = errors.New("timeout") err = errors.New("timeout")
} }
@ -131,8 +129,7 @@ func getClient(sshConfig SSHConfig) (*ssh.Client, error) {
return ssh.Dial("tcp", addr, config) return ssh.Dial("tcp", addr, config)
} }
func triggerTimeout(ch chan bool, timeout int) {
func triggerTimeout(ch chan bool, timeout int){
// 最长执行时间不能超过24小时 // 最长执行时间不能超过24小时
if timeout <= 0 || timeout > 86400 { if timeout <= 0 || timeout > 86400 {
timeout = 86400 timeout = 86400
@ -140,4 +137,3 @@ func triggerTimeout(ch chan bool, timeout int){
time.Sleep(time.Duration(timeout) * time.Second) time.Sleep(time.Duration(timeout) * time.Second)
close(ch) close(ch)
} }

View File

@ -42,7 +42,7 @@ 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 { func (j *JsonResponse) CommonFailure(message string, err ...error) string {
if len(err) > 0 { if len(err) > 0 {
logger.Warn(err) logger.Warn(err)
} }

View File

@ -3,13 +3,13 @@ package utils
import ( import (
"crypto/md5" "crypto/md5"
"encoding/hex" "encoding/hex"
"math/rand"
"time"
"runtime"
"github.com/Tang-RoseChild/mahonia"
"strings"
"os"
"fmt" "fmt"
"github.com/Tang-RoseChild/mahonia"
"math/rand"
"os"
"runtime"
"strings"
"time"
) )
// 生成长度为length的随机字符串 // 生成长度为length的随机字符串
@ -72,7 +72,7 @@ func ReplaceStrings(s string, old []string, replace []string) string {
func InStringSlice(slice []string, element string) bool { func InStringSlice(slice []string, element string) bool {
element = strings.TrimSpace(element) element = strings.TrimSpace(element)
for _, v := range slice { for _, v := range slice {
if strings.TrimSpace(v) == element{ if strings.TrimSpace(v) == element {
return true return true
} }
} }
@ -82,8 +82,8 @@ func InStringSlice(slice []string, element string) bool {
// 转义json特殊字符 // 转义json特殊字符
func EscapeJson(s string) string { func EscapeJson(s string) string {
specialChars := []string{"\\", "\b","\f", "\n", "\r", "\t", "\"",} specialChars := []string{"\\", "\b", "\f", "\n", "\r", "\t", "\""}
replaceChars := []string{ "\\\\", "\\b", "\\f", "\\n", "\\r", "\\t", "\\\"",} replaceChars := []string{"\\\\", "\\b", "\\f", "\\n", "\\r", "\\t", "\\\""}
return ReplaceStrings(s, specialChars, replaceChars) return ReplaceStrings(s, specialChars, replaceChars)
} }

View File

@ -3,10 +3,10 @@
package utils package utils
import ( import (
"errors"
"golang.org/x/net/context"
"os/exec" "os/exec"
"syscall" "syscall"
"golang.org/x/net/context"
"errors"
) )
type Result struct { type Result struct {
@ -22,16 +22,16 @@ func ExecShell(ctx context.Context, command string) (string, error) {
} }
var resultChan chan Result = make(chan Result) var resultChan chan Result = make(chan Result)
go func() { go func() {
output ,err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
resultChan <- Result{string(output), err} resultChan <- Result{string(output), err}
}() }()
select { select {
case <- ctx.Done(): case <-ctx.Done():
if cmd.Process.Pid > 0 { if cmd.Process.Pid > 0 {
syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
} }
return "", errors.New("timeout killed") return "", errors.New("timeout killed")
case result := <- resultChan: case result := <-resultChan:
return result.output, result.err return result.output, result.err
} }
} }

View File

@ -3,11 +3,11 @@
package utils package utils
import ( import (
"syscall" "errors"
"golang.org/x/net/context"
"os/exec" "os/exec"
"strconv" "strconv"
"golang.org/x/net/context" "syscall"
"errors"
) )
type Result struct { type Result struct {
@ -24,25 +24,22 @@ func ExecShell(ctx context.Context, command string) (string, error) {
} }
var resultChan chan Result = make(chan Result) var resultChan chan Result = make(chan Result)
go func() { go func() {
output ,err := cmd.CombinedOutput() output, err := cmd.CombinedOutput()
resultChan <- Result{string(output), err} resultChan <- Result{string(output), err}
}() }()
select { select {
case <- ctx.Done(): case <-ctx.Done():
if cmd.Process.Pid > 0 { if cmd.Process.Pid > 0 {
exec.Command("taskkill", "/F", "/T", "/PID", strconv.Itoa(cmd.Process.Pid)).Run() exec.Command("taskkill", "/F", "/T", "/PID", strconv.Itoa(cmd.Process.Pid)).Run()
cmd.Process.Kill() cmd.Process.Kill()
} }
return "", errors.New("timeout killed") return "", errors.New("timeout killed")
case result := <- resultChan: case result := <-resultChan:
return ConvertEncoding(result.output), result.err return ConvertEncoding(result.output), result.err
} }
return "", nil
} }
func ConvertEncoding(outputGBK string) (string) { func ConvertEncoding(outputGBK string) string {
// windows平台编码为gbk需转换为utf8才能入库 // windows平台编码为gbk需转换为utf8才能入库
outputUTF8, ok := GBK2UTF8(outputGBK) outputUTF8, ok := GBK2UTF8(outputGBK)
if ok { if ok {

View File

@ -1,8 +1,8 @@
package base package base
import ( 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) { func ParsePageAndPageSize(ctx *macaron.Context, params models.CommonMap) {

View File

@ -1,21 +1,21 @@
package host package host
import ( 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" "fmt"
"html/template" "github.com/Unknwon/paginater"
"github.com/ouqiang/gocron/routers/base"
"github.com/go-macaron/binding" "github.com/go-macaron/binding"
"github.com/ouqiang/gocron/modules/rpc/grpcpool" "github.com/ouqiang/gocron/models"
"strings" "github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/rpc/client" "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/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) { func Index(ctx *macaron.Context) {
@ -32,7 +32,7 @@ func Index(ctx *macaron.Context) {
safeNameHTML = template.HTMLEscapeString(name) safeNameHTML = template.HTMLEscapeString(name)
} }
PageParams := fmt.Sprintf("id=%d&name=%s&page_size=%d", 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) queryParams["PageParams"] = template.URL(PageParams)
p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5) p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
ctx.Data["Pagination"] = p ctx.Data["Pagination"] = p
@ -136,7 +136,7 @@ func Remove(ctx *macaron.Context) string {
return json.CommonFailure("参数错误", err) return json.CommonFailure("参数错误", err)
} }
taskHostModel := new(models.TaskHost) taskHostModel := new(models.TaskHost)
exist,err := taskHostModel.HostIdExist(int16(id)) exist, err := taskHostModel.HostIdExist(int16(id))
if err != nil { if err != nil {
return json.CommonFailure("操作失败", err) return json.CommonFailure("操作失败", err)
} }
@ -150,7 +150,7 @@ func Remove(ctx *macaron.Context) string {
return json.CommonFailure("主机不存在") return json.CommonFailure("主机不存在")
} }
_, err =hostModel.Delete(id) _, err = hostModel.Delete(id)
if err != nil { if err != nil {
return json.CommonFailure("操作失败", err) return json.CommonFailure("操作失败", err)
} }
@ -158,7 +158,6 @@ func Remove(ctx *macaron.Context) string {
addr := fmt.Sprintf("%s:%d", hostModel.Name, hostModel.Port) addr := fmt.Sprintf("%s:%d", hostModel.Name, hostModel.Port)
grpcpool.Pool.Release(addr) grpcpool.Pool.Release(addr)
return json.Success("操作成功", nil) return json.Success("操作成功", nil)
} }
@ -167,24 +166,23 @@ func Ping(ctx *macaron.Context) string {
hostModel := new(models.Host) hostModel := new(models.Host)
err := hostModel.Find(id) err := hostModel.Find(id)
json := utils.JsonResponse{} json := utils.JsonResponse{}
if err != nil || hostModel.Id <= 0{ if err != nil || hostModel.Id <= 0 {
return json.CommonFailure("主机不存在", err) return json.CommonFailure("主机不存在", err)
} }
taskReq := &rpc.TaskRequest{} taskReq := &rpc.TaskRequest{}
taskReq.Command = "echo hello" taskReq.Command = "echo hello"
taskReq.Timeout = 10 taskReq.Timeout = 10
output, err := client.Exec(hostModel.Name, hostModel.Port, taskReq) output, err := client.Exec(hostModel.Name, hostModel.Port, taskReq)
if err != nil { if err != nil {
return json.CommonFailure("连接失败-" + err.Error() + " " + output, err) return json.CommonFailure("连接失败-"+err.Error()+" "+output, err)
} }
return json.Success("连接成功", nil) return json.Success("连接成功", nil)
} }
// 解析查询参数 // 解析查询参数
func parseQueryParams(ctx *macaron.Context) (models.CommonMap) { func parseQueryParams(ctx *macaron.Context) models.CommonMap {
var params models.CommonMap = models.CommonMap{} var params models.CommonMap = models.CommonMap{}
params["Id"] = ctx.QueryInt("id") params["Id"] = ctx.QueryInt("id")
params["Name"] = ctx.QueryTrim("name") params["Name"] = ctx.QueryTrim("name")

View File

@ -1,15 +1,15 @@
package install package install
import ( import (
"fmt"
"github.com/go-macaron/binding"
"github.com/ouqiang/gocron/models" "github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/app" "github.com/ouqiang/gocron/modules/app"
"github.com/ouqiang/gocron/modules/setting" "github.com/ouqiang/gocron/modules/setting"
"github.com/ouqiang/gocron/modules/utils" "github.com/ouqiang/gocron/modules/utils"
"github.com/ouqiang/gocron/service"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
"strconv" "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.host", form.DbHost,
"db.port", strconv.Itoa(form.DbPort), "db.port", strconv.Itoa(form.DbPort),
"db.user", form.DbUsername, "db.user", form.DbUsername,
"db.password",form.DbPassword, "db.password", form.DbPassword,
"db.database", form.DbName, "db.database", form.DbName,
"db.prefix", form.DbTablePrefix, "db.prefix", form.DbTablePrefix,
"db.charset", "utf8", "db.charset", "utf8",

View File

@ -1,12 +1,12 @@
package loginlog package loginlog
import ( import (
"gopkg.in/macaron.v1"
"github.com/Unknwon/paginater"
"fmt" "fmt"
"github.com/ouqiang/gocron/modules/logger" "github.com/Unknwon/paginater"
"github.com/ouqiang/gocron/models" "github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/routers/base" "github.com/ouqiang/gocron/routers/base"
"gopkg.in/macaron.v1"
"html/template" "html/template"
) )
@ -19,7 +19,7 @@ func Index(ctx *macaron.Context) {
if err != nil { if err != nil {
logger.Error(err) logger.Error(err)
} }
PageParams := fmt.Sprintf("page_size=%d", params["PageSize"]); PageParams := fmt.Sprintf("page_size=%d", params["PageSize"])
params["PageParams"] = template.URL(PageParams) params["PageParams"] = template.URL(PageParams)
p := paginater.New(int(total), params["PageSize"].(int), params["Page"].(int), 5) p := paginater.New(int(total), params["PageSize"].(int), params["Page"].(int), 5)
ctx.Data["Pagination"] = p ctx.Data["Pagination"] = p

View File

@ -1,14 +1,13 @@
package manage package manage
import ( import (
"gopkg.in/macaron.v1" "encoding/json"
"github.com/ouqiang/gocron/modules/utils"
"github.com/ouqiang/gocron/models" "github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/logger" "github.com/ouqiang/gocron/modules/logger"
"encoding/json" "github.com/ouqiang/gocron/modules/utils"
"gopkg.in/macaron.v1"
) )
// region slack // region slack
func EditSlack(ctx *macaron.Context) { func EditSlack(ctx *macaron.Context) {
@ -89,7 +88,6 @@ func Mail(ctx *macaron.Context) string {
return json.Success("", mail) return json.Success("", mail)
} }
type MailServerForm struct { type MailServerForm struct {
Host string `binding:"Required;MaxSize(100)"` Host string `binding:"Required;MaxSize(100)"`
Port int `binding:"Required;Range(1-65535)"` Port int `binding:"Required;Range(1-65535)"`

View File

@ -2,26 +2,26 @@ package routers
import ( import (
"github.com/go-macaron/binding" "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/cache"
"github.com/go-macaron/captcha" "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("/tasklog/remove/:id", tasklog.Remove)
m.Post("/task/enable/:id", task.Enable) m.Post("/task/enable/:id", task.Enable)
m.Post("/task/disable/:id", task.Disable) m.Post("/task/disable/:id", task.Disable)
}, apiAuth); }, apiAuth)
// 404错误 // 404错误
m.NotFound(func(ctx *macaron.Context) { m.NotFound(func(ctx *macaron.Context) {
@ -141,9 +141,9 @@ func RegisterMiddleware(m *macaron.Macaron) {
IndentJSON: true, IndentJSON: true,
// 渲染具有缩进格式的 XML默认为不缩进 // 渲染具有缩进格式的 XML默认为不缩进
IndentXML: true, IndentXML: true,
Funcs: []template.FuncMap{map[string]interface{} { Funcs: []template.FuncMap{map[string]interface{}{
"HostFormat": func(index int) bool { "HostFormat": func(index int) bool {
return (index + 1) % 3 == 0 return (index+1)%3 == 0
}, },
"unescape": func(str string) template.HTML { "unescape": func(str string) template.HTML {
return template.HTML(str) return template.HTML(str)
@ -158,7 +158,7 @@ func RegisterMiddleware(m *macaron.Macaron) {
})) }))
m.Use(toolbox.Toolboxer(m)) m.Use(toolbox.Toolboxer(m))
checkAppInstall(m) checkAppInstall(m)
m.Use(func(ctx *macaron.Context, sess session.Store){ m.Use(func(ctx *macaron.Context, sess session.Store) {
if app.Installed { if app.Installed {
ipAuth(ctx) ipAuth(ctx)
userAuth(ctx, sess) userAuth(ctx, sess)

View File

@ -1,18 +1,18 @@
package task package task
import ( 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/models"
"github.com/ouqiang/gocron/modules/logger" "github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/utils" "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/ouqiang/gocron/routers/base"
"github.com/go-macaron/binding" "github.com/ouqiang/gocron/service"
"gopkg.in/macaron.v1"
"html/template"
"strconv"
"strings" "strings"
) )
@ -36,7 +36,6 @@ type TaskForm struct {
NotifyReceiverId string NotifyReceiverId string
} }
func (f TaskForm) Error(ctx *macaron.Context, errs binding.Errors) { func (f TaskForm) Error(ctx *macaron.Context, errs binding.Errors) {
if len(errs) == 0 { if len(errs) == 0 {
return return
@ -65,7 +64,7 @@ func Index(ctx *macaron.Context) {
safeNameHTML = template.HTMLEscapeString(name) safeNameHTML = template.HTMLEscapeString(name)
} }
PageParams := fmt.Sprintf("id=%d&host_id=%d&name=%s&protocol=%d&tag=%s&status=%d&page_size=%d", 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) queryParams["PageParams"] = template.URL(PageParams)
p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5) p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
ctx.Data["Pagination"] = p ctx.Data["Pagination"] = p
@ -98,7 +97,7 @@ func Edit(ctx *macaron.Context) {
if err != nil { if err != nil {
logger.Error(err) logger.Error(err)
} else { } else {
for i, host := range(hosts) { for i, host := range hosts {
if inHosts(task.Hosts, host.Id) { if inHosts(task.Hosts, host.Id) {
hosts[i].Selected = true hosts[i].Selected = true
} }
@ -163,8 +162,8 @@ func Store(ctx *macaron.Context, form TaskForm) string {
return json.CommonFailure("任务重试次数取值0-10") return json.CommonFailure("任务重试次数取值0-10")
} }
if (taskModel.DependencyStatus != models.TaskDependencyStatusStrong && if taskModel.DependencyStatus != models.TaskDependencyStatusStrong &&
taskModel.DependencyStatus != models.TaskDependencyStatusWeak) { taskModel.DependencyStatus != models.TaskDependencyStatusWeak {
return json.CommonFailure("请选择依赖关系") return json.CommonFailure("请选择依赖关系")
} }
@ -250,7 +249,7 @@ func Run(ctx *macaron.Context) string {
id := ctx.ParamsInt(":id") id := ctx.ParamsInt(":id")
json := utils.JsonResponse{} json := utils.JsonResponse{}
taskModel := new(models.Task) taskModel := new(models.Task)
task , err := taskModel.Detail(id) task, err := taskModel.Detail(id)
if err != nil || task.Id <= 0 { if err != nil || task.Id <= 0 {
return json.CommonFailure("获取任务详情失败", err) return json.CommonFailure("获取任务详情失败", err)
} }
@ -259,7 +258,7 @@ func Run(ctx *macaron.Context) string {
serviceTask := new(service.Task) serviceTask := new(service.Task)
serviceTask.Run(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{} var params models.CommonMap = models.CommonMap{}
params["Id"] = ctx.QueryInt("id") params["Id"] = ctx.QueryInt("id")
params["HostId"] = ctx.QueryInt("host_id") params["HostId"] = ctx.QueryInt("host_id")
@ -305,7 +304,7 @@ func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
params["Protocol"] = ctx.QueryInt("protocol") params["Protocol"] = ctx.QueryInt("protocol")
params["Tag"] = ctx.QueryTrim("tag") params["Tag"] = ctx.QueryTrim("tag")
status := ctx.QueryInt("status") status := ctx.QueryInt("status")
if status >=0 { if status >= 0 {
status -= 1 status -= 1
} }
params["Status"] = status params["Status"] = status

View File

@ -3,14 +3,14 @@ package tasklog
// 任务日志 // 任务日志
import ( import (
"gopkg.in/macaron.v1" "fmt"
"github.com/Unknwon/paginater"
"github.com/ouqiang/gocron/models" "github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/logger" "github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/utils" "github.com/ouqiang/gocron/modules/utils"
"github.com/Unknwon/paginater"
"fmt"
"html/template"
"github.com/ouqiang/gocron/routers/base" "github.com/ouqiang/gocron/routers/base"
"gopkg.in/macaron.v1"
"html/template"
) )
func Index(ctx *macaron.Context) { 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", PageParams := fmt.Sprintf("task_id=%d&protocol=%d&status=%d&page_size=%d",
queryParams["TaskId"], queryParams["Protocol"], queryParams["Status"], queryParams["TaskId"], queryParams["Protocol"], queryParams["Status"],
queryParams["PageSize"]); queryParams["PageSize"])
queryParams["PageParams"] = template.URL(PageParams) queryParams["PageParams"] = template.URL(PageParams)
p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5) p := paginater.New(int(total), queryParams["PageSize"].(int), queryParams["Page"].(int), 5)
ctx.Data["Pagination"] = p 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{} var params models.CommonMap = models.CommonMap{}
params["TaskId"] = ctx.QueryInt("task_id") params["TaskId"] = ctx.QueryInt("task_id")
params["Protocol"] = ctx.QueryInt("protocol") params["Protocol"] = ctx.QueryInt("protocol")
status := ctx.QueryInt("status") status := ctx.QueryInt("status")
if status >=0 { if status >= 0 {
status -= 1 status -= 1
} }
params["Status"] = status params["Status"] = status

View File

@ -1,12 +1,12 @@
package user package user
import ( 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<qingqianludao@gmail.com> // @author qiang.ou<qingqianludao@gmail.com>
@ -55,7 +55,7 @@ func ValidateLogin(ctx *macaron.Context, sess session.Store, cpt *captcha.Captch
if username == "" || password == "" { if username == "" || password == "" {
return json.CommonFailure("用户名、密码不能为空") return json.CommonFailure("用户名、密码不能为空")
} }
userModel := new (models.User) userModel := new(models.User)
if !userModel.Match(username, password) { if !userModel.Match(username, password) {
return json.CommonFailure("用户名或密码错误") return json.CommonFailure("用户名或密码错误")
} }
@ -71,7 +71,6 @@ func ValidateLogin(ctx *macaron.Context, sess session.Store, cpt *captcha.Captch
logger.Error("记录用户登录日志失败", err) logger.Error("记录用户登录日志失败", err)
} }
sess.Set("username", userModel.Name) sess.Set("username", userModel.Name)
sess.Set("uid", userModel.Id) sess.Set("uid", userModel.Id)
sess.Set("isAdmin", userModel.IsAdmin) sess.Set("isAdmin", userModel.IsAdmin)
@ -91,7 +90,7 @@ func Logout(ctx *macaron.Context, sess session.Store) {
} }
func Username(sess session.Store) string { func Username(sess session.Store) string {
username,ok := sess.Get("username").(string) username, ok := sess.Get("username").(string)
if ok { if ok {
return username return username
} }
@ -100,7 +99,7 @@ func Username(sess session.Store) string {
} }
func Uid(sess session.Store) int { func Uid(sess session.Store) int {
uid,ok := sess.Get("uid").(int) uid, ok := sess.Get("uid").(int)
if ok { if ok {
return uid return uid
} }

View File

@ -1,25 +1,27 @@
package service package service
import ( import (
"github.com/ouqiang/gocron/models"
"strconv"
"time"
"github.com/ouqiang/gocron/modules/logger"
"github.com/jakecoffman/cron"
"errors" "errors"
"fmt" "fmt"
"github.com/jakecoffman/cron"
"github.com/ouqiang/gocron/models"
"github.com/ouqiang/gocron/modules/httpclient" "github.com/ouqiang/gocron/modules/httpclient"
"github.com/ouqiang/gocron/modules/logger"
"github.com/ouqiang/gocron/modules/notify" "github.com/ouqiang/gocron/modules/notify"
"sync"
rpcClient "github.com/ouqiang/gocron/modules/rpc/client" rpcClient "github.com/ouqiang/gocron/modules/rpc/client"
pb "github.com/ouqiang/gocron/modules/rpc/proto" pb "github.com/ouqiang/gocron/modules/rpc/proto"
"strconv"
"strings" "strings"
"sync"
"time"
) )
// 定时任务调度管理器 // 定时任务调度管理器
var Cron *cron.Cron var Cron *cron.Cron
// 同一任务是否有实例处于运行中 // 同一任务是否有实例处于运行中
var runInstance Instance var runInstance Instance
// 任务计数-正在运行中的任务 // 任务计数-正在运行中的任务
var TaskNum TaskCount var TaskNum TaskCount
@ -116,7 +118,7 @@ func (task *Task) BatchAdd(tasks []models.Task) {
// 添加任务 // 添加任务
func (task *Task) Add(taskModel models.Task) { func (task *Task) Add(taskModel models.Task) {
if taskModel.Level == models.TaskLevelChild { if taskModel.Level == models.TaskLevelChild {
logger.Errorf("添加任务失败#不允许添加子任务到调度器#任务Id-%d", taskModel.Id); logger.Errorf("添加任务失败#不允许添加子任务到调度器#任务Id-%d", taskModel.Id)
return return
} }
taskFunc := createJob(taskModel) taskFunc := createJob(taskModel)
@ -148,7 +150,6 @@ type Handler interface {
Run(taskModel models.Task) (string, error) Run(taskModel models.Task) (string, error)
} }
// HTTP任务 // HTTP任务
type HTTPHandler struct{} type HTTPHandler struct{}
@ -169,7 +170,7 @@ func (h *HTTPHandler) Run(taskModel models.Task) (result string, err error) {
} }
// RPC调用执行任务 // RPC调用执行任务
type RPCHandler struct {} type RPCHandler struct{}
func (h *RPCHandler) Run(taskModel models.Task) (result string, err error) { func (h *RPCHandler) Run(taskModel models.Task) (result string, err error) {
taskRequest := new(pb.TaskRequest) 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)) var resultChan chan TaskResult = make(chan TaskResult, len(taskModel.Hosts))
for _, taskHost := range taskModel.Hosts { for _, taskHost := range taskModel.Hosts {
go func(th models.TaskHostDetail) { 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 = "" var errorMessage string = ""
if err != nil { if err != nil {
errorMessage = err.Error() 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", outputMessage := fmt.Sprintf("主机: [%s-%s]\n%s\n%s\n\n",
th.Alias, th.Name, errorMessage, output, th.Alias, th.Name, errorMessage, output,
) )
resultChan <- TaskResult{Err:err, Result: outputMessage} resultChan <- TaskResult{Err: err, Result: outputMessage}
}(taskHost) }(taskHost)
} }
var aggregationErr error = nil var aggregationErr error = nil
var aggregationResult string = "" var aggregationResult string = ""
for i := 0; i < len(taskModel.Hosts); i++ { for i := 0; i < len(taskModel.Hosts); i++ {
taskResult := <- resultChan taskResult := <-resultChan
aggregationResult += taskResult.Result aggregationResult += taskResult.Result
if taskResult.Err != nil { if taskResult.Err != nil {
aggregationErr = taskResult.Err aggregationErr = taskResult.Err
@ -203,7 +204,6 @@ func (h *RPCHandler) Run(taskModel models.Task) (result string, err error) {
return aggregationResult, aggregationErr return aggregationResult, aggregationErr
} }
// 创建任务日志 // 创建任务日志
func createTaskLog(taskModel models.Task, status models.Status) (int64, error) { func createTaskLog(taskModel models.Task, status models.Status) (int64, error) {
taskLogModel := new(models.TaskLog) taskLogModel := new(models.TaskLog)
@ -275,8 +275,7 @@ func createHandler(taskModel models.Task) Handler {
handler = new(RPCHandler) handler = new(RPCHandler)
} }
return handler
return handler;
} }
// 任务前置操作 // 任务前置操作
@ -333,7 +332,7 @@ func execDependencyTask(taskModel models.Task, taskResult TaskResult) {
// 获取子任务 // 获取子任务
model := new(models.Task) model := new(models.Task)
tasks , err := model.GetDependencyTaskList(dependencyTaskId) tasks, err := model.GetDependencyTaskList(dependencyTaskId)
if err != nil { if err != nil {
logger.Errorf("获取依赖任务失败#主任务ID-%d#%s", taskModel.Id, err.Error()) logger.Errorf("获取依赖任务失败#主任务ID-%d#%s", taskModel.Id, err.Error())
return return
@ -375,7 +374,7 @@ func SendNotification(taskModel models.Task, taskResult TaskResult) {
"output": taskResult.Result, "output": taskResult.Result,
"status": statusName, "status": statusName,
"taskId": taskModel.Id, "taskId": taskModel.Id,
}; }
notify.Push(msg) notify.Push(msg)
} }
@ -385,13 +384,13 @@ func execJob(handler Handler, taskModel models.Task) TaskResult {
if err := recover(); err != nil { if err := recover(); err != nil {
logger.Error("panic#service/task.go:execJob#", err) logger.Error("panic#service/task.go:execJob#", err)
} }
} () }()
if taskModel.Multi == 0 { if taskModel.Multi == 0 {
defer runInstance.done(taskModel.Id) defer runInstance.done(taskModel.Id)
} }
// 默认只运行任务一次 // 默认只运行任务一次
var execTimes int8 = 1 var execTimes int8 = 1
if (taskModel.RetryTimes > 0) { if taskModel.RetryTimes > 0 {
execTimes += taskModel.RetryTimes execTimes += taskModel.RetryTimes
} }
var i int8 = 0 var i int8 = 0
@ -406,7 +405,7 @@ func execJob(handler Handler, taskModel models.Task) TaskResult {
if i < execTimes { if i < execTimes {
logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error()) logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error())
// 重试间隔时间每次递增1分钟 // 重试间隔时间每次递增1分钟
time.Sleep( time.Duration(i) * time.Minute) time.Sleep(time.Duration(i) * time.Minute)
} }
} }

View File

@ -19,7 +19,7 @@ func PowInt(x int, y int) int {
if y <= 0 { if y <= 0 {
return 1 return 1
} else { } else {
if y % 2 == 0 { if y%2 == 0 {
sqrt := PowInt(x, y/2) sqrt := PowInt(x, y/2)
return sqrt * sqrt return sqrt * sqrt
} else { } else {

View File

@ -1,11 +1,11 @@
package core package core
import ( import (
"bytes"
"encoding/gob"
"errors" "errors"
"fmt" "fmt"
"time" "time"
"bytes"
"encoding/gob"
) )
const ( const (
@ -55,7 +55,6 @@ func encodeIds(ids []PK) (string, error) {
return buf.String(), err return buf.String(), err
} }
func decodeIds(s string) ([]PK, error) { func decodeIds(s string) ([]PK, error) {
pks := make([]PK, 0) pks := make([]PK, 0)

View File

@ -1,12 +1,12 @@
package cron package cron
import ( import (
"fmt"
"log" "log"
"math" "math"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"fmt"
) )
// Parse returns a new crontab schedule representing the given spec. // 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 // parseDescriptor returns a pre-defined schedule for the expression, or panics
// if none matches. // if none matches.
func parseDescriptor(spec string) (Schedule,error) { func parseDescriptor(spec string) (Schedule, error) {
switch spec { switch spec {
case "@yearly", "@annually": case "@yearly", "@annually":
return &SpecSchedule{ return &SpecSchedule{
@ -219,7 +219,7 @@ func parseDescriptor(spec string) (Schedule,error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("Failed to parse duration %s: %s", spec, err) 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) return nil, fmt.Errorf("Unrecognized descriptor: %s", spec)