mirror of https://github.com/ouqiang/gocron
任务列表增加搜索选项
parent
1e62bf7f3b
commit
8fbdd7f81e
|
@ -3,6 +3,7 @@ package models
|
|||
import (
|
||||
"time"
|
||||
"github.com/ouqiang/gocron/modules/ssh"
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
type TaskProtocol int8
|
||||
|
@ -82,7 +83,6 @@ func (task *Task) Enable(id int) (int64, error) {
|
|||
|
||||
// 获取所有激活任务
|
||||
func (task *Task) ActiveList() ([]TaskHost, error) {
|
||||
task.parsePageAndPageSize()
|
||||
list := make([]TaskHost, 0)
|
||||
fields := "t.*, host.alias,host.name,host.username,host.password,host.port,host.auth_type,host.private_key"
|
||||
err := Db.Alias("t").Join("LEFT", "host", "t.host_id=host.id").Where("t.status = ?", Enabled).Cols(fields).Find(&list)
|
||||
|
@ -92,7 +92,6 @@ func (task *Task) ActiveList() ([]TaskHost, error) {
|
|||
|
||||
// 获取某个主机下的所有激活任务
|
||||
func (task *Task) ActiveListByHostId(hostId int16) ([]TaskHost, error) {
|
||||
task.parsePageAndPageSize()
|
||||
list := make([]TaskHost, 0)
|
||||
fields := "t.*, host.alias,host.name,host.username,host.password,host.port,host.auth_type,host.private_key"
|
||||
err := Db.Alias("t").Join("LEFT", "host", "t.host_id=host.id").Where("t.status = ? AND t.host_id = ?", Enabled, hostId).Cols(fields).Find(&list)
|
||||
|
@ -126,11 +125,13 @@ func(task *Task) Detail(id int) (TaskHost, error) {
|
|||
return taskHost, err
|
||||
}
|
||||
|
||||
func (task *Task) List() ([]TaskHost, error) {
|
||||
task.parsePageAndPageSize()
|
||||
func (task *Task) List(params CommonMap) ([]TaskHost, error) {
|
||||
task.parsePageAndPageSize(params)
|
||||
list := make([]TaskHost, 0)
|
||||
fields := "t.*, host.alias"
|
||||
err := Db.Alias("t").Join("LEFT", "host", "t.host_id=host.id").Cols(fields).Desc("t.id").Limit(task.PageSize, task.pageLimitOffset()).Find(&list)
|
||||
session := Db.Alias("t").Join("LEFT", "host", "t.host_id=host.id")
|
||||
parseWhere(session, params)
|
||||
err := session.Cols(fields).Desc("t.id").Limit(task.PageSize, task.pageLimitOffset()).Find(&list)
|
||||
|
||||
return list, err
|
||||
}
|
||||
|
@ -139,7 +140,38 @@ func (task *Task) Total() (int64, error) {
|
|||
return Db.Count(task)
|
||||
}
|
||||
|
||||
func (task *Task) parsePageAndPageSize() {
|
||||
// 解析where
|
||||
func parseWhere(session *xorm.Session, params CommonMap) {
|
||||
if len(params) == 0 {
|
||||
return
|
||||
}
|
||||
hostId, ok := params["HostId"]
|
||||
if ok && hostId.(int) > 0 {
|
||||
session.And("host_id = ? ", hostId)
|
||||
}
|
||||
name, ok := params["Name"]
|
||||
if ok && name.(string) != "" {
|
||||
session.And("name = ?", name)
|
||||
}
|
||||
protocol, ok := params["Protocol"]
|
||||
if ok && protocol.(int) > 0 {
|
||||
session.And("protocol = ?", protocol)
|
||||
}
|
||||
status, ok := params["Status"]
|
||||
if ok && status.(int) > -1 {
|
||||
session.And("status = ?", status)
|
||||
}
|
||||
}
|
||||
|
||||
func (task *Task) parsePageAndPageSize(params CommonMap) {
|
||||
page, ok := params["Page"]
|
||||
if ok {
|
||||
task.Page = page.(int)
|
||||
}
|
||||
pageSize, ok := params["PageSize"]
|
||||
if ok {
|
||||
task.PageSize = pageSize.(int)
|
||||
}
|
||||
if task.Page <= 0 {
|
||||
task.Page = Page
|
||||
}
|
||||
|
|
|
@ -34,43 +34,43 @@ func Debug(v ...interface{}) {
|
|||
write(DEBUG, v)
|
||||
}
|
||||
|
||||
func Debugf(format string, v... interface{}) {
|
||||
writef(DEBUG, format, v)
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
writef(DEBUG, format, v...)
|
||||
}
|
||||
|
||||
func Info(v ...interface{}) {
|
||||
write(INFO, v)
|
||||
}
|
||||
|
||||
func Infof(format string, v... interface{}) {
|
||||
writef(INFO, format, v)
|
||||
func Infof(format string, v ...interface{}) {
|
||||
writef(INFO, format, v...)
|
||||
}
|
||||
|
||||
func Warn(v ...interface{}) {
|
||||
write(WARN, v)
|
||||
}
|
||||
|
||||
func Warnf(format string, v... interface{}) {
|
||||
writef(WARN, format, v)
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
writef(WARN, format, v...)
|
||||
}
|
||||
|
||||
func Error(v ...interface{}) {
|
||||
write(ERROR, v)
|
||||
}
|
||||
|
||||
func Errorf(format string, v... interface{}) {
|
||||
writef(ERROR, format, v)
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
writef(ERROR, format, v...)
|
||||
}
|
||||
|
||||
func Fatal(v ...interface{}) {
|
||||
write(FATAL, v)
|
||||
}
|
||||
|
||||
func Fatalf(format string, v... interface{}) {
|
||||
writef(FATAL, format, v)
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
writef(FATAL, format, v...)
|
||||
}
|
||||
|
||||
func write(level Level, v... interface{}) {
|
||||
func write(level Level, v ...interface{}) {
|
||||
defer logger.Flush()
|
||||
|
||||
switch level {
|
||||
|
@ -88,21 +88,21 @@ func write(level Level, v... interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
func writef(level Level, format string, v... interface{}) {
|
||||
func writef(level Level, format string, v ...interface{}) {
|
||||
defer logger.Flush()
|
||||
|
||||
switch level {
|
||||
case DEBUG:
|
||||
logger.Debugf(format, v)
|
||||
logger.Debugf(format, v...)
|
||||
case INFO:
|
||||
logger.Infof(format, v)
|
||||
logger.Infof(format, v...)
|
||||
case WARN:
|
||||
logger.Warnf(format, v)
|
||||
logger.Warnf(format, v...)
|
||||
case FATAL:
|
||||
logger.Criticalf(format, v)
|
||||
logger.Criticalf(format, v...)
|
||||
os.Exit(1)
|
||||
case ERROR:
|
||||
logger.Errorf(format, v)
|
||||
logger.Errorf(format, v...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ func RegisterMiddleware(m *macaron.Macaron) {
|
|||
})
|
||||
// 设置模板共享变量
|
||||
m.Use(func(ctx *macaron.Context) {
|
||||
ctx.Data["URI"] = ctx.Req.RequestURI
|
||||
ctx.Data["URI"] = ctx.Req.URL.Path
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -25,27 +25,21 @@ type TaskForm struct {
|
|||
|
||||
func Index(ctx *macaron.Context) {
|
||||
taskModel := new(models.Task)
|
||||
tasks, err := taskModel.List()
|
||||
queryParams := parseQueryParams(ctx)
|
||||
tasks, err := taskModel.List(queryParams)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
}
|
||||
setHostsToTemplate(ctx)
|
||||
ctx.Data["Params"] = queryParams
|
||||
ctx.Data["Title"] = "任务列表"
|
||||
ctx.Data["Tasks"] = tasks
|
||||
ctx.HTML(200, "task/index")
|
||||
}
|
||||
|
||||
func Create(ctx *macaron.Context) {
|
||||
hostModel := new(models.Host)
|
||||
hosts, err := hostModel.List()
|
||||
if err != nil || len(hosts) == 0 {
|
||||
logger.Error(err)
|
||||
}
|
||||
setHostsToTemplate(ctx)
|
||||
ctx.Data["Title"] = "添加任务"
|
||||
ctx.Data["Hosts"] = hosts
|
||||
if len(hosts) > 0 {
|
||||
ctx.Data["FirstHostName"] = hosts[0].Name
|
||||
ctx.Data["FirstHostId"] = hosts[0].Id
|
||||
}
|
||||
ctx.HTML(200, "task/task_form")
|
||||
}
|
||||
|
||||
|
@ -197,3 +191,31 @@ func addTaskToTimer(id int) {
|
|||
taskService := service.Task{}
|
||||
taskService.Add(task)
|
||||
}
|
||||
|
||||
// 解析查询参数
|
||||
func parseQueryParams(ctx *macaron.Context) (models.CommonMap) {
|
||||
var params models.CommonMap = models.CommonMap{}
|
||||
params["HostId"] = ctx.QueryInt("host_id")
|
||||
params["Name"] = ctx.QueryTrim("name")
|
||||
params["Protocol"] = ctx.QueryInt("protocol")
|
||||
params["Status"] = ctx.QueryInt("status")
|
||||
params["Page"] = ctx.QueryInt("page")
|
||||
params["PageSize"] = ctx.QueryInt("page_size")
|
||||
|
||||
logger.Debug("%+v", params)
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
func setHostsToTemplate(ctx *macaron.Context) {
|
||||
hostModel := new(models.Host)
|
||||
hosts, err := hostModel.List()
|
||||
if err != nil || len(hosts) == 0 {
|
||||
logger.Error(err)
|
||||
}
|
||||
ctx.Data["Hosts"] = hosts
|
||||
if len(hosts) > 0 {
|
||||
ctx.Data["FirstHostName"] = hosts[0].Name
|
||||
ctx.Data["FirstHostId"] = hosts[0].Id
|
||||
}
|
||||
}
|
|
@ -138,7 +138,7 @@ func (h *HTTPHandler) Run(taskModel models.TaskHost) (result string, err error)
|
|||
return
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return string(body), errors.New(fmt.Sprintf("HTTP状态码非200-%d", resp.StatusCode))
|
||||
return string(body), errors.New(fmt.Sprintf("HTTP状态码非200-->%d", resp.StatusCode))
|
||||
}
|
||||
|
||||
return string(body), err
|
||||
|
@ -183,7 +183,7 @@ func createTaskLog(taskModel models.TaskHost) (int64, error) {
|
|||
func updateTaskLog(taskLogId int64, taskResult TaskResult) (int64, error) {
|
||||
taskLogModel := new(models.TaskLog)
|
||||
var status models.Status
|
||||
var result string
|
||||
var result string = taskResult.Result
|
||||
if taskResult.Err != nil {
|
||||
result = taskResult.Err.Error() + " " + result
|
||||
status = models.Failure
|
||||
|
@ -191,6 +191,7 @@ func updateTaskLog(taskLogId int64, taskResult TaskResult) (int64, error) {
|
|||
status = models.Finish
|
||||
}
|
||||
return taskLogModel.Update(taskLogId, models.CommonMap{
|
||||
"retry_times": taskResult.RetryTimes,
|
||||
"status": status,
|
||||
"result": result,
|
||||
})
|
||||
|
@ -248,7 +249,7 @@ func execJob(handler Handler, taskModel models.TaskHost) TaskResult {
|
|||
}
|
||||
i++
|
||||
if i < execTimes {
|
||||
logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误信息-%s", taskModel.Id, i, output, err)
|
||||
logger.Warnf("任务执行失败#任务id-%d#重试第%d次#输出-%s#错误-%s", taskModel.Id, i, output, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
<th>别名</th>
|
||||
<th>用户名</th>
|
||||
<th>端口</th>
|
||||
<th>任务数量</th>
|
||||
<th>备注</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
|
@ -33,12 +32,14 @@
|
|||
<td>{{{.Alias}}}</td>
|
||||
<td>{{{.Username}}}</td>
|
||||
<td>{{{.Port}}}</td>
|
||||
<td></td>
|
||||
<td>{{{.Remark}}}</td>
|
||||
<td class="operation">
|
||||
<a class="ui purple button" href="/host/edit/{{{.Id}}}">编辑</a>
|
||||
<button class="ui positive button" onclick="util.removeConfirm('/host/remove/{{{.Id}}}')">删除</button>
|
||||
<button class="ui positive button" onclick="util.removeConfirm('/host/remove/{{{.Id}}}')">删除</button><br>
|
||||
<div style="margin-top: 5px;">
|
||||
<a class="ui twitter button" href="/task?host_id={{{.Id}}}">查看任务</a>
|
||||
<button class="ui blue button" @click="ping({{{.Id}}})">连接测试</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{{{end}}}
|
||||
|
|
|
@ -13,6 +13,64 @@
|
|||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<form class="ui form">
|
||||
<div class="five fields">
|
||||
<div class="field">
|
||||
<input type="text" placeholder="任务名称" name="name">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>主机</label>
|
||||
<div class="ui dropdown selection">
|
||||
<input type="hidden" name="protocol" value="{{{if gt .Params.Protocol 0}}}{{{.Params.Protocol}}}{{{else}}}3{{{end}}}">
|
||||
<div class="default text">本地命令</div>
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="3">本地命令</div>
|
||||
<div class="item" data-value="2">SSH</div>
|
||||
<div class="item" data-value="1">HTTP</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline fields">
|
||||
{{{range $i, $v := .Hosts}}}
|
||||
<div class="field">
|
||||
<div class="ui radio checkbox">
|
||||
<input type="radio" name="host_id" tabindex="0" class="hidden" value="{{{.Id}}}"
|
||||
{{{if eq $.Params.HostId .Id }}} checked {{{end}}}>
|
||||
</div>
|
||||
</div>
|
||||
{{{end}}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui dropdown selection">
|
||||
<input type="hidden" name="protocol" value="{{{if gt .Params.Protocol 0}}}{{{.Params.Protocol}}}{{{else}}}3{{{end}}}">
|
||||
<div class="default text">本地命令</div>
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="-1">协议</div>
|
||||
<div class="item" data-value="3">本地命令</div>
|
||||
<div class="item" data-value="2">SSH</div>
|
||||
<div class="item" data-value="1">HTTP</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui dropdown selection">
|
||||
<input type="hidden" name="status" value="{{{if eq .Params.Status 1}}}1{{{else}}}2{{{end}}}">
|
||||
<div class="default text">暂停</div>
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="-1">状态</div>
|
||||
<div class="item" data-value="2">暂停</div>
|
||||
<div class="item" data-value="1">激活</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<button class="ui linkedin submit button">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table class="ui violet table">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -35,7 +93,7 @@
|
|||
<td>{{{.Spec}}}</td>
|
||||
<td>{{{if eq .Protocol 1}}} HTTP {{{else}}} SSH {{{end}}}</td>
|
||||
<td>{{{.Command}}}</td>
|
||||
<td>{{{.Timeout}}}</td>
|
||||
<td>{{{if gt .Timeout 0}}}{{{.Timeout}}}秒{{{else}}}不限制{{{end}}}</td>
|
||||
<td>{{{.RetryTimes}}}</td>
|
||||
<td>{{{.Alias}}}</td>
|
||||
<td>{{{.Remark}}}</td>
|
||||
|
@ -50,7 +108,7 @@
|
|||
<button class="ui positive button" @click="remove({{{.Id}}})">删除</button> <br>
|
||||
<div style="margin-top:10px;">
|
||||
<button class="ui twitter button" @click="run({{{.Id}}})">手动运行</button>
|
||||
<button class="ui instagram button">查看日志</button>
|
||||
<a class="ui instagram button" href="/task/log?task_id={{{.Id}}}">查看日志</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<td>{{{.Name}}}</td>
|
||||
<td>{{{.Spec}}}</td>
|
||||
<td>{{{if eq .Protocol 1}}} HTTP {{{else if eq .Protocol 2}}} SSH {{{else}}} 本地命令 {{{end}}}</td>
|
||||
<td>{{{.Timeout}}}秒</td>
|
||||
<td>{{{if gt .Timeout 0}}}{{{.Timeout}}}秒{{{else}}}不限制{{{end}}}</td>
|
||||
<td>{{{.RetryTimes}}}</td>
|
||||
<td>{{{.Hostname}}}</td>
|
||||
<td>
|
||||
|
|
|
@ -73,17 +73,17 @@
|
|||
<textarea rows="5" name="command">{{{.Task.Command}}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="four fields">
|
||||
<div class="two fields">
|
||||
<div class="field">
|
||||
<label>任务超时时间 (单位秒, 默认0,不限制超时)</label>
|
||||
<input type="text" name="timeout" value="{{{.Task.Timeout}}}">
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>任务执行失败重试次数(0-10次, 默认0,不重试)</label>
|
||||
<input type="text" name="retry_times" value="{{{.Task.RetryTimes}}}">
|
||||
<label>任务执行事变 (单位秒,0不限制,不能超过24小时)</label>
|
||||
<input type="text" name="timeout" value="{{{.Task.Timeout}}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="four fields">
|
||||
<div class="three fields">
|
||||
<div class="field">
|
||||
<label>任务状态 (任务添加成功后,是否立即调度)</label>
|
||||
<div class="ui dropdown selection">
|
||||
|
|
Loading…
Reference in New Issue