mirror of https://github.com/ouqiang/gocron
完善主机编辑
parent
f57561118d
commit
0a9e71cb5a
|
@ -99,6 +99,7 @@ func catchSignal() {
|
|||
}
|
||||
}
|
||||
|
||||
// 作为守护进程运行
|
||||
func becomeDaemon(ctx *cli.Context) {
|
||||
// 不支持windows
|
||||
if app.IsWindows {
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package models
|
||||
|
||||
import "github.com/ouqiang/gocron/modules/ssh"
|
||||
|
||||
|
||||
|
||||
// 主机
|
||||
type Host struct {
|
||||
Id int16 `xorm:"smallint pk autoincr"`
|
||||
|
@ -9,6 +13,8 @@ type Host struct {
|
|||
Password string `xorm:"varchar(64) notnull default ''"` // ssh 密码
|
||||
Port int `xorm:"notnull default 22"` // 主机端口
|
||||
Remark string `xorm:"varchar(512) notnull default '' "` // 备注
|
||||
AuthType ssh.HostAuthType `xorm:"tinyint notnull default 1"` // 认证方式 1: 密码 2: 公钥
|
||||
PrivateKey string `xorm:"varchar(4096) notnull default '' "` // 私钥
|
||||
Page int `xorm:"-"`
|
||||
PageSize int `xorm:"-"`
|
||||
}
|
||||
|
@ -23,6 +29,11 @@ func (host *Host) Create() (insertId int16, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (host *Host) UpdateBean() (int64, error) {
|
||||
return Db.Cols("name,alias,username,password,port,remark,auth_type,private_key").Update(host)
|
||||
}
|
||||
|
||||
|
||||
// 更新
|
||||
func (host *Host) Update(id int, data CommonMap) (int64, error) {
|
||||
return Db.Table(host).ID(id).Update(data)
|
||||
|
@ -39,9 +50,13 @@ func (host *Host) Find(id int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (host *Host) NameExists(name string) (bool, error) {
|
||||
count, err := Db.Where("name = ?", name).Count(host);
|
||||
func (host *Host) NameExists(name string, id int16) (bool, error) {
|
||||
if id == 0 {
|
||||
count, err := Db.Where("name = ?", name).Count(host);
|
||||
return count > 0, err
|
||||
}
|
||||
|
||||
count, err := Db.Where("name = ? AND id != ?", name, id).Count(host);
|
||||
return count > 0, err
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package models
|
|||
|
||||
import (
|
||||
"time"
|
||||
"github.com/ouqiang/gocron/modules/ssh"
|
||||
)
|
||||
|
||||
type TaskProtocol int8
|
||||
|
@ -36,6 +37,8 @@ type TaskHost struct {
|
|||
Username string
|
||||
Password string
|
||||
Alias string
|
||||
AuthType ssh.HostAuthType
|
||||
PrivateKey string
|
||||
}
|
||||
|
||||
func (TaskHost) TableName() string {
|
||||
|
@ -52,7 +55,7 @@ func (task *Task) Create() (insertId int, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (task *Task) UpdateBean(id int) (int64, error) {
|
||||
func (task *Task) UpdateBean() (int64, error) {
|
||||
return Db.UseBool("status").Update(task)
|
||||
}
|
||||
|
||||
|
@ -76,15 +79,26 @@ func (task *Task) Enable(id int) (int64, error) {
|
|||
return task.Update(id, CommonMap{"status": Enabled})
|
||||
}
|
||||
|
||||
// 获取所有激活任务
|
||||
func (task *Task) ActiveList() ([]TaskHost, error) {
|
||||
task.parsePageAndPageSize()
|
||||
list := make([]TaskHost, 0)
|
||||
fields := "t.*, host.name,host.username,host.password,host.port"
|
||||
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)
|
||||
|
||||
return list, err
|
||||
}
|
||||
|
||||
// 获取某个主机下的所有激活任务
|
||||
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)
|
||||
|
||||
return list, err
|
||||
}
|
||||
|
||||
// 判断主机id是否有引用
|
||||
func (task *Task) HostIdExist(hostId int16) (bool, error) {
|
||||
count, err := Db.Where("host_id = ?", hostId).Count(task);
|
||||
|
@ -105,7 +119,7 @@ func (task *Task) NameExist(name string, id int) (bool, error) {
|
|||
|
||||
func(task *Task) Detail(id int) (TaskHost, error) {
|
||||
taskHost := TaskHost{}
|
||||
fields := "t.*, host.name,host.username,host.password,host.port"
|
||||
fields := "t.*, 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.id=?", id).Cols(fields).Get(&taskHost)
|
||||
|
||||
return taskHost, err
|
||||
|
|
|
@ -8,9 +8,22 @@ import (
|
|||
"errors"
|
||||
)
|
||||
|
||||
|
||||
type HostAuthType int8 // 认证方式
|
||||
|
||||
const (
|
||||
HostPassword = 1 // 密码认证
|
||||
HostPublicKey = 2 // 公钥认证
|
||||
)
|
||||
|
||||
const SSHConnectTimeout = 10
|
||||
|
||||
|
||||
type SSHConfig struct {
|
||||
AuthType HostAuthType
|
||||
User string
|
||||
Password string
|
||||
PrivateKey string
|
||||
Host string
|
||||
Port int
|
||||
ExecTimeout int// 执行超时时间
|
||||
|
@ -21,6 +34,45 @@ type Result struct {
|
|||
Err error
|
||||
}
|
||||
|
||||
func parseSSHConfig(sshConfig SSHConfig) (config *ssh.ClientConfig, err error) {
|
||||
timeout := SSHConnectTimeout * time.Second
|
||||
// 密码认证
|
||||
if sshConfig.AuthType == HostPassword {
|
||||
config = &ssh.ClientConfig{
|
||||
User: sshConfig.User,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(sshConfig.Password),
|
||||
},
|
||||
Timeout: timeout,
|
||||
HostKeyCallback:func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
signer, err := ssh.ParsePrivateKey([]byte(sshConfig.PrivateKey))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 公钥认证
|
||||
config = &ssh.ClientConfig{
|
||||
User: sshConfig.User,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.PublicKeys(signer),
|
||||
},
|
||||
Timeout: timeout,
|
||||
HostKeyCallback:func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 执行shell命令
|
||||
func Exec(sshConfig SSHConfig, cmd string) (output string, err error) {
|
||||
client, err := getClient(sshConfig)
|
||||
|
@ -56,15 +108,9 @@ func Exec(sshConfig SSHConfig, cmd string) (output string, err error) {
|
|||
}
|
||||
|
||||
func getClient(sshConfig SSHConfig) (*ssh.Client, error) {
|
||||
config := &ssh.ClientConfig{
|
||||
User: sshConfig.User,
|
||||
Auth: []ssh.AuthMethod{
|
||||
ssh.Password(sshConfig.Password),
|
||||
},
|
||||
Timeout: 10 * time.Second,
|
||||
HostKeyCallback:func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
},
|
||||
config, err := parseSSHConfig(sshConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addr := fmt.Sprintf("%s:%d", sshConfig.Host, sshConfig.Port)
|
||||
|
||||
|
@ -80,3 +126,4 @@ func triggerTimeout(ch chan bool, timeout int){
|
|||
time.Sleep(time.Duration(timeout) * time.Second)
|
||||
close(ch)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,36 +4,43 @@
|
|||
|
||||
function Util() {
|
||||
var util = {};
|
||||
util.post = function(url, params, callback) {
|
||||
// 用户认证失败
|
||||
var SUCCESS = 0;
|
||||
var FAILURE = 1;
|
||||
var NOT_FOUND = 2;
|
||||
var AUTH_ERROR = 3;
|
||||
var SUCCESS = 0; // 操作成功
|
||||
var FAILURE_MESSAGE = '操作失败';
|
||||
util.ajaxSuccess = function(response, callback) {
|
||||
if (response.code === undefined) {
|
||||
swal(FAILURE_MESSAGE, '服务端返回值无法解析', 'error');
|
||||
return;
|
||||
}
|
||||
if (response.code != SUCCESS) {
|
||||
swal(FAILURE_MESSAGE, response.message ,'error');
|
||||
return;
|
||||
}
|
||||
callback(response.code, response.message, response.data);
|
||||
};
|
||||
util.ajaxFailure = function() {
|
||||
// todo 错误处理
|
||||
swal(FAILURE_MESSAGE, '未知错误', 'error');
|
||||
};
|
||||
util.get = function(url, callback) {
|
||||
var SUCCESS = 0; // 操作成功
|
||||
var FAILURE_MESSAGE = '操作失败';
|
||||
$.get(
|
||||
url,
|
||||
function(response) {
|
||||
util.ajaxSuccess(response, callback);
|
||||
},
|
||||
'json'
|
||||
).error(util.ajaxFailure);
|
||||
};
|
||||
util.post = function(url, params, callback) {
|
||||
$.post(
|
||||
url,
|
||||
params,
|
||||
function(response) {
|
||||
if (response.code === undefined) {
|
||||
swal(FAILURE_MESSAGE, '服务端返回值无法解析', 'error');
|
||||
}
|
||||
if (response.code == AUTH_ERROR) {
|
||||
swal(FAILURE_MESSAGE, response.message, 'error');
|
||||
return;
|
||||
}
|
||||
if (response.code == NOT_FOUND) {
|
||||
swal(FAILURE_MESSAGE, response.message, 'error');
|
||||
return;
|
||||
}
|
||||
if (response.code == FAILURE) {
|
||||
swal(FAILURE_MESSAGE, response.message ,'error');
|
||||
return;
|
||||
}
|
||||
callback(response.code, response.message, response.data);
|
||||
util.ajaxSuccess(response, callback);
|
||||
},
|
||||
'json'
|
||||
)
|
||||
).error(util.ajaxFailure);
|
||||
};
|
||||
util.confirm = function(message, callback) {
|
||||
swal({
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"strconv"
|
||||
"github.com/ouqiang/gocron/modules/ssh"
|
||||
"github.com/ouqiang/gocron/service"
|
||||
)
|
||||
|
||||
func Index(ctx *macaron.Context) {
|
||||
|
@ -36,36 +38,87 @@ func Edit(ctx *macaron.Context) {
|
|||
ctx.HTML(200, "host/host_form")
|
||||
}
|
||||
|
||||
func Ping(ctx *macaron.Context) string {
|
||||
id := ctx.ParamsInt(":id")
|
||||
hostModel := new(models.Host)
|
||||
err := hostModel.Find(id)
|
||||
json := utils.JsonResponse{}
|
||||
if err != nil || hostModel.Id <= 0{
|
||||
return json.CommonFailure("主机不存在", err)
|
||||
}
|
||||
|
||||
sshConfig := ssh.SSHConfig{
|
||||
User: hostModel.Username,
|
||||
Password: hostModel.Password,
|
||||
Host: hostModel.Name,
|
||||
Port: hostModel.Port,
|
||||
ExecTimeout: 5,
|
||||
AuthType: hostModel.AuthType,
|
||||
PrivateKey: hostModel.PrivateKey,
|
||||
}
|
||||
_, err = ssh.Exec(sshConfig, "pwd")
|
||||
if err != nil {
|
||||
return json.CommonFailure("连接失败-" + err.Error(), err)
|
||||
}
|
||||
|
||||
return json.Success("连接成功", nil)
|
||||
}
|
||||
|
||||
type HostForm struct {
|
||||
Id int16
|
||||
Name string `binding:"Required;MaxSize(100)"`
|
||||
Alias string `binding:"Required;MaxSize(32)"`
|
||||
Username string `binding:"Required;MaxSize(32)"`
|
||||
Password string `binding:"Required;MaxSize(64)"`
|
||||
Password string
|
||||
Port int `binding:"Required;Range(1-65535)"`
|
||||
AuthType ssh.HostAuthType `binding:"Required:Range(1,2)"`
|
||||
PrivateKey string
|
||||
Remark string
|
||||
}
|
||||
|
||||
func Store(ctx *macaron.Context, form HostForm) string {
|
||||
json := utils.JsonResponse{}
|
||||
hostModel := new(models.Host)
|
||||
nameExist, err := hostModel.NameExists(form.Name)
|
||||
id := form.Id
|
||||
nameExist, err := hostModel.NameExists(form.Name, form.Id)
|
||||
if err != nil {
|
||||
return json.CommonFailure("操作失败", err)
|
||||
}
|
||||
if nameExist {
|
||||
return json.CommonFailure("主机名已存在")
|
||||
}
|
||||
if form.Id > 0 {
|
||||
hostModel.Id = form.Id
|
||||
}
|
||||
hostModel.Name = form.Name
|
||||
hostModel.Alias = form.Alias
|
||||
hostModel.Username = form.Username
|
||||
hostModel.Password = form.Password
|
||||
hostModel.Port = form.Port
|
||||
hostModel.Remark = form.Remark
|
||||
_, err = hostModel.Create()
|
||||
hostModel.PrivateKey = form.PrivateKey
|
||||
hostModel.AuthType = form.AuthType
|
||||
isCreate := false
|
||||
if id > 0 {
|
||||
_, err = hostModel.UpdateBean()
|
||||
} else {
|
||||
isCreate = true
|
||||
id, err = hostModel.Create()
|
||||
}
|
||||
if err != nil {
|
||||
return json.CommonFailure("保存失败", err)
|
||||
}
|
||||
|
||||
taskModel := new(models.TaskHost)
|
||||
tasks, err := taskModel.ActiveListByHostId(id)
|
||||
if err != nil {
|
||||
return json.CommonFailure("刷新任务主机信息失败", err)
|
||||
}
|
||||
if !isCreate && len(tasks) > 0 {
|
||||
serviceTask := new(service.Task)
|
||||
serviceTask.BatchAdd(tasks)
|
||||
}
|
||||
|
||||
return json.Success("保存成功", nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,8 @@ func Register(m *macaron.Macaron) {
|
|||
// 主机
|
||||
m.Group("/host", func() {
|
||||
m.Get("/create", host.Create)
|
||||
m.Get("/Edit", host.Edit)
|
||||
m.Get("/edit/:id", host.Edit)
|
||||
m.Get("/ping/:id", host.Ping)
|
||||
m.Post("/store", binding.Bind(host.HostForm{}), host.Store)
|
||||
m.Get("", host.Index)
|
||||
m.Post("/remove/:id", host.Remove)
|
||||
|
|
|
@ -45,7 +45,7 @@ func Edit(ctx *macaron.Context) {
|
|||
}
|
||||
taskModel := new(models.Task)
|
||||
task, err := taskModel.Detail(id)
|
||||
if err != nil || taskModel.Id != id {
|
||||
if err != nil || task.Id != id {
|
||||
logger.Errorf("编辑任务#获取任务详情失败#任务ID-%d#%s", id, err.Error())
|
||||
ctx.Redirect("/task")
|
||||
}
|
||||
|
@ -92,6 +92,9 @@ func Store(ctx *macaron.Context, form TaskForm) string {
|
|||
return json.CommonFailure("请选择主机名")
|
||||
}
|
||||
|
||||
if form.Id > 0 {
|
||||
taskModel.Id = form.Id
|
||||
}
|
||||
taskModel.Name = form.Name
|
||||
taskModel.Protocol = form.Protocol
|
||||
taskModel.Command = form.Command
|
||||
|
@ -106,7 +109,7 @@ func Store(ctx *macaron.Context, form TaskForm) string {
|
|||
if id == 0 {
|
||||
id, err = taskModel.Create()
|
||||
} else {
|
||||
_, err = taskModel.UpdateBean(id)
|
||||
_, err = taskModel.UpdateBean()
|
||||
}
|
||||
if err != nil {
|
||||
return json.CommonFailure("保存失败", err)
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/ouqiang/gocron/modules/logger"
|
||||
"github.com/ouqiang/gocron/modules/ssh"
|
||||
"github.com/jakecoffman/cron"
|
||||
"strings"
|
||||
"github.com/ouqiang/gocron/modules/utils"
|
||||
"errors"
|
||||
)
|
||||
|
@ -32,7 +31,12 @@ func (task *Task) Initialize() {
|
|||
logger.Debug("任务列表为空")
|
||||
return
|
||||
}
|
||||
for _, item := range taskList {
|
||||
task.BatchAdd(taskList)
|
||||
}
|
||||
|
||||
// 批量添加任务
|
||||
func (task *Task) BatchAdd(tasks []models.TaskHost) {
|
||||
for _, item := range tasks {
|
||||
task.Add(item)
|
||||
}
|
||||
}
|
||||
|
@ -65,14 +69,10 @@ func (h *LocalCommandHandler) Run(taskModel models.TaskHost) (string, error) {
|
|||
if taskModel.Command == "" {
|
||||
return "", errors.New("invalid command")
|
||||
}
|
||||
fields := strings.Split(taskModel.Command, " ")
|
||||
var args []string
|
||||
if len(fields) > 1 {
|
||||
args = fields[1:]
|
||||
} else {
|
||||
args = []string{}
|
||||
}
|
||||
return utils.ExecShellWithTimeout(taskModel.Timeout, fields[0], args...)
|
||||
|
||||
args := []string{"-c", taskModel.Command}
|
||||
|
||||
return utils.ExecShellWithTimeout(taskModel.Timeout, "/bin/bash", args...)
|
||||
}
|
||||
|
||||
// HTTP任务
|
||||
|
@ -83,7 +83,7 @@ func (h *HTTPHandler) Run(taskModel models.TaskHost) (result string, err error)
|
|||
if taskModel.Timeout > 0 {
|
||||
client.Timeout = time.Duration(taskModel.Timeout) * time.Second
|
||||
}
|
||||
req, err := http.NewRequest("POST", taskModel.Command, nil)
|
||||
req, err := http.NewRequest("GET", taskModel.Command, nil)
|
||||
if err != nil {
|
||||
logger.Error("任务处理#创建HTTP请求错误-", err.Error())
|
||||
return
|
||||
|
@ -119,6 +119,8 @@ func (h *SSHCommandHandler) Run(taskModel models.TaskHost) (string, error) {
|
|||
Host: taskModel.Name,
|
||||
Port: taskModel.Port,
|
||||
ExecTimeout: taskModel.Timeout,
|
||||
AuthType: taskModel.AuthType,
|
||||
PrivateKey: taskModel.PrivateKey,
|
||||
}
|
||||
return ssh.Exec(sshConfig, taskModel.Command)
|
||||
}
|
||||
|
@ -132,7 +134,7 @@ func createTaskLog(taskModel models.TaskHost) (int64, error) {
|
|||
taskLogModel.Protocol = taskModel.Protocol
|
||||
taskLogModel.Command = taskModel.Command
|
||||
taskLogModel.Timeout = taskModel.Timeout
|
||||
taskLogModel.Hostname = taskModel.Name
|
||||
taskLogModel.Hostname = taskModel.Alias + "-" + taskModel.Name
|
||||
taskLogModel.StartTime = time.Now()
|
||||
taskLogModel.Status = models.Running
|
||||
insertId, err := taskLogModel.Create()
|
||||
|
|
|
@ -10,46 +10,72 @@
|
|||
<h3 class="ui dividing header">
|
||||
<i class="large add icon"></i>
|
||||
<div class="content">
|
||||
添加主机
|
||||
{{{.Title}}}
|
||||
</div>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<form class="ui form fluid vertical segment">
|
||||
<div class="two fields">
|
||||
<input type="hidden" name="id" value="{{{.Host.Id}}}">
|
||||
<div class="four fields">
|
||||
<div class="field">
|
||||
<label>主机名 (域名或IP)</label>
|
||||
<div class="ui small left icon input">
|
||||
<input type="text" placeholder="127.0.0.1" name="name">
|
||||
<input type="text" name="name" value="{{{.Host.Name}}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>主机别名 (方便记忆和引用)</label>
|
||||
<div class="ui small left icon input">
|
||||
<input type="text" placeholder="db" name="alias">
|
||||
<input type="text" name="alias" value="{{{.Host.Alias}}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="two fields">
|
||||
<div class="four fields">
|
||||
<div class="field">
|
||||
<label>SSH用户名</label>
|
||||
<div class="ui small left icon input">
|
||||
<input type="text" placeholder="root" name="username">
|
||||
<input type="text" name="username" value="{{{.Host.Username}}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>SSH密码</label>
|
||||
<div class="ui small left icon input">
|
||||
<input type="text" placeholder="123456" name="password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="two fields">
|
||||
<div class="field">
|
||||
<label>SSH端口</label>
|
||||
<div class="ui small left icon input">
|
||||
<input type="text" placeholder="22" name="port" value="22">
|
||||
<input type="text" name="port" value="{{{.Host.Port}}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="four fields">
|
||||
<div class="field">
|
||||
<label>认证方式</label>
|
||||
<div class="ui dropdown selection">
|
||||
{{{ if .Host }}}
|
||||
<input type="hidden" name="auth_type" value="{{{if eq .Host.AuthType 1 }}}1{{{else}}}2{{{end}}}">
|
||||
{{{else}}}
|
||||
<input type="hidden" name="auth_type" value="2">
|
||||
{{{end}}}
|
||||
<div class="default text">公钥</div>
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="menu">
|
||||
<div class="item" data-value="2">公钥</div>
|
||||
<div class="item" data-value="1">密码</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="two fields">
|
||||
<div class="field">
|
||||
<label>私钥 (~/.ssh/id_rsa)</label>
|
||||
<div class="ui small left icon input">
|
||||
<textarea rows="7" name="private_key">{{{.Host.PrivateKey}}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="four fields">
|
||||
<div class="field">
|
||||
<label>SSH密码</label>
|
||||
<div class="ui small left icon input">
|
||||
<input type="text" placeholder="" name="password" value="{{{.Host.Password}}}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -57,7 +83,7 @@
|
|||
<div class="field">
|
||||
<label>备注</label>
|
||||
<div class="ui small left icon input">
|
||||
<textarea rows="5" name="remark" placeholder="数据库服务器"></textarea>
|
||||
<textarea rows="7" name="remark" >{{{.Host.Remark}}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
<th>主机名</th>
|
||||
<th>别名</th>
|
||||
<th>用户名</th>
|
||||
<th>密码</th>
|
||||
<th>端口</th>
|
||||
<th>任务数量</th>
|
||||
<th>备注</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
|
@ -32,14 +32,13 @@
|
|||
<td>{{{.Name}}}</td>
|
||||
<td>{{{.Alias}}}</td>
|
||||
<td>{{{.Username}}}</td>
|
||||
<td>{{{.Password}}}</td>
|
||||
<td>{{{.Port}}}</td>
|
||||
<td></td>
|
||||
<td>{{{.Remark}}}</td>
|
||||
<td>
|
||||
<button class="ui pink button" >编辑</button>
|
||||
<td id="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 pink button" >连接测试</button>
|
||||
<button class="ui pink button" >查看任务</button>
|
||||
<button class="ui blue button" @click="ping({{{.Id}}})">连接测试</button>
|
||||
</td>
|
||||
</tr>
|
||||
{{{end}}}
|
||||
|
@ -48,4 +47,23 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var Vue = new Vue({
|
||||
el: '#operation',
|
||||
methods: {
|
||||
ping: function(id) {
|
||||
swal({
|
||||
title: '',
|
||||
text: "连接中.......",
|
||||
type: 'info',
|
||||
closeOnConfirm: true
|
||||
});
|
||||
util.get("/host/ping/" + id, function(code, message) {
|
||||
swal('操作成功', '连接成功', 'success');
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
{{{ template "common/footer" . }}}
|
|
@ -46,7 +46,7 @@
|
|||
<button class="ui blue button" onclick="changeStatus({{{.Id}}},{{{.Status}}})">激活 </button>
|
||||
{{{end}}}
|
||||
<button class="ui positive button" onclick="util.removeConfirm('/task/remove/{{{.Id}}}')">删除</button>
|
||||
<button class="ui pink button">查看日志</button>
|
||||
<button class="ui instagram button">查看日志</button>
|
||||
</td>
|
||||
</tr>
|
||||
{{{end}}}
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
{{{if eq $.Task.HostId .Id}}} checked {{{end}}}
|
||||
>
|
||||
{{{else}}}
|
||||
<input type="radio" name="host_id" tabindex="0" class="hidden">
|
||||
<input type="radio" name="host_id" tabindex="0" class="hidden" value="{{{.Id}}}">
|
||||
{{{end}}}
|
||||
<label>{{{.Alias}}}-{{{.Name}}}</label>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue