mirror of
https://gitee.com/dromara/mayfly-go
synced 2025-11-02 15:30:25 +08:00
增加webssh及数据库查询
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,3 +10,5 @@
|
|||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
|
*/node_modules/
|
||||||
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
0
.idea/.name
generated
0
.idea/.name
generated
10
.idea/mayfly-go.iml
generated
10
.idea/mayfly-go.iml
generated
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="WEB_MODULE" version="4">
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<content url="file://$MODULE_DIR$/../mayfly-go">
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/../mayfly-go/mayfly-go-front" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
6
.idea/misc.xml
generated
6
.idea/misc.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="JavaScriptSettings">
|
|
||||||
<option name="languageLevel" value="ES6" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/mayfly-job.iml" filepath="$PROJECT_DIR$/.idea/mayfly-job.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
17
.vscode/launch.json
vendored
Normal file
17
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
// 使用 IntelliSense 了解相关属性。
|
||||||
|
// 悬停以查看现有属性的描述。
|
||||||
|
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "mayfly-go",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${fileDirname}/../main.go",
|
||||||
|
"env": {},
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,25 +2,30 @@ package base
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/astaxie/beego"
|
"fmt"
|
||||||
"github.com/astaxie/beego/logs"
|
"mayfly-go/base/ctx"
|
||||||
"github.com/astaxie/beego/validation"
|
"mayfly-go/base/model"
|
||||||
|
"mayfly-go/base/token"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/core/logs"
|
||||||
|
"github.com/beego/beego/v2/core/validation"
|
||||||
|
"github.com/beego/beego/v2/server/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Controller struct {
|
type Controller struct {
|
||||||
beego.Controller
|
web.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取数据函数
|
// 获取数据函数
|
||||||
type getDataFunc func(loginAccount *LoginAccount) interface{}
|
type getDataFunc func(loginAccount *ctx.LoginAccount) interface{}
|
||||||
|
|
||||||
// 操作函数,无返回数据
|
// 操作函数,无返回数据
|
||||||
type operationFunc func(loginAccount *LoginAccount)
|
type operationFunc func(loginAccount *ctx.LoginAccount)
|
||||||
|
|
||||||
// 将请求体的json赋值给指定的结构体
|
// 将请求体的json赋值给指定的结构体
|
||||||
func (c *Controller) UnmarshalBody(data interface{}) {
|
func (c *Controller) UnmarshalBody(data interface{}) {
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, data)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, data)
|
||||||
BizErrIsNil(err, "request body解析错误")
|
model.BizErrIsNil(err, "request body解析错误")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 校验表单数据
|
// 校验表单数据
|
||||||
@@ -32,7 +37,7 @@ func (c *Controller) validForm(form interface{}) {
|
|||||||
}
|
}
|
||||||
if !b {
|
if !b {
|
||||||
e := valid.Errors[0]
|
e := valid.Errors[0]
|
||||||
panic(NewBizErr(e.Field + " " + e.Message))
|
panic(model.NewBizErr(e.Field + " " + e.Message))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,13 +56,32 @@ func (c *Controller) ReturnData(checkToken bool, getData getDataFunc) {
|
|||||||
c.parseErr(err)
|
c.parseErr(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var loginAccount *LoginAccount
|
var loginAccount *ctx.LoginAccount
|
||||||
if checkToken {
|
if checkToken {
|
||||||
loginAccount = c.CheckToken()
|
loginAccount = c.CheckToken()
|
||||||
}
|
}
|
||||||
c.Success(getData(loginAccount))
|
c.Success(getData(loginAccount))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 返回数据
|
||||||
|
// @param checkToken 是否校验token
|
||||||
|
// @param getData 获取数据的回调函数
|
||||||
|
func (c *Controller) ReturnDataWithPermisison(permission ctx.Permission, getData getDataFunc) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
c.parseErr(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
var logMsg string
|
||||||
|
var loginAccount *ctx.LoginAccount
|
||||||
|
if permission.CheckToken {
|
||||||
|
loginAccount = c.CheckToken()
|
||||||
|
logMsg = fmt.Sprintf("[uid=%d, uname=%s]\n", loginAccount.Id, loginAccount.Username)
|
||||||
|
}
|
||||||
|
c.Success(getData(loginAccount))
|
||||||
|
logs.Info(logMsg)
|
||||||
|
}
|
||||||
|
|
||||||
// 无返回数据的操作,如新增修改等无需返回数据的操作
|
// 无返回数据的操作,如新增修改等无需返回数据的操作
|
||||||
// @param checkToken 是否校验token
|
// @param checkToken 是否校验token
|
||||||
func (c *Controller) Operation(checkToken bool, operation operationFunc) {
|
func (c *Controller) Operation(checkToken bool, operation operationFunc) {
|
||||||
@@ -66,7 +90,7 @@ func (c *Controller) Operation(checkToken bool, operation operationFunc) {
|
|||||||
c.parseErr(err)
|
c.parseErr(err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var loginAccount *LoginAccount
|
var loginAccount *ctx.LoginAccount
|
||||||
if checkToken {
|
if checkToken {
|
||||||
loginAccount = c.CheckToken()
|
loginAccount = c.CheckToken()
|
||||||
}
|
}
|
||||||
@@ -75,54 +99,54 @@ func (c *Controller) Operation(checkToken bool, operation operationFunc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 校验token,并返回登录者账号信息
|
// 校验token,并返回登录者账号信息
|
||||||
func (c *Controller) CheckToken() *LoginAccount {
|
func (c *Controller) CheckToken() *ctx.LoginAccount {
|
||||||
tokenStr := c.Ctx.Input.Header("Authorization")
|
tokenStr := c.Ctx.Input.Header("Authorization")
|
||||||
loginAccount, err := ParseToken(tokenStr)
|
loginAccount, err := token.ParseToken(tokenStr)
|
||||||
if err != nil || loginAccount == nil {
|
if err != nil || loginAccount == nil {
|
||||||
panic(NewBizErrCode(TokenErrorCode, TokenErrorMsg))
|
panic(model.NewBizErrCode(model.TokenErrorCode, model.TokenErrorMsg))
|
||||||
}
|
}
|
||||||
return loginAccount
|
return loginAccount
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取分页参数
|
// 获取分页参数
|
||||||
func (c *Controller) GetPageParam() *PageParam {
|
func (c *Controller) GetPageParam() *model.PageParam {
|
||||||
pn, err := c.GetInt("pageNum", 1)
|
pn, err := c.GetInt("pageNum", 1)
|
||||||
BizErrIsNil(err, "pageNum参数错误")
|
model.BizErrIsNil(err, "pageNum参数错误")
|
||||||
ps, serr := c.GetInt("pageSize", 10)
|
ps, serr := c.GetInt("pageSize", 10)
|
||||||
BizErrIsNil(serr, "pageSize参数错误")
|
model.BizErrIsNil(serr, "pageSize参数错误")
|
||||||
return &PageParam{PageNum: pn, PageSize: ps}
|
return &model.PageParam{PageNum: pn, PageSize: ps}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 统一返回Result json对象
|
// 统一返回Result json对象
|
||||||
func (c *Controller) Result(result *Result) {
|
func (c *Controller) Result(result *model.Result) {
|
||||||
c.Data["json"] = result
|
c.Data["json"] = result
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回成功结果
|
// 返回成功结果
|
||||||
func (c *Controller) Success(data interface{}) {
|
func (c *Controller) Success(data interface{}) {
|
||||||
c.Result(Success(data))
|
c.Result(model.Success(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回成功结果
|
// 返回成功结果
|
||||||
func (c *Controller) SuccessNoData() {
|
func (c *Controller) SuccessNoData() {
|
||||||
c.Result(SuccessNoData())
|
c.Result(model.SuccessNoData())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回业务错误
|
// 返回业务错误
|
||||||
func (c *Controller) BizError(bizError BizError) {
|
func (c *Controller) BizError(bizError model.BizError) {
|
||||||
c.Result(Error(bizError.Code(), bizError.Error()))
|
c.Result(model.Error(bizError.Code(), bizError.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回服务器错误结果
|
// 返回服务器错误结果
|
||||||
func (c *Controller) ServerError() {
|
func (c *Controller) ServerError() {
|
||||||
c.Result(ServerError())
|
c.Result(model.ServerError())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析error,并对不同error返回不同result
|
// 解析error,并对不同error返回不同result
|
||||||
func (c *Controller) parseErr(err interface{}) {
|
func (c *Controller) parseErr(err interface{}) {
|
||||||
switch t := err.(type) {
|
switch t := err.(type) {
|
||||||
case BizError:
|
case model.BizError:
|
||||||
c.BizError(t)
|
c.BizError(t)
|
||||||
break
|
break
|
||||||
case error:
|
case error:
|
||||||
|
|||||||
12
base/ctx/login_account.go
Normal file
12
base/ctx/login_account.go
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package ctx
|
||||||
|
|
||||||
|
type LoginAccount struct {
|
||||||
|
Id uint64
|
||||||
|
Username string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Permission struct {
|
||||||
|
CheckToken bool // 是否检查token
|
||||||
|
Code string // 权限码
|
||||||
|
Name string // 描述
|
||||||
|
}
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
package base
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BizErrIsNil(err error, msg string) {
|
func BizErrIsNil(err error, msg string, params ...interface{}) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(NewBizErr(msg))
|
panic(NewBizErr(fmt.Sprintf(msg, params...)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,15 +17,15 @@ func ErrIsNil(err error, msg string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsTrue(exp bool, msg string) {
|
func IsTrue(exp bool, msg string, params ...interface{}) {
|
||||||
if !exp {
|
if !exp {
|
||||||
panic(NewBizErr(msg))
|
panic(NewBizErr(fmt.Sprintf(msg, params...)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotEmpty(str string, msg string) {
|
func NotEmpty(str string, msg string, params ...interface{}) {
|
||||||
if str == "" {
|
if str == "" {
|
||||||
panic(NewBizErr(msg))
|
panic(NewBizErr(fmt.Sprintf(msg, params...)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package base
|
package model
|
||||||
|
|
||||||
// 业务错误
|
// 业务错误
|
||||||
type BizError struct {
|
type BizError struct {
|
||||||
@@ -1,24 +1,48 @@
|
|||||||
package base
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/astaxie/beego/orm"
|
"mayfly-go/base/ctx"
|
||||||
"github.com/siddontang/go/log"
|
|
||||||
"mayfly-go/base/utils"
|
"mayfly-go/base/utils"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
|
"github.com/siddontang/go/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
Id uint64 `orm:"column(id);auto" json:"id"`
|
Id uint64 `orm:"column(id);auto" json:"id"`
|
||||||
CreateTime time.Time `orm:"column(create_time);type(datetime);null" json:"createTime"`
|
CreateTime *time.Time `orm:"column(create_time);type(datetime);null" json:"createTime"`
|
||||||
CreatorId uint64 `orm:"column(creator_id)" json:"creatorId"`
|
CreatorId uint64 `orm:"column(creator_id)" json:"creatorId"`
|
||||||
Creator string `orm:"column(creator)" json:"creator"`
|
Creator string `orm:"column(creator)" json:"creator"`
|
||||||
UpdateTime time.Time `orm:"column(update_time);type(datetime);null" json:"updateTime"`
|
UpdateTime *time.Time `orm:"column(update_time);type(datetime);null" json:"updateTime"`
|
||||||
ModifierId uint64 `orm:"column(modifier_id)" json:"modifierId"`
|
ModifierId uint64 `orm:"column(modifier_id)" json:"modifierId"`
|
||||||
Modifier string `orm:"column(modifier)" json:"modifier"`
|
Modifier string `orm:"column(modifier)" json:"modifier"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置基础信息. 如创建时间,修改时间,创建者,修改者信息
|
||||||
|
func (m *Model) SetBaseInfo(account *ctx.LoginAccount) {
|
||||||
|
nowTime := time.Now()
|
||||||
|
isCreate := m.Id == 0
|
||||||
|
if isCreate {
|
||||||
|
m.CreateTime = &nowTime
|
||||||
|
}
|
||||||
|
m.UpdateTime = &nowTime
|
||||||
|
|
||||||
|
if account == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
id := account.Id
|
||||||
|
name := account.Username
|
||||||
|
if isCreate {
|
||||||
|
m.CreatorId = id
|
||||||
|
m.Creator = name
|
||||||
|
}
|
||||||
|
m.Modifier = name
|
||||||
|
m.ModifierId = id
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取orm querySeter
|
// 获取orm querySeter
|
||||||
@@ -26,6 +50,74 @@ func QuerySetter(table interface{}) orm.QuerySeter {
|
|||||||
return getOrm().QueryTable(table)
|
return getOrm().QueryTable(table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据id获取实体对象。model需为指针类型(需要将查询出来的值赋值给model)
|
||||||
|
//
|
||||||
|
// 若error不为nil则为不存在该记录
|
||||||
|
func GetById(model interface{}, id uint64, cols ...string) error {
|
||||||
|
return QuerySetter(model).Filter("Id", id).One(model, cols...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据id更新model,更新字段为model中不为空的值,即int类型不为0,ptr类型不为nil这类字段值
|
||||||
|
func UpdateById(model interface{}) (int64, error) {
|
||||||
|
var id uint64
|
||||||
|
params := orm.Params{}
|
||||||
|
err := utils.DoWithFields(model, func(ft reflect.StructField, fv reflect.Value) error {
|
||||||
|
if utils.IsBlank(fv) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if ft.Name == "Id" {
|
||||||
|
if id = fv.Uint(); id == 0 {
|
||||||
|
return errors.New("根据id更新model时Id不能为0")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
params[ft.Name] = fv.Interface()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return QuerySetter(model).Filter("Id", id).Update(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据id删除model
|
||||||
|
func DeleteById(model interface{}, id uint64) (int64, error) {
|
||||||
|
return QuerySetter(model).Filter("Id", id).Delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 插入model
|
||||||
|
func Insert(model interface{}) (int64, error) {
|
||||||
|
return getOrm().Insert(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取满足model中不为空的字段值条件的所有数据.
|
||||||
|
//
|
||||||
|
// @param list为数组类型 如 var users []*User
|
||||||
|
func ListByCondition(model interface{}, list interface{}) {
|
||||||
|
qs := QuerySetter(model)
|
||||||
|
utils.DoWithFields(model, func(ft reflect.StructField, fv reflect.Value) error {
|
||||||
|
if !utils.IsBlank(fv) {
|
||||||
|
qs = qs.Filter(ft.Name, fv.Interface())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
qs.All(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取满足model中不为空的字段值条件的单个对象。model需为指针类型(需要将查询出来的值赋值给model)
|
||||||
|
//
|
||||||
|
// 若 error不为nil,则为不存在该记录
|
||||||
|
func GetByCondition(model interface{}, cols ...string) error {
|
||||||
|
qs := QuerySetter(model)
|
||||||
|
utils.DoWithFields(model, func(ft reflect.StructField, fv reflect.Value) error {
|
||||||
|
if !utils.IsBlank(fv) {
|
||||||
|
qs = qs.Filter(ft.Name, fv.Interface())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return qs.One(model, cols...)
|
||||||
|
}
|
||||||
|
|
||||||
// 获取分页结果
|
// 获取分页结果
|
||||||
func GetPage(seter orm.QuerySeter, pageParam *PageParam, models interface{}, toModels interface{}) PageResult {
|
func GetPage(seter orm.QuerySeter, pageParam *PageParam, models interface{}, toModels interface{}) PageResult {
|
||||||
count, _ := seter.Count()
|
count, _ := seter.Count()
|
||||||
@@ -80,6 +172,7 @@ func GetListBySql(sql string, params ...interface{}) *[]orm.Params {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有列表数据
|
// 获取所有列表数据
|
||||||
|
// model为数组类型 如 var users []*User
|
||||||
func GetList(seter orm.QuerySeter, model interface{}, toModel interface{}) {
|
func GetList(seter orm.QuerySeter, model interface{}, toModel interface{}) {
|
||||||
_, _ = seter.All(model, getFieldNames(toModel)...)
|
_, _ = seter.All(model, getFieldNames(toModel)...)
|
||||||
err := utils.Copy(toModel, model)
|
err := utils.Copy(toModel, model)
|
||||||
@@ -110,14 +203,6 @@ func GetBy(model interface{}, fs ...string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Insert(model interface{}) error {
|
|
||||||
_, err := getOrm().Insert(model)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("数据插入失败")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Update(model interface{}, fs ...string) error {
|
func Update(model interface{}, fs ...string) error {
|
||||||
_, err := getOrm().Update(model, fs...)
|
_, err := getOrm().Update(model, fs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
package base
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/astaxie/beego/orm"
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
"mayfly-go/base/utils"
|
"mayfly-go/base/utils"
|
||||||
"mayfly-go/controllers/vo"
|
"mayfly-go/controllers/vo"
|
||||||
"mayfly-go/models"
|
"mayfly-go/models"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AccountDetailVO struct {
|
type AccountDetailVO struct {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package base
|
package model
|
||||||
|
|
||||||
// 分页参数
|
// 分页参数
|
||||||
type PageParam struct {
|
type PageParam struct {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package base
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
package base
|
package token
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/dgrijalva/jwt-go"
|
"mayfly-go/base/ctx"
|
||||||
|
"mayfly-go/base/model"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/dgrijalva/jwt-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -11,11 +14,6 @@ const (
|
|||||||
ExpTime = time.Hour * 24 * 7
|
ExpTime = time.Hour * 24 * 7
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoginAccount struct {
|
|
||||||
Id uint64
|
|
||||||
Username string
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建用户token
|
// 创建用户token
|
||||||
func CreateToken(userId uint64, username string) string {
|
func CreateToken(userId uint64, username string) string {
|
||||||
// 带权限创建令牌
|
// 带权限创建令牌
|
||||||
@@ -28,12 +26,12 @@ func CreateToken(userId uint64, username string) string {
|
|||||||
|
|
||||||
// 使用自定义字符串加密 and get the complete encoded token as a string
|
// 使用自定义字符串加密 and get the complete encoded token as a string
|
||||||
tokenString, err := token.SignedString([]byte(JwtKey))
|
tokenString, err := token.SignedString([]byte(JwtKey))
|
||||||
BizErrIsNil(err, "token创建失败")
|
model.BizErrIsNil(err, "token创建失败")
|
||||||
return tokenString
|
return tokenString
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析token,并返回登录者账号信息
|
// 解析token,并返回登录者账号信息
|
||||||
func ParseToken(tokenStr string) (*LoginAccount, error) {
|
func ParseToken(tokenStr string) (*ctx.LoginAccount, error) {
|
||||||
if tokenStr == "" {
|
if tokenStr == "" {
|
||||||
return nil, errors.New("token error")
|
return nil, errors.New("token error")
|
||||||
}
|
}
|
||||||
@@ -45,5 +43,5 @@ func ParseToken(tokenStr string) (*LoginAccount, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
i := token.Claims.(jwt.MapClaims)
|
i := token.Claims.(jwt.MapClaims)
|
||||||
return &LoginAccount{Id: uint64(i["id"].(float64)), Username: i["username"].(string)}, nil
|
return &ctx.LoginAccount{Id: uint64(i["id"].(float64)), Username: i["username"].(string)}, nil
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,26 @@ func SubString(str string, begin, end int) (substr string) {
|
|||||||
return string(rs[begin:end])
|
return string(rs[begin:end])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Camel2Underline(name string) string {
|
||||||
|
if name == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
temp := strings.Split(name, "_")
|
||||||
|
var s string
|
||||||
|
for _, v := range temp {
|
||||||
|
vv := []rune(v)
|
||||||
|
if len(vv) > 0 {
|
||||||
|
if bool(vv[0] >= 'a' && vv[0] <= 'z') { //首字母大写
|
||||||
|
vv[0] -= 32
|
||||||
|
}
|
||||||
|
s += string(vv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
func UnicodeIndex(str, substr string) int {
|
func UnicodeIndex(str, substr string) int {
|
||||||
// 子串在字符串的字节位置
|
// 子串在字符串的字节位置
|
||||||
result := strings.Index(str, substr)
|
result := strings.Index(str, substr)
|
||||||
|
|||||||
@@ -132,6 +132,31 @@ func Copy(toValue interface{}, fromValue interface{}) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 对结构体的每个字段以及字段值执行doWith回调函数, 包括匿名属性的字段
|
||||||
|
func DoWithFields(str interface{}, doWith func(fType reflect.StructField, fValue reflect.Value) error) error {
|
||||||
|
t := IndirectType(reflect.TypeOf(str))
|
||||||
|
if t.Kind() != reflect.Struct {
|
||||||
|
return errors.New("非结构体")
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldNum := t.NumField()
|
||||||
|
v := Indirect(reflect.ValueOf(str))
|
||||||
|
for i := 0; i < fieldNum; i++ {
|
||||||
|
ft := t.Field(i)
|
||||||
|
fv := v.Field(i)
|
||||||
|
// 如果是匿名属性,则递归调用该方法
|
||||||
|
if ft.Anonymous {
|
||||||
|
DoWithFields(fv.Interface(), doWith)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
err := doWith(ft, fv)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func deepFields(reflectType reflect.Type) []reflect.StructField {
|
func deepFields(reflectType reflect.Type) []reflect.StructField {
|
||||||
var fields []reflect.StructField
|
var fields []reflect.StructField
|
||||||
|
|
||||||
@@ -610,7 +635,7 @@ func Case2Camel(name string) string {
|
|||||||
return strings.Replace(name, " ", "", -1)
|
return strings.Replace(name, " ", "", -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isBlank(value reflect.Value) bool {
|
func IsBlank(value reflect.Value) bool {
|
||||||
switch value.Kind() {
|
switch value.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return value.Len() == 0
|
return value.Len() == 0
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/mapstructure"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -144,9 +143,9 @@ func TestMap2Struct(t *testing.T) {
|
|||||||
//
|
//
|
||||||
//fmt.Println(name, b)
|
//fmt.Println(name, b)
|
||||||
//将 map 转换为指定的结构体
|
//将 map 转换为指定的结构体
|
||||||
if err := mapstructure.Decode(mapInstance, &s); err != nil {
|
// if err := decode(mapInstance, &s); err != nil {
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
fmt.Printf("map2struct后得到的 struct 内容为:%v", s)
|
fmt.Printf("map2struct后得到的 struct 内容为:%v", s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"mayfly-go/base"
|
"mayfly-go/base"
|
||||||
|
"mayfly-go/base/ctx"
|
||||||
|
"mayfly-go/base/model"
|
||||||
|
"mayfly-go/base/token"
|
||||||
"mayfly-go/controllers/form"
|
"mayfly-go/controllers/form"
|
||||||
"mayfly-go/models"
|
"mayfly-go/models"
|
||||||
)
|
)
|
||||||
@@ -17,14 +20,14 @@ type AccountController struct {
|
|||||||
|
|
||||||
// @router /accounts/login [post]
|
// @router /accounts/login [post]
|
||||||
func (c *AccountController) Login() {
|
func (c *AccountController) Login() {
|
||||||
c.ReturnData(false, func(la *base.LoginAccount) interface{} {
|
c.ReturnData(false, func(la *ctx.LoginAccount) interface{} {
|
||||||
loginForm := &form.LoginForm{}
|
loginForm := &form.LoginForm{}
|
||||||
c.UnmarshalBodyAndValid(loginForm)
|
c.UnmarshalBodyAndValid(loginForm)
|
||||||
|
|
||||||
a := &models.Account{Username: loginForm.Username, Password: loginForm.Password}
|
a := &models.Account{Username: loginForm.Username, Password: loginForm.Password}
|
||||||
base.BizErrIsNil(base.GetBy(a, "Username", "Password"), "用户名或密码错误")
|
model.BizErrIsNil(model.GetBy(a, "Username", "Password"), "用户名或密码错误")
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"token": base.CreateToken(a.Id, a.Username),
|
"token": token.CreateToken(a.Id, a.Username),
|
||||||
"username": a.Username,
|
"username": a.Username,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -32,7 +35,7 @@ func (c *AccountController) Login() {
|
|||||||
|
|
||||||
// @router /accounts [get]
|
// @router /accounts [get]
|
||||||
func (c *AccountController) Accounts() {
|
func (c *AccountController) Accounts() {
|
||||||
c.ReturnData(true, func(account *base.LoginAccount) interface{} {
|
c.ReturnData(true, func(account *ctx.LoginAccount) interface{} {
|
||||||
//s := c.GetString("username")
|
//s := c.GetString("username")
|
||||||
//query := models.QuerySetter(new(models.Account)).OrderBy("-Id").RelatedSel()
|
//query := models.QuerySetter(new(models.Account)).OrderBy("-Id").RelatedSel()
|
||||||
//return models.GetPage(query, c.GetPageParam(), new([]models.Account), new([]vo.AccountVO))
|
//return models.GetPage(query, c.GetPageParam(), new([]models.Account), new([]vo.AccountVO))
|
||||||
|
|||||||
140
controllers/db.go
Normal file
140
controllers/db.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"mayfly-go/base"
|
||||||
|
"mayfly-go/base/ctx"
|
||||||
|
"mayfly-go/base/model"
|
||||||
|
"mayfly-go/controllers/form"
|
||||||
|
"mayfly-go/controllers/vo"
|
||||||
|
"mayfly-go/db"
|
||||||
|
"mayfly-go/models"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DbController struct {
|
||||||
|
base.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
// @router /api/dbs [get]
|
||||||
|
func (c *DbController) Dbs() {
|
||||||
|
c.ReturnData(false, func(account *ctx.LoginAccount) interface{} {
|
||||||
|
m := new([]models.Db)
|
||||||
|
querySetter := model.QuerySetter(new(models.Db))
|
||||||
|
return model.GetPage(querySetter, c.GetPageParam(), m, new([]vo.SelectDataDbVO))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @router /api/db/:dbId/select [get]
|
||||||
|
func (c *DbController) SelectData() {
|
||||||
|
c.ReturnData(false, func(account *ctx.LoginAccount) interface{} {
|
||||||
|
selectSql := c.GetString("selectSql")
|
||||||
|
model.NotEmpty(selectSql, "selectSql不能为空")
|
||||||
|
res, err := db.GetDbInstance(c.GetDbId()).SelectData(selectSql)
|
||||||
|
if err != nil {
|
||||||
|
panic(model.NewBizErr(fmt.Sprintf("查询失败: %s", err.Error())))
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @router /api/db/:dbId/exec-sql [post]
|
||||||
|
func (c *DbController) ExecSql() {
|
||||||
|
c.ReturnData(false, func(account *ctx.LoginAccount) interface{} {
|
||||||
|
selectSql := c.GetString("sql")
|
||||||
|
model.NotEmpty(selectSql, "sql不能为空")
|
||||||
|
num, err := db.GetDbInstance(c.GetDbId()).Exec(selectSql)
|
||||||
|
if err != nil {
|
||||||
|
panic(model.NewBizErr(fmt.Sprintf("执行失败: %s", err.Error())))
|
||||||
|
}
|
||||||
|
return num
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @router /api/db/:dbId/t-metadata [get]
|
||||||
|
func (c *DbController) TableMA() {
|
||||||
|
c.ReturnData(false, func(account *ctx.LoginAccount) interface{} {
|
||||||
|
return db.GetDbInstance(c.GetDbId()).GetTableMetedatas()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @router /api/db/:dbId/c-metadata [get]
|
||||||
|
func (c *DbController) ColumnMA() {
|
||||||
|
c.ReturnData(false, func(account *ctx.LoginAccount) interface{} {
|
||||||
|
tn := c.GetString("tableName")
|
||||||
|
model.NotEmpty(tn, "tableName不能为空")
|
||||||
|
return db.GetDbInstance(c.GetDbId()).GetColumnMetadatas(tn)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @router /api/db/:dbId/hint-tables [get]
|
||||||
|
// 数据表及字段前端提示接口
|
||||||
|
func (c *DbController) HintTables() {
|
||||||
|
c.ReturnData(false, func(account *ctx.LoginAccount) interface{} {
|
||||||
|
dbi := db.GetDbInstance(c.GetDbId())
|
||||||
|
tables := dbi.GetTableMetedatas()
|
||||||
|
res := make(map[string][]string)
|
||||||
|
for _, v := range tables {
|
||||||
|
tableName := v["tableName"]
|
||||||
|
columnMds := dbi.GetColumnMetadatas(tableName)
|
||||||
|
columnNames := make([]string, len(columnMds))
|
||||||
|
for i, v := range columnMds {
|
||||||
|
comment := v["columnComment"]
|
||||||
|
if comment != "" {
|
||||||
|
columnNames[i] = v["columnName"] + " [" + comment + "]"
|
||||||
|
} else {
|
||||||
|
columnNames[i] = v["columnName"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res[tableName] = columnNames
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @router /api/db/:dbId/sql [post]
|
||||||
|
func (c *DbController) SaveSql() {
|
||||||
|
c.Operation(true, func(account *ctx.LoginAccount) {
|
||||||
|
dbSqlForm := &form.DbSqlSaveForm{}
|
||||||
|
c.UnmarshalBodyAndValid(dbSqlForm)
|
||||||
|
|
||||||
|
dbId := c.GetDbId()
|
||||||
|
// 判断dbId是否存在
|
||||||
|
err := model.GetById(new(models.Db), dbId)
|
||||||
|
model.BizErrIsNil(err, "该数据库信息不存在")
|
||||||
|
|
||||||
|
// 获取用于是否有该dbsql的保存记录,有则更改,否则新增
|
||||||
|
dbSql := &models.DbSql{Type: dbSqlForm.Type, DbId: dbId}
|
||||||
|
dbSql.CreatorId = account.Id
|
||||||
|
e := model.GetByCondition(dbSql)
|
||||||
|
|
||||||
|
dbSql.SetBaseInfo(account)
|
||||||
|
// 更新sql信息
|
||||||
|
dbSql.Sql = dbSqlForm.Sql
|
||||||
|
if e == nil {
|
||||||
|
model.UpdateById(dbSql)
|
||||||
|
} else {
|
||||||
|
model.Insert(dbSql)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// @router /api/db/:dbId/sql [get]
|
||||||
|
func (c *DbController) GetSql() {
|
||||||
|
c.ReturnData(true, func(account *ctx.LoginAccount) interface{} {
|
||||||
|
// 获取用于是否有该dbsql的保存记录,有则更改,否则新增
|
||||||
|
dbSql := &models.DbSql{Type: 1, DbId: c.GetDbId()}
|
||||||
|
dbSql.CreatorId = account.Id
|
||||||
|
e := model.GetByCondition(dbSql)
|
||||||
|
if e != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return dbSql
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DbController) GetDbId() uint64 {
|
||||||
|
dbId, _ := strconv.Atoi(c.Ctx.Input.Param(":dbId"))
|
||||||
|
model.IsTrue(dbId > 0, "dbId错误")
|
||||||
|
return uint64(dbId)
|
||||||
|
}
|
||||||
@@ -10,3 +10,8 @@ type MachineRunForm struct {
|
|||||||
MachineId int64 `valid:"Required"`
|
MachineId int64 `valid:"Required"`
|
||||||
Cmd string `valid:"Required"`
|
Cmd string `valid:"Required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DbSqlSaveForm struct {
|
||||||
|
Sql string `valid:"Required"`
|
||||||
|
Type int `valid:"Required"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
"mayfly-go/base"
|
"mayfly-go/base"
|
||||||
|
"mayfly-go/base/ctx"
|
||||||
|
"mayfly-go/base/model"
|
||||||
"mayfly-go/machine"
|
"mayfly-go/machine"
|
||||||
"mayfly-go/models"
|
"mayfly-go/models"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MachineController struct {
|
type MachineController struct {
|
||||||
base.Controller
|
base.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
var upGrader = websocket.Upgrader{
|
var upgrader = websocket.Upgrader{
|
||||||
ReadBufferSize: 1024,
|
ReadBufferSize: 1024,
|
||||||
WriteBufferSize: 1024 * 1024 * 10,
|
WriteBufferSize: 1024 * 1024 * 10,
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
@@ -22,69 +25,81 @@ var upGrader = websocket.Upgrader{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *MachineController) Machines() {
|
func (c *MachineController) Machines() {
|
||||||
c.ReturnData(true, func(account *base.LoginAccount) interface{} {
|
c.ReturnData(true, func(account *ctx.LoginAccount) interface{} {
|
||||||
return models.GetMachineList(c.GetPageParam())
|
return models.GetMachineList(c.GetPageParam())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MachineController) Run() {
|
func (c *MachineController) Run() {
|
||||||
c.ReturnData(true, func(account *base.LoginAccount) interface{} {
|
c.ReturnData(true, func(account *ctx.LoginAccount) interface{} {
|
||||||
cmd := c.GetString("cmd")
|
cmd := c.GetString("cmd")
|
||||||
base.NotEmpty(cmd, "cmd不能为空")
|
model.NotEmpty(cmd, "cmd不能为空")
|
||||||
|
|
||||||
return machine.GetCli(c.GetMachineId()).Run(cmd)
|
res, err := c.getCli().Run(cmd)
|
||||||
|
model.BizErrIsNil(err, "执行命令失败")
|
||||||
|
return res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 系统基本信息
|
// 系统基本信息
|
||||||
func (c *MachineController) SysInfo() {
|
func (c *MachineController) SysInfo() {
|
||||||
c.ReturnData(true, func(account *base.LoginAccount) interface{} {
|
c.ReturnData(true, func(account *ctx.LoginAccount) interface{} {
|
||||||
return machine.GetSystemInfo(machine.GetCli(c.GetMachineId()))
|
res, err := c.getCli().GetSystemInfo()
|
||||||
|
model.BizErrIsNil(err, "获取系统基本信息失败")
|
||||||
|
return res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// top命令信息
|
// top命令信息
|
||||||
func (c *MachineController) Top() {
|
func (c *MachineController) Top() {
|
||||||
c.ReturnData(true, func(account *base.LoginAccount) interface{} {
|
c.ReturnData(true, func(account *ctx.LoginAccount) interface{} {
|
||||||
return machine.GetTop(machine.GetCli(c.GetMachineId()))
|
return c.getCli().GetTop()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MachineController) GetProcessByName() {
|
func (c *MachineController) GetProcessByName() {
|
||||||
c.ReturnData(true, func(account *base.LoginAccount) interface{} {
|
c.ReturnData(true, func(account *ctx.LoginAccount) interface{} {
|
||||||
name := c.GetString("name")
|
name := c.GetString("name")
|
||||||
base.NotEmpty(name, "name不能为空")
|
model.NotEmpty(name, "name不能为空")
|
||||||
return machine.GetProcessByName(machine.GetCli(c.GetMachineId()), name)
|
res, err := c.getCli().GetProcessByName(name)
|
||||||
|
model.BizErrIsNil(err, "获取失败")
|
||||||
|
return res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (c *MachineController) WsSSH() {
|
func (c *MachineController) WsSSH() {
|
||||||
// wsConn, err := upGrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
|
wsConn, err := upgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// panic(base.NewBizErr("获取requst responsewirte错误"))
|
panic(model.NewBizErr("获取requst responsewirte错误"))
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// cols, _ := c.GetInt("col", 80)
|
cols, _ := c.GetInt("cols", 80)
|
||||||
// rows, _ := c.GetInt("rows", 40)
|
rows, _ := c.GetInt("rows", 40)
|
||||||
//
|
|
||||||
// sws, err := machine.NewLogicSshWsSession(cols, rows, true, machine.GetCli(c.GetMachineId()), wsConn)
|
sws, err := machine.NewLogicSshWsSession(cols, rows, c.getCli(), wsConn)
|
||||||
// if sws == nil {
|
if sws == nil {
|
||||||
// panic(base.NewBizErr("连接失败"))
|
panic(model.NewBizErr("连接失败"))
|
||||||
// }
|
}
|
||||||
// //if wshandleError(wsConn, err) {
|
//if wshandleError(wsConn, err) {
|
||||||
// // return
|
// return
|
||||||
// //}
|
//}
|
||||||
// defer sws.Close()
|
defer sws.Close()
|
||||||
//
|
|
||||||
// quitChan := make(chan bool, 3)
|
quitChan := make(chan bool, 3)
|
||||||
// sws.Start(quitChan)
|
sws.Start(quitChan)
|
||||||
// go sws.Wait(quitChan)
|
go sws.Wait(quitChan)
|
||||||
//
|
|
||||||
// <-quitChan
|
<-quitChan
|
||||||
//}
|
}
|
||||||
|
|
||||||
func (c *MachineController) GetMachineId() uint64 {
|
func (c *MachineController) GetMachineId() uint64 {
|
||||||
machineId, _ := strconv.Atoi(c.Ctx.Input.Param(":machineId"))
|
machineId, _ := strconv.Atoi(c.Ctx.Input.Param(":machineId"))
|
||||||
base.IsTrue(machineId > 0, "machineId错误")
|
model.IsTrue(machineId > 0, "machineId错误")
|
||||||
return uint64(machineId)
|
return uint64(machineId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *MachineController) getCli() *machine.Cli {
|
||||||
|
cli, err := machine.GetCli(c.GetMachineId())
|
||||||
|
model.BizErrIsNil(err, "获取客户端错误")
|
||||||
|
return cli
|
||||||
|
}
|
||||||
|
|||||||
16
controllers/vo/db.go
Normal file
16
controllers/vo/db.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package vo
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type SelectDataDbVO struct {
|
||||||
|
//models.BaseModel
|
||||||
|
Id *int64 `json:"id"`
|
||||||
|
Name *string `json:"name"`
|
||||||
|
Host *string `json:"host"`
|
||||||
|
Port *int `json:"port"`
|
||||||
|
Type *string `json:"type"`
|
||||||
|
Database *string `json:"database"`
|
||||||
|
CreateTime *time.Time `json:"createTime"`
|
||||||
|
Creator *string `json:"creator"`
|
||||||
|
CreatorId *int64 `json:"creatorId"`
|
||||||
|
}
|
||||||
127
db/db.go
Normal file
127
db/db.go
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"mayfly-go/base/model"
|
||||||
|
"mayfly-go/models"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
)
|
||||||
|
|
||||||
|
var dbCache sync.Map
|
||||||
|
|
||||||
|
// db实例
|
||||||
|
type DbInstance struct {
|
||||||
|
Id uint64
|
||||||
|
Type string
|
||||||
|
db *sql.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行查询语句
|
||||||
|
func (d *DbInstance) SelectData(sql string) ([]map[string]string, error) {
|
||||||
|
sql = strings.Trim(sql, " ")
|
||||||
|
if !strings.HasPrefix(sql, "SELECT") && !strings.HasPrefix(sql, "select") {
|
||||||
|
return nil, errors.New("该sql非查询语句")
|
||||||
|
}
|
||||||
|
rows, err := d.db.Query(sql)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// rows对象一定要close掉,如果出错,不关掉则会很迅速的达到设置最大连接数,
|
||||||
|
// 后面的链接过来直接报错或拒绝,实际上也没有起效果
|
||||||
|
defer func() {
|
||||||
|
if rows != nil {
|
||||||
|
rows.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
cols, _ := rows.Columns()
|
||||||
|
// 这里表示一行填充数据
|
||||||
|
scans := make([]interface{}, len(cols))
|
||||||
|
// 这里表示一行所有列的值,用[]byte表示
|
||||||
|
vals := make([][]byte, len(cols))
|
||||||
|
// 这里scans引用vals,把数据填充到[]byte里
|
||||||
|
for k := range vals {
|
||||||
|
scans[k] = &vals[k]
|
||||||
|
}
|
||||||
|
result := make([]map[string]string, 0)
|
||||||
|
for rows.Next() {
|
||||||
|
// 不Scan也会导致等待,该链接实际处于未工作的状态,然后也会导致连接数迅速达到最大
|
||||||
|
err := rows.Scan(scans...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 每行数据
|
||||||
|
rowData := make(map[string]string)
|
||||||
|
// 把vals中的数据复制到row中
|
||||||
|
for k, v := range vals {
|
||||||
|
key := cols[k]
|
||||||
|
// 这里把[]byte数据转成string
|
||||||
|
rowData[key] = string(v)
|
||||||
|
}
|
||||||
|
//放入结果集
|
||||||
|
result = append(result, rowData)
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行 update, insert, delete,建表等sql
|
||||||
|
//
|
||||||
|
// 返回影响条数和错误
|
||||||
|
func (d *DbInstance) Exec(sql string) (int64, error) {
|
||||||
|
res, err := d.db.Exec(sql)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return res.RowsAffected()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭连接,并从缓存中移除
|
||||||
|
func (d *DbInstance) Close() {
|
||||||
|
d.db.Close()
|
||||||
|
dbCache.Delete(d.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取dataSourceName
|
||||||
|
func getDsn(d *models.Db) string {
|
||||||
|
if d.Type == "mysql" {
|
||||||
|
return fmt.Sprintf("%s:%s@%s(%s:%d)/%s", d.Username, d.Passowrd, d.Network, d.Host, d.Port, d.Database)
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDbInstance(id uint64) *DbInstance {
|
||||||
|
// Id不为0,则为需要缓存
|
||||||
|
needCache := id != 0
|
||||||
|
if needCache {
|
||||||
|
load, ok := dbCache.Load(id)
|
||||||
|
if ok {
|
||||||
|
return load.(*DbInstance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d := models.GetDbById(uint64(id))
|
||||||
|
model.NotNil(d, "数据库信息不存在")
|
||||||
|
DB, err := sql.Open(d.Type, getDsn(d))
|
||||||
|
model.ErrIsNil(err, fmt.Sprintf("Open %s failed, err:%v\n", d.Type, err))
|
||||||
|
perr := DB.Ping()
|
||||||
|
if perr != nil {
|
||||||
|
panic(model.NewBizErr(fmt.Sprintf("数据库连接失败: %s", perr.Error())))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最大连接周期,超过时间的连接就close
|
||||||
|
DB.SetConnMaxLifetime(100 * time.Second)
|
||||||
|
// 设置最大连接数
|
||||||
|
DB.SetMaxOpenConns(5)
|
||||||
|
// 设置闲置连接数
|
||||||
|
DB.SetMaxIdleConns(1)
|
||||||
|
|
||||||
|
dbi := &DbInstance{Id: id, Type: d.Type, db: DB}
|
||||||
|
if needCache {
|
||||||
|
dbCache.LoadOrStore(d.Id, dbi)
|
||||||
|
}
|
||||||
|
return dbi
|
||||||
|
}
|
||||||
33
db/metadata.go
Normal file
33
db/metadata.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// mysql 表信息元数据
|
||||||
|
MYSQL_TABLE_MA = `SELECT table_name tableName, engine, table_comment tableComment,
|
||||||
|
create_time createTime from information_schema.tables
|
||||||
|
WHERE table_schema = (SELECT database())`
|
||||||
|
|
||||||
|
// mysql 列信息元数据
|
||||||
|
MYSQL_COLOUMN_MA = `SELECT column_name columnName, column_type columnType,
|
||||||
|
column_comment columnComment, column_key columnKey, extra from information_schema.columns
|
||||||
|
WHERE table_name = '%s' AND table_schema = (SELECT database()) ORDER BY ordinal_position`
|
||||||
|
)
|
||||||
|
|
||||||
|
func (d *DbInstance) GetTableMetedatas() []map[string]string {
|
||||||
|
var sql string
|
||||||
|
if d.Type == "mysql" {
|
||||||
|
sql = MYSQL_TABLE_MA
|
||||||
|
}
|
||||||
|
res, _ := d.SelectData(sql)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DbInstance) GetColumnMetadatas(tableName string) []map[string]string {
|
||||||
|
var sql string
|
||||||
|
if d.Type == "mysql" {
|
||||||
|
sql = fmt.Sprintf(MYSQL_COLOUMN_MA, tableName)
|
||||||
|
}
|
||||||
|
res, _ := d.SelectData(sql)
|
||||||
|
return res
|
||||||
|
}
|
||||||
21
go.mod
21
go.mod
@@ -1,21 +1,18 @@
|
|||||||
module mayfly-go
|
module mayfly-go
|
||||||
|
|
||||||
go 1.13
|
go 1.15
|
||||||
|
|
||||||
require github.com/astaxie/beego v1.12.1
|
|
||||||
|
|
||||||
require github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
|
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/beego/beego/v2 v2.0.1
|
||||||
|
// jwt
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
github.com/gliderlabs/ssh v0.2.2
|
github.com/go-sql-driver/mysql v1.5.0
|
||||||
github.com/go-sql-driver/mysql v1.4.1
|
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/mitchellh/mapstructure v1.3.3
|
github.com/pkg/sftp v1.12.0
|
||||||
github.com/pkg/sftp v1.11.0
|
// 定时任务
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726
|
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0
|
||||||
github.com/smartystreets/goconvey v1.6.4
|
github.com/smartystreets/goconvey v1.6.4
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
// ssh
|
||||||
google.golang.org/appengine v1.6.6 // indirect
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||||
)
|
)
|
||||||
|
|||||||
262
go.sum
262
go.sum
@@ -1,95 +1,321 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/astaxie/beego v1.12.1 h1:dfpuoxpzLVgclveAXe4PyNKqkzgm5zF4tgF2B3kkM2I=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/astaxie/beego v1.12.1/go.mod h1:kPBWpSANNbSdIqOc8SUL9h+1oyBMZhROeYsXQDbidWQ=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||||
|
github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
|
||||||
|
github.com/astaxie/beego v1.12.3 h1:SAQkdD2ePye+v8Gn1r4X6IKZM1wd28EyUOVQ3PDSOOQ=
|
||||||
|
github.com/astaxie/beego v1.12.3/go.mod h1:p3qIm0Ryx7zeBHLljmd7omloyca1s4yu1a8kM1FkpIA=
|
||||||
|
github.com/beego/beego/v2 v2.0.1 h1:07a7Z0Ok5vbqyqh+q53sDPl9LdhKh0ZDy3gbyGrhFnE=
|
||||||
|
github.com/beego/beego/v2 v2.0.1/go.mod h1:8zyHi1FnWO1mZLwTn62aKRIZF/aIKvkCBB2JYs+eqQI=
|
||||||
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
|
github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ=
|
||||||
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
|
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
|
||||||
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
|
github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE=
|
||||||
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||||
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||||
github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
|
github.com/coreos/etcd v3.3.25+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
|
github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
|
||||||
|
github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
|
||||||
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||||
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||||
|
github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk=
|
||||||
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
|
||||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/godror/godror v0.9.0 h1:IQ+HRUl00B1V03jR4AduWKkKlP9RsTq9E4iEG3gcCZY=
|
||||||
|
github.com/godror/godror v0.9.0/go.mod h1:06LLZykQEXjuUYiVKBa7Ls+AvbUZ8sbtolIALCeL/jw=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||||
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
|
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||||
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
|
||||||
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||||
|
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
|
||||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
|
||||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.0 h1:7ks8ZkOP5/ujthUsT07rNv+nkLXCQWKNHuwzOAesEks=
|
||||||
|
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
|
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
|
||||||
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
|
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||||
|
github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
|
||||||
|
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.11.0 h1:4Zv0OGbpkg4yNuUtH0s8rvoYxRCNyT29NVUo6pgPmxI=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/sftp v1.11.0/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/sftp v1.12.0 h1:/f3b24xrDhkhddlaobPe2JgBqfdt+gC/NYl0QY9IOuI=
|
||||||
|
github.com/pkg/sftp v1.12.0/go.mod h1:fUqqXB5vEgVCZ131L+9say31RAri6aF6KDViawhxKK8=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
|
github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U=
|
||||||
|
github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||||
|
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
|
||||||
|
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8=
|
||||||
|
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
|
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo=
|
||||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
||||||
|
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 h1:DAYUYH5869yV94zvCES9F51oYtN5oGlwjxJJz7ZCnik=
|
||||||
|
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg=
|
||||||
|
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0 h1:QIF48X1cihydXibm+4wfAc0r/qyPyuFiPFRNphdMpEE=
|
||||||
|
github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
|
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
|
||||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
|
||||||
github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg=
|
github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s=
|
||||||
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||||
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||||
|
github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
|
||||||
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc=
|
||||||
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
|
||||||
|
go.etcd.io/etcd v3.3.25+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI=
|
||||||
|
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||||
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
|
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
|
||||||
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA=
|
||||||
|
golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||||
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
|
||||||
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
|
||||||
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||||
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag=
|
||||||
|
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
|
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
|||||||
1
lastupdate.tmp
Executable file
1
lastupdate.tmp
Executable file
@@ -0,0 +1 @@
|
|||||||
|
{"/Users/hml/Desktop/project/go/mayfly-go/controllers":1610075329396211594}
|
||||||
@@ -3,16 +3,17 @@ package machine
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pkg/sftp"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
"io"
|
"io"
|
||||||
"mayfly-go/base"
|
"mayfly-go/base/model"
|
||||||
"mayfly-go/models"
|
"mayfly-go/models"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/sftp"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 客户端信息
|
// 客户端信息
|
||||||
@@ -27,20 +28,20 @@ var clientCache sync.Map
|
|||||||
var mutex sync.Mutex
|
var mutex sync.Mutex
|
||||||
|
|
||||||
// 从缓存中获取客户端信息,不存在则查库,并新建
|
// 从缓存中获取客户端信息,不存在则查库,并新建
|
||||||
func GetCli(machineId uint64) *Cli {
|
func GetCli(machineId uint64) (*Cli, error) {
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
load, ok := clientCache.Load(machineId)
|
load, ok := clientCache.Load(machineId)
|
||||||
if ok {
|
if ok {
|
||||||
return load.(*Cli)
|
return load.(*Cli), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cli, err := newClient(models.GetMachineById(machineId))
|
cli, err := newClient(models.GetMachineById(machineId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(base.NewBizErr(err.Error()))
|
return nil, err
|
||||||
}
|
}
|
||||||
clientCache.LoadOrStore(machineId, cli)
|
clientCache.LoadOrStore(machineId, cli)
|
||||||
return cli
|
return cli, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//根据机器信息创建客户端对象
|
//根据机器信息创建客户端对象
|
||||||
@@ -53,7 +54,7 @@ func newClient(machine *models.Machine) (*Cli, error) {
|
|||||||
cli.machine = machine
|
cli.machine = machine
|
||||||
err := cli.connect()
|
err := cli.connect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("获取机器client失败:" + err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
return cli, nil
|
return cli, nil
|
||||||
}
|
}
|
||||||
@@ -114,12 +115,12 @@ func (c *Cli) Close() {
|
|||||||
func (c *Cli) GetSftpCli() *sftp.Client {
|
func (c *Cli) GetSftpCli() *sftp.Client {
|
||||||
if c.client == nil {
|
if c.client == nil {
|
||||||
if err := c.connect(); err != nil {
|
if err := c.connect(); err != nil {
|
||||||
panic(base.NewBizErr("连接ssh失败:" + err.Error()))
|
panic(model.NewBizErr("连接ssh失败:" + err.Error()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client, serr := sftp.NewClient(c.client, sftp.MaxPacket(1<<15))
|
client, serr := sftp.NewClient(c.client, sftp.MaxPacket(1<<15))
|
||||||
if serr != nil {
|
if serr != nil {
|
||||||
panic(base.NewBizErr("获取sftp client失败:" + serr.Error()))
|
panic(model.NewBizErr("获取sftp client失败:" + serr.Error()))
|
||||||
}
|
}
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
@@ -136,17 +137,19 @@ func (c *Cli) GetSession() (*ssh.Session, error) {
|
|||||||
|
|
||||||
//执行shell
|
//执行shell
|
||||||
//@param shell shell脚本命令
|
//@param shell shell脚本命令
|
||||||
func (c *Cli) Run(shell string) string {
|
func (c *Cli) Run(shell string) (*string, error) {
|
||||||
session, err := c.GetSession()
|
session, err := c.GetSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(base.NewBizErr("获取ssh session失败:" + err.Error()))
|
c.Close()
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
buf, rerr := session.CombinedOutput(shell)
|
buf, rerr := session.CombinedOutput(shell)
|
||||||
if rerr != nil {
|
if rerr != nil {
|
||||||
panic(base.NewBizErr("执行命令失败:" + rerr.Error()))
|
return nil, rerr
|
||||||
}
|
}
|
||||||
return string(buf)
|
res := string(buf)
|
||||||
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行带交互的命令
|
//执行带交互的命令
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/siddontang/go/log"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"mayfly-go/base"
|
"mayfly-go/base/model"
|
||||||
"mayfly-go/base/utils"
|
"mayfly-go/base/utils"
|
||||||
"mayfly-go/models"
|
"mayfly-go/models"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/siddontang/go/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
const BasePath = "./machine/shell/"
|
const BasePath = "./machine/shell/"
|
||||||
@@ -16,26 +17,29 @@ const MonitorTemp = "cpuRate:{cpuRate}%,memRate:{memRate}%,sysLoad:{sysLoad}\n"
|
|||||||
// shell文件内容缓存,避免每次读取文件
|
// shell文件内容缓存,避免每次读取文件
|
||||||
var shellCache = make(map[string]string)
|
var shellCache = make(map[string]string)
|
||||||
|
|
||||||
func GetProcessByName(cli *Cli, name string) string {
|
func (c *Cli) GetProcessByName(name string) (*string, error) {
|
||||||
return cli.Run(getShellContent("sys_info"))
|
return c.Run(getShellContent("sys_info"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSystemInfo(cli *Cli) string {
|
func (c *Cli) GetSystemInfo() (*string, error) {
|
||||||
return cli.Run(getShellContent("system_info"))
|
return c.Run(getShellContent("system_info"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMonitorInfo(cli *Cli) *models.MachineMonitor {
|
func (c *Cli) GetMonitorInfo() *models.MachineMonitor {
|
||||||
mm := new(models.MachineMonitor)
|
mm := new(models.MachineMonitor)
|
||||||
res := cli.Run(getShellContent("monitor"))
|
res, _ := c.Run(getShellContent("monitor"))
|
||||||
|
if res == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
resMap := make(map[string]interface{})
|
resMap := make(map[string]interface{})
|
||||||
utils.ReverStrTemplate(MonitorTemp, res, resMap)
|
utils.ReverStrTemplate(MonitorTemp, *res, resMap)
|
||||||
|
|
||||||
err := utils.Map2Struct(resMap, mm)
|
err := utils.Map2Struct(resMap, mm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("解析machine monitor: %s", err.Error())
|
log.Error("解析machine monitor: %s", err.Error())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
mm.MachineId = cli.machine.Id
|
mm.MachineId = c.machine.Id
|
||||||
mm.CreateTime = time.Now()
|
mm.CreateTime = time.Now()
|
||||||
return mm
|
return mm
|
||||||
}
|
}
|
||||||
@@ -47,7 +51,7 @@ func getShellContent(name string) string {
|
|||||||
return cacheShell
|
return cacheShell
|
||||||
}
|
}
|
||||||
bytes, err := ioutil.ReadFile(BasePath + name + ".sh")
|
bytes, err := ioutil.ReadFile(BasePath + name + ".sh")
|
||||||
base.ErrIsNil(err, "获取shell文件失败")
|
model.ErrIsNil(err, "获取shell文件失败")
|
||||||
shellStr := string(bytes)
|
shellStr := string(bytes)
|
||||||
shellCache[name] = shellStr
|
shellCache[name] = shellStr
|
||||||
return shellStr
|
return shellStr
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package machine
|
package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"mayfly-go/base"
|
"mayfly-go/base/model"
|
||||||
"mayfly-go/base/utils"
|
"mayfly-go/base/utils"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -11,10 +11,10 @@ type SystemVersion struct {
|
|||||||
Version string
|
Version string
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSystemVersion(cli *Cli) *SystemVersion {
|
func (c *Cli) GetSystemVersion() *SystemVersion {
|
||||||
res := cli.Run("cat /etc/redhat-release")
|
res, _ := c.Run("cat /etc/redhat-release")
|
||||||
return &SystemVersion{
|
return &SystemVersion{
|
||||||
Version: res,
|
Version: *res,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,15 +68,15 @@ type Top struct {
|
|||||||
AvailMem int `json:"availMem"`
|
AvailMem int `json:"availMem"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTop(cli *Cli) *Top {
|
func (c *Cli) GetTop() *Top {
|
||||||
res := cli.Run("top -b -n 1 | head -5")
|
res, _ := c.Run("top -b -n 1 | head -5")
|
||||||
topTemp := "top - {upAndUsers}, load average: {loadavg}\n" +
|
topTemp := "top - {upAndUsers}, load average: {loadavg}\n" +
|
||||||
"Tasks:{totalTask} total,{runningTask} running,{sleepingTask} sleeping,{stoppedTask} stopped,{zombieTask} zombie\n" +
|
"Tasks:{totalTask} total,{runningTask} running,{sleepingTask} sleeping,{stoppedTask} stopped,{zombieTask} zombie\n" +
|
||||||
"%Cpu(s):{cpuUs} us,{cpuSy} sy,{cpuNi} ni,{cpuId} id,{cpuWa} wa,{cpuHi} hi,{cpuSi} si,{cpuSt} st\n" +
|
"%Cpu(s):{cpuUs} us,{cpuSy} sy,{cpuNi} ni,{cpuId} id,{cpuWa} wa,{cpuHi} hi,{cpuSi} si,{cpuSt} st\n" +
|
||||||
"KiB Mem :{totalMem} total,{freeMem} free,{usedMem} used,{cacheMem} buff/cache\n" +
|
"KiB Mem :{totalMem} total,{freeMem} free,{usedMem} used,{cacheMem} buff/cache\n" +
|
||||||
"KiB Swap:{totalSwap} total,{freeSwap} free,{usedSwap} used. {availMem} avail Mem \n"
|
"KiB Swap:{totalSwap} total,{freeSwap} free,{usedSwap} used. {availMem} avail Mem \n"
|
||||||
resMap := make(map[string]interface{})
|
resMap := make(map[string]interface{})
|
||||||
utils.ReverStrTemplate(topTemp, res, resMap)
|
utils.ReverStrTemplate(topTemp, *res, resMap)
|
||||||
|
|
||||||
//17:14:07 up 5 days, 6:30, 2
|
//17:14:07 up 5 days, 6:30, 2
|
||||||
timeUpAndUserStr := resMap["upAndUsers"].(string)
|
timeUpAndUserStr := resMap["upAndUsers"].(string)
|
||||||
@@ -93,7 +93,7 @@ func GetTop(cli *Cli) *Top {
|
|||||||
|
|
||||||
top := &Top{Time: time, Up: up, NowUsers: users, OneMinLoadavg: float32(oneMinLa), FiveMinLoadavg: float32(fiveMinLa), FifteenMinLoadavg: float32(fifMinLa)}
|
top := &Top{Time: time, Up: up, NowUsers: users, OneMinLoadavg: float32(oneMinLa), FiveMinLoadavg: float32(fiveMinLa), FifteenMinLoadavg: float32(fifMinLa)}
|
||||||
err := utils.Map2Struct(resMap, top)
|
err := utils.Map2Struct(resMap, top)
|
||||||
base.BizErrIsNil(err, "解析top出错")
|
model.BizErrIsNil(err, "解析top出错")
|
||||||
return top
|
return top
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,51 +3,14 @@ package machine
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/astaxie/beego/logs"
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
|
||||||
|
|
||||||
//func WsSsh(c *controllers.MachineController) {
|
"github.com/beego/beego/v2/core/logs"
|
||||||
// wsConn, err := upGrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
|
"github.com/gorilla/websocket"
|
||||||
// if err != nil {
|
"golang.org/x/crypto/ssh"
|
||||||
// panic(base.NewBizErr("获取requst responsewirte错误"))
|
)
|
||||||
// }
|
|
||||||
//
|
|
||||||
// cols, _ := c.GetInt("col", 80)
|
|
||||||
// rows, _ := c.GetInt("rows", 40)
|
|
||||||
//
|
|
||||||
// sws, err := NewLogicSshWsSession(cols, rows, true, GetCli(c.GetMachineId()).client, wsConn)
|
|
||||||
// if sws == nil {
|
|
||||||
// panic(base.NewBizErr("连接失败"))
|
|
||||||
// }
|
|
||||||
// //if wshandleError(wsConn, err) {
|
|
||||||
// // return
|
|
||||||
// //}
|
|
||||||
// defer sws.Close()
|
|
||||||
//
|
|
||||||
// quitChan := make(chan bool, 3)
|
|
||||||
// sws.Start(quitChan)
|
|
||||||
// go sws.Wait(quitChan)
|
|
||||||
//
|
|
||||||
// <-quitChan
|
|
||||||
// //保存日志
|
|
||||||
//
|
|
||||||
// ////write logs
|
|
||||||
// //xtermLog := model.SshLog{
|
|
||||||
// // StartedAt: startTime,
|
|
||||||
// // UserId: userM.Id,
|
|
||||||
// // Log: sws.LogString(),
|
|
||||||
// // MachineId: idx,
|
|
||||||
// // ClientIp: cIp,
|
|
||||||
// //}
|
|
||||||
// //err = xtermLog.Create()
|
|
||||||
// //if wshandleError(wsConn, err) {
|
|
||||||
// // return
|
|
||||||
//}
|
|
||||||
|
|
||||||
type safeBuffer struct {
|
type safeBuffer struct {
|
||||||
buffer bytes.Buffer
|
buffer bytes.Buffer
|
||||||
@@ -75,9 +38,9 @@ const (
|
|||||||
wsMsgResize = "resize"
|
wsMsgResize = "resize"
|
||||||
)
|
)
|
||||||
|
|
||||||
type wsMsg struct {
|
type WsMsg struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Cmd string `json:"cmd"`
|
Msg string `json:"msg"`
|
||||||
Cols int `json:"cols"`
|
Cols int `json:"cols"`
|
||||||
Rows int `json:"rows"`
|
Rows int `json:"rows"`
|
||||||
}
|
}
|
||||||
@@ -89,11 +52,9 @@ type LogicSshWsSession struct {
|
|||||||
inputFilterBuff *safeBuffer //用来过滤输入的命令和ssh_filter配置对比的
|
inputFilterBuff *safeBuffer //用来过滤输入的命令和ssh_filter配置对比的
|
||||||
session *ssh.Session
|
session *ssh.Session
|
||||||
wsConn *websocket.Conn
|
wsConn *websocket.Conn
|
||||||
isAdmin bool
|
|
||||||
IsFlagged bool `comment:"当前session是否包含禁止命令"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLogicSshWsSession(cols, rows int, isAdmin bool, cli *Cli, wsConn *websocket.Conn) (*LogicSshWsSession, error) {
|
func NewLogicSshWsSession(cols, rows int, cli *Cli, wsConn *websocket.Conn) (*LogicSshWsSession, error) {
|
||||||
sshSession, err := cli.GetSession()
|
sshSession, err := cli.GetSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -132,8 +93,6 @@ func NewLogicSshWsSession(cols, rows int, isAdmin bool, cli *Cli, wsConn *websoc
|
|||||||
inputFilterBuff: inputBuf,
|
inputFilterBuff: inputBuf,
|
||||||
session: sshSession,
|
session: sshSession,
|
||||||
wsConn: wsConn,
|
wsConn: wsConn,
|
||||||
isAdmin: isAdmin,
|
|
||||||
IsFlagged: false,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,15 +126,13 @@ func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) {
|
|||||||
//read websocket msg
|
//read websocket msg
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
_, wsData, err := wsConn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error("reading webSocket message failed")
|
logs.Error("reading webSocket message failed: ", err)
|
||||||
//panic(base.NewBizErr("reading webSocket message failed"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//unmashal bytes into struct
|
//unmashal bytes into struct
|
||||||
msgObj := wsMsg{}
|
msgObj := WsMsg{}
|
||||||
if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
||||||
logs.Error("unmarshal websocket message failed")
|
logs.Error("unmarshal websocket message failed:", err)
|
||||||
//panic(base.NewBizErr("unmarshal websocket message failed"))
|
|
||||||
}
|
}
|
||||||
switch msgObj.Type {
|
switch msgObj.Type {
|
||||||
case wsMsgResize:
|
case wsMsgResize:
|
||||||
@@ -183,7 +140,6 @@ func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) {
|
|||||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
||||||
if err := sws.session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
if err := sws.session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
||||||
logs.Error("ssh pty change windows size failed")
|
logs.Error("ssh pty change windows size failed")
|
||||||
//panic(base.NewBizErr("ssh pty change windows size failed"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case wsMsgCmd:
|
case wsMsgCmd:
|
||||||
@@ -193,7 +149,7 @@ func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) {
|
|||||||
// logs.Error("websock cmd string base64 decoding failed")
|
// logs.Error("websock cmd string base64 decoding failed")
|
||||||
// //panic(base.NewBizErr("websock cmd string base64 decoding failed"))
|
// //panic(base.NewBizErr("websock cmd string base64 decoding failed"))
|
||||||
//}
|
//}
|
||||||
sws.sendWebsocketInputCommandToSshSessionStdinPipe([]byte(msgObj.Cmd))
|
sws.sendWebsocketInputCommandToSshSessionStdinPipe([]byte(msgObj.Msg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,7 +159,6 @@ func (sws *LogicSshWsSession) receiveWsMsg(exitCh chan bool) {
|
|||||||
func (sws *LogicSshWsSession) sendWebsocketInputCommandToSshSessionStdinPipe(cmdBytes []byte) {
|
func (sws *LogicSshWsSession) sendWebsocketInputCommandToSshSessionStdinPipe(cmdBytes []byte) {
|
||||||
if _, err := sws.stdinPipe.Write(cmdBytes); err != nil {
|
if _, err := sws.stdinPipe.Write(cmdBytes); err != nil {
|
||||||
logs.Error("ws cmd bytes write to ssh.stdin pipe failed")
|
logs.Error("ws cmd bytes write to ssh.stdin pipe failed")
|
||||||
//panic(base.NewBizErr("ws cmd bytes write to ssh.stdin pipe failed"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,12 +183,10 @@ func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) {
|
|||||||
err := wsConn.WriteMessage(websocket.TextMessage, bs)
|
err := wsConn.WriteMessage(websocket.TextMessage, bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error("ssh sending combo output to webSocket failed")
|
logs.Error("ssh sending combo output to webSocket failed")
|
||||||
//panic(base.NewBizErr("ssh sending combo output to webSocket failed"))
|
|
||||||
}
|
}
|
||||||
_, err = sws.logBuff.Write(bs)
|
_, err = sws.logBuff.Write(bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Error("combo output to log buffer failed")
|
logs.Error("combo output to log buffer failed")
|
||||||
//panic(base.NewBizErr("combo output to log buffer failed"))
|
|
||||||
}
|
}
|
||||||
sws.comboOutput.buffer.Reset()
|
sws.comboOutput.buffer.Reset()
|
||||||
}
|
}
|
||||||
@@ -246,8 +199,7 @@ func (sws *LogicSshWsSession) sendComboOutput(exitCh chan bool) {
|
|||||||
|
|
||||||
func (sws *LogicSshWsSession) Wait(quitChan chan bool) {
|
func (sws *LogicSshWsSession) Wait(quitChan chan bool) {
|
||||||
if err := sws.session.Wait(); err != nil {
|
if err := sws.session.Wait(); err != nil {
|
||||||
logs.Error("ssh session wait failed")
|
logs.Error("ssh session wait failed: ", err)
|
||||||
//panic(base.NewBizErr("ssh session wait failed"))
|
|
||||||
setQuit(quitChan)
|
setQuit(quitChan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
main.go
15
main.go
@@ -1,15 +1,16 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego"
|
|
||||||
"github.com/astaxie/beego/context"
|
|
||||||
"github.com/astaxie/beego/orm"
|
|
||||||
"github.com/astaxie/beego/plugins/cors"
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
_ "mayfly-go/routers"
|
_ "mayfly-go/routers"
|
||||||
scheduler "mayfly-go/scheudler"
|
scheduler "mayfly-go/scheudler"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
|
"github.com/beego/beego/v2/server/web"
|
||||||
|
"github.com/beego/beego/v2/server/web/context"
|
||||||
|
"github.com/beego/beego/v2/server/web/filter/cors"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -21,7 +22,7 @@ func init() {
|
|||||||
func main() {
|
func main() {
|
||||||
orm.Debug = true
|
orm.Debug = true
|
||||||
// 跨域配置
|
// 跨域配置
|
||||||
beego.InsertFilter("/**", beego.BeforeRouter, cors.Allow(&cors.Options{
|
web.InsertFilter("/**", web.BeforeRouter, cors.Allow(&cors.Options{
|
||||||
AllowAllOrigins: true,
|
AllowAllOrigins: true,
|
||||||
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
||||||
AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
|
AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
|
||||||
@@ -30,7 +31,7 @@ func main() {
|
|||||||
}))
|
}))
|
||||||
scheduler.Start()
|
scheduler.Start()
|
||||||
defer scheduler.Stop()
|
defer scheduler.Stop()
|
||||||
beego.Run()
|
web.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解决beego无法访问根目录静态文件
|
// 解决beego无法访问根目录静态文件
|
||||||
|
|||||||
4345
mayfly-go-front/package-lock.json
generated
4345
mayfly-go-front/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,27 +13,31 @@
|
|||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"echarts": "^4.8.0",
|
"echarts": "^4.8.0",
|
||||||
"element-ui": "^2.13.2",
|
"element-ui": "^2.13.2",
|
||||||
|
"sql-formatter": "^2.3.3",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-class-component": "^7.2.3",
|
"vue-class-component": "^7.2.3",
|
||||||
|
"vue-codemirror": "^4.0.6",
|
||||||
"vue-property-decorator": "^8.4.2",
|
"vue-property-decorator": "^8.4.2",
|
||||||
"vue-router": "^3.2.0",
|
"vue-router": "^3.2.0",
|
||||||
"vuex": "^3.4.0"
|
"vuex": "^3.4.0",
|
||||||
|
"xterm": "^4.9.0",
|
||||||
|
"xterm-addon-fit": "^0.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
||||||
"@typescript-eslint/parser": "^2.33.0",
|
"@typescript-eslint/parser": "^2.33.0",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.9",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/cli-plugin-eslint": "~4.5.9",
|
||||||
"@vue/cli-plugin-router": "~4.5.0",
|
"@vue/cli-plugin-router": "~4.5.9",
|
||||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
"@vue/cli-plugin-typescript": "~4.5.9",
|
||||||
"@vue/cli-plugin-vuex": "~4.5.0",
|
"@vue/cli-plugin-vuex": "~4.5.9",
|
||||||
"@vue/cli-service": "~4.5.0",
|
"@vue/cli-service": "~4.5.9",
|
||||||
"@vue/eslint-config-typescript": "^5.0.2",
|
"@vue/eslint-config-typescript": "^5.0.2",
|
||||||
"eslint": "^6.7.2",
|
"eslint": "^6.7.2",
|
||||||
"eslint-plugin-vue": "^6.2.2",
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
"typescript": "~3.9.3",
|
"typescript": "~3.9.7",
|
||||||
"vue-template-compiler": "^2.6.11",
|
"vue-template-compiler": "^2.6.11",
|
||||||
"sass-resources-loader": "^2.0.3",
|
"sass-resources-loader": "^2.1.1",
|
||||||
"ts-import-plugin": "^1.6.6",
|
"ts-import-plugin": "^1.6.6",
|
||||||
"less": "^3.10.3",
|
"less": "^3.10.3",
|
||||||
"less-loader": "^5.0.0"
|
"less-loader": "^5.0.0"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="less">
|
||||||
#app {
|
#app {
|
||||||
background-color: #222d32;
|
background-color: #222d32;
|
||||||
}
|
}
|
||||||
|
|||||||
60
mayfly-go-front/src/common/assert.ts
Normal file
60
mayfly-go-front/src/common/assert.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/**
|
||||||
|
* 不符合业务断言错误
|
||||||
|
*/
|
||||||
|
class AssertError extends Error {
|
||||||
|
constructor(message: string) {
|
||||||
|
super(message); // (1)
|
||||||
|
// 错误类名
|
||||||
|
this.name = "AssertError";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言对象不为null或undefiend
|
||||||
|
*
|
||||||
|
* @param obj 对象
|
||||||
|
* @param msg 错误提示
|
||||||
|
*/
|
||||||
|
export function notNull(obj: any, msg: string) {
|
||||||
|
if (obj == null || obj == undefined) {
|
||||||
|
throw new AssertError(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言字符串不能为空
|
||||||
|
*
|
||||||
|
* @param str 字符串
|
||||||
|
* @param msg 错误提示
|
||||||
|
*/
|
||||||
|
export function notEmpty(str: string, msg: string) {
|
||||||
|
if (str == null || str == undefined || str == '') {
|
||||||
|
throw new AssertError(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言两对象相等
|
||||||
|
*
|
||||||
|
* @param obj1 对象1
|
||||||
|
* @param obj2 对象2
|
||||||
|
* @param msg 错误消息
|
||||||
|
*/
|
||||||
|
export function isEquals(obj1: any, obj2: any, msg: string) {
|
||||||
|
if (obj1 !== obj2) {
|
||||||
|
throw new AssertError(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言表达式为true
|
||||||
|
*
|
||||||
|
* @param obj1 对象1
|
||||||
|
* @param obj2 对象2
|
||||||
|
* @param msg 错误消息
|
||||||
|
*/
|
||||||
|
export function isTrue(condition: boolean, msg: string) {
|
||||||
|
if (!condition) {
|
||||||
|
throw new AssertError(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -167,11 +167,28 @@ export default class App extends Vue {
|
|||||||
icon: 'el-icon-menu',
|
icon: 'el-icon-menu',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
|
id: 11,
|
||||||
type: 1,
|
type: 1,
|
||||||
name: '机器列表',
|
name: '机器列表',
|
||||||
url: '/machines',
|
url: '/machines',
|
||||||
icon: 'el-icon-menu',
|
icon: 'el-icon-menu',
|
||||||
code: 'index',
|
code: 'machines',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
type: 1,
|
||||||
|
name: 'DBMS',
|
||||||
|
icon: 'el-icon-menu',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 21,
|
||||||
|
type: 1,
|
||||||
|
name: '数据查询',
|
||||||
|
url: '/db-select-data',
|
||||||
|
icon: 'el-icon-menu',
|
||||||
|
code: 'db-select',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -290,7 +307,7 @@ export default class App extends Vue {
|
|||||||
.menu {
|
.menu {
|
||||||
border-right: none;
|
border-right: none;
|
||||||
// 禁止选择
|
// 禁止选择
|
||||||
moz-user-select: -moz-none;
|
-moz-user-select: -moz-none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-o-user-select: none;
|
-o-user-select: none;
|
||||||
-khtml-user-select: none;
|
-khtml-user-select: none;
|
||||||
|
|||||||
@@ -15,9 +15,18 @@ import './assets/css/style.css'
|
|||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
// 注册组件后即可使用
|
// 注册组件后即可使用
|
||||||
// Vue.component('v-chart', ECharts)
|
// Vue.component('v-chart', ECharts)
|
||||||
|
|
||||||
Vue.use(ElementUI)
|
Vue.use(ElementUI)
|
||||||
|
|
||||||
|
// 全局error处理
|
||||||
|
Vue.config.errorHandler = function(err, vm ,info) {
|
||||||
|
// 如果是断言错误,则进行提示即可
|
||||||
|
if (err.name == 'AssertError') {
|
||||||
|
ElementUI.Message.error(err.message)
|
||||||
|
} else {
|
||||||
|
console.error(err, info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
|
|||||||
@@ -30,6 +30,24 @@ const routes: Array<RouteConfig> = [
|
|||||||
keepAlive: false
|
keepAlive: false
|
||||||
},
|
},
|
||||||
component: () => import('@/views/machine')
|
component: () => import('@/views/machine')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'db-select-data',
|
||||||
|
name: 'dbs',
|
||||||
|
meta: {
|
||||||
|
title: 'DBMS',
|
||||||
|
keepAlive: false
|
||||||
|
},
|
||||||
|
component: () => import('@/views/db/SelectData.vue')
|
||||||
|
// children: [{
|
||||||
|
// path: 'select',
|
||||||
|
// name: 'select-data',
|
||||||
|
// meta: {
|
||||||
|
// title: 'DBMS',
|
||||||
|
// keepAlive: false
|
||||||
|
// },
|
||||||
|
// component: () => import('@/views/db/SelectData.vue')
|
||||||
|
// }]
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
2
mayfly-go-front/src/shims-vue.d.ts
vendored
2
mayfly-go-front/src/shims-vue.d.ts
vendored
@@ -2,3 +2,5 @@ declare module '*.vue' {
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
export default Vue
|
export default Vue
|
||||||
}
|
}
|
||||||
|
declare module 'vue-codemirror';
|
||||||
|
declare module 'sql-formatter';
|
||||||
312
mayfly-go-front/src/views/db/SelectData.vue
Normal file
312
mayfly-go-front/src/views/db/SelectData.vue
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="toolbar">
|
||||||
|
<div class="fl">
|
||||||
|
<el-select
|
||||||
|
size="small"
|
||||||
|
v-model="dbId"
|
||||||
|
placeholder="请选择数据库"
|
||||||
|
@change="changeDb"
|
||||||
|
@clear="clearDb"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in dbs.list"
|
||||||
|
:key="item.id"
|
||||||
|
:label="`${item.name} [${item.type}]`"
|
||||||
|
:value="item.id"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-container style="height: 50%; border: 1px solid #eee; margin-top: 1px">
|
||||||
|
<el-aside width="70%" style="background-color: rgb(238, 241, 246)">
|
||||||
|
<div class="toolbar">
|
||||||
|
<div class="fl">
|
||||||
|
<el-button
|
||||||
|
@click="runSql"
|
||||||
|
type="success"
|
||||||
|
icon="el-icon-video-play"
|
||||||
|
size="mini"
|
||||||
|
plain
|
||||||
|
>执行</el-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
@click="formatSql"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-magic-stick"
|
||||||
|
size="mini"
|
||||||
|
plain
|
||||||
|
>格式化</el-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<el-button
|
||||||
|
@click="saveSql"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-document-add"
|
||||||
|
size="mini"
|
||||||
|
plain
|
||||||
|
>保存</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<codemirror
|
||||||
|
class="codesql"
|
||||||
|
ref="cmEditor"
|
||||||
|
v-model="sql"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:options="cmOptions"
|
||||||
|
@inputRead="inputRead"
|
||||||
|
/>
|
||||||
|
</el-aside>
|
||||||
|
|
||||||
|
<el-container style="margin-left: 2px">
|
||||||
|
<el-header
|
||||||
|
style="text-align: left; height: 45px; font-size: 12px; padding: 0px"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="tableName"
|
||||||
|
placeholder="请选择表"
|
||||||
|
@change="changeTable"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 99%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in tableMetadata"
|
||||||
|
:key="item.tableName"
|
||||||
|
:label="
|
||||||
|
item.tableName +
|
||||||
|
(item.tableComment != '' ? `【${item.tableComment}】` : '')
|
||||||
|
"
|
||||||
|
:value="item.tableName"
|
||||||
|
>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-header>
|
||||||
|
|
||||||
|
<el-main style="padding: 0px; height: 100%; overflow: hidden">
|
||||||
|
<el-table :data="columnMetadata" height="100%" size="mini">
|
||||||
|
<el-table-column prop="columnName" label="名称"> </el-table-column>
|
||||||
|
<el-table-column prop="columnType" label="类型"> </el-table-column>
|
||||||
|
<el-table-column prop="columnComment" label="备注">
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
<el-table
|
||||||
|
style="margin-top: 1px"
|
||||||
|
:data="selectRes.data"
|
||||||
|
size="mini"
|
||||||
|
max-height="300"
|
||||||
|
stripe
|
||||||
|
border
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
min-width="100"
|
||||||
|
align="center"
|
||||||
|
v-for="item in selectRes.tableColumn"
|
||||||
|
:key="item"
|
||||||
|
:prop="item"
|
||||||
|
:label="item"
|
||||||
|
>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- <el-pagination
|
||||||
|
style="text-align: center"
|
||||||
|
background
|
||||||
|
layout="prev, pager, next, total, jumper"
|
||||||
|
:total="data.total"
|
||||||
|
:current-page.sync="params.pageNum"
|
||||||
|
:page-size="params.pageSize"
|
||||||
|
/> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from 'vue-property-decorator'
|
||||||
|
import { dbApi } from './api'
|
||||||
|
|
||||||
|
import 'codemirror/theme/ambiance.css'
|
||||||
|
import 'codemirror/addon/hint/show-hint.css'
|
||||||
|
// import base style
|
||||||
|
import 'codemirror/lib/codemirror.css'
|
||||||
|
// 引入主题后还需要在 options 中指定主题才会生效
|
||||||
|
import 'codemirror/theme/base16-light.css'
|
||||||
|
|
||||||
|
// require('codemirror/addon/edit/matchbrackets')
|
||||||
|
require('codemirror/addon/selection/active-line')
|
||||||
|
import { codemirror } from 'vue-codemirror'
|
||||||
|
import 'codemirror/mode/sql/sql.js'
|
||||||
|
import 'codemirror/addon/hint/show-hint.js'
|
||||||
|
import 'codemirror/addon/hint/sql-hint.js'
|
||||||
|
|
||||||
|
import sqlFormatter from 'sql-formatter'
|
||||||
|
import { notEmpty } from '@/common/assert'
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
name: 'SelectData',
|
||||||
|
components: {
|
||||||
|
codemirror,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class SelectData extends Vue {
|
||||||
|
dbs = []
|
||||||
|
tables = []
|
||||||
|
dbId = ''
|
||||||
|
tableName = ''
|
||||||
|
tableMetadata = []
|
||||||
|
columnMetadata = []
|
||||||
|
sql = ''
|
||||||
|
selectRes = {
|
||||||
|
tableColumn: [],
|
||||||
|
data: [],
|
||||||
|
}
|
||||||
|
params = {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
}
|
||||||
|
placeholder = 'sqlshuru'
|
||||||
|
cmOptions = {
|
||||||
|
tabSize: 4,
|
||||||
|
mode: 'text/x-sql',
|
||||||
|
// theme: 'cobalt',
|
||||||
|
lineNumbers: true,
|
||||||
|
line: true,
|
||||||
|
indentWithTabs: true,
|
||||||
|
smartIndent: true,
|
||||||
|
// matchBrackets: true,
|
||||||
|
theme: 'base16-light',
|
||||||
|
autofocus: true,
|
||||||
|
extraKeys: { Tab: 'autocomplete' }, // 自定义快捷键
|
||||||
|
hintOptions: {
|
||||||
|
completeSingle: false,
|
||||||
|
// 自定义提示选项
|
||||||
|
tables: {},
|
||||||
|
},
|
||||||
|
// more CodeMirror options...
|
||||||
|
}
|
||||||
|
|
||||||
|
get codemirror() {
|
||||||
|
return this.$refs.cmEditor['codemirror']
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.search()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入字符给提示
|
||||||
|
inputRead(instance: any, changeObj: any) {
|
||||||
|
if (/^[a-zA-Z]/.test(changeObj.text[0])) {
|
||||||
|
this.showHint()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行sql
|
||||||
|
async runSql() {
|
||||||
|
notEmpty(this.dbId, '请先选择数据库')
|
||||||
|
// 没有选中的文本,则为全部文本
|
||||||
|
let selectSql = this.codemirror.getSelection()
|
||||||
|
if (selectSql == '') {
|
||||||
|
selectSql = this.sql
|
||||||
|
}
|
||||||
|
notEmpty(this.sql, '内容不能为空')
|
||||||
|
const res = await dbApi.selectData.request({
|
||||||
|
id: this.dbId,
|
||||||
|
selectSql,
|
||||||
|
})
|
||||||
|
let tableColumn: any
|
||||||
|
let data
|
||||||
|
if (res.length > 0) {
|
||||||
|
tableColumn = Object.keys(res[0])
|
||||||
|
data = res
|
||||||
|
} else {
|
||||||
|
tableColumn = []
|
||||||
|
data = []
|
||||||
|
}
|
||||||
|
this.selectRes.tableColumn = tableColumn
|
||||||
|
this.selectRes.data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveSql() {
|
||||||
|
notEmpty(this.sql, 'sql内容不能为空')
|
||||||
|
notEmpty(this.dbId, '请先选择数据库')
|
||||||
|
await dbApi.saveSql.request({ id: this.dbId, sql: this.sql, type: 1 })
|
||||||
|
this.$message.success('保存成功')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更改数据库事件
|
||||||
|
async changeDb(id: number) {
|
||||||
|
if (!id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.clearDb()
|
||||||
|
this.tableMetadata = await dbApi.tableMetadata.request({ id })
|
||||||
|
// 赋值第一个表信息
|
||||||
|
if (this.tableMetadata.length > 0) {
|
||||||
|
this.tableName = this.tableMetadata[0]['tableName']
|
||||||
|
this.changeTable(this.tableName)
|
||||||
|
}
|
||||||
|
const dbSql = await dbApi.getSql.request({ id, type: 1 })
|
||||||
|
if (dbSql) {
|
||||||
|
this.sql = dbSql.sql
|
||||||
|
}
|
||||||
|
this.cmOptions.hintOptions.tables = await dbApi.hintTables.request({
|
||||||
|
id: this.dbId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清空数据库事件
|
||||||
|
clearDb() {
|
||||||
|
this.tableName = ''
|
||||||
|
this.tableMetadata = []
|
||||||
|
this.columnMetadata = []
|
||||||
|
this.selectRes.data = []
|
||||||
|
this.selectRes.tableColumn = []
|
||||||
|
this.sql = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择表事件
|
||||||
|
async changeTable(tableName: string) {
|
||||||
|
if (tableName == '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.columnMetadata = await dbApi.columnMetadata.request({
|
||||||
|
id: this.dbId,
|
||||||
|
tableName,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动提示功能
|
||||||
|
showHint() {
|
||||||
|
this.codemirror.showHint()
|
||||||
|
}
|
||||||
|
|
||||||
|
formatSql() {
|
||||||
|
/* 获取文本编辑器内容*/
|
||||||
|
let sqlContent = ''
|
||||||
|
sqlContent = this.codemirror.getValue()
|
||||||
|
/* 将sql内容进行格式后放入编辑器中*/
|
||||||
|
this.codemirror.setValue(sqlFormatter.format(sqlContent))
|
||||||
|
}
|
||||||
|
|
||||||
|
async search() {
|
||||||
|
this.dbs = await dbApi.dbs.request(this.params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.codesql {
|
||||||
|
font-size: 10pt;
|
||||||
|
font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono,
|
||||||
|
DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
25
mayfly-go-front/src/views/db/api.ts
Normal file
25
mayfly-go-front/src/views/db/api.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import Api from '@/common/Api';
|
||||||
|
|
||||||
|
export const dbApi = {
|
||||||
|
// 获取权限列表
|
||||||
|
dbs: Api.create("/dbs", 'get'),
|
||||||
|
tableMetadata: Api.create("/db/{id}/t-metadata", 'get'),
|
||||||
|
columnMetadata: Api.create("/db/{id}/c-metadata", 'get'),
|
||||||
|
// 获取表即列提示
|
||||||
|
hintTables: Api.create("/db/{id}/hint-tables", 'get'),
|
||||||
|
selectData: Api.create("/db/{id}/select", 'get'),
|
||||||
|
// 保存sql
|
||||||
|
saveSql: Api.create("/db/{id}/sql", 'post'),
|
||||||
|
// 获取保存的sql
|
||||||
|
getSql: Api.create("/db/{id}/sql", 'get'),
|
||||||
|
lsFile: Api.create("/devops/machines/files/{fileId}/ls", 'get'),
|
||||||
|
rmFile: Api.create("/devops/machines/files/{fileId}/rm", 'delete'),
|
||||||
|
uploadFile: Api.create("/devops/machines/files/upload", 'post'),
|
||||||
|
fileContent: Api.create("/devops/machines/files/{fileId}/cat", 'get'),
|
||||||
|
// 修改文件内容
|
||||||
|
updateFileContent: Api.create("/devops/machines/files/{id}", 'put'),
|
||||||
|
// 添加文件or目录
|
||||||
|
addConf: Api.create("/devops/machines/{machineId}/files", 'post'),
|
||||||
|
// 删除配置的文件or目录
|
||||||
|
delConf: Api.create("/devops/machines/files/{id}", 'delete'),
|
||||||
|
}
|
||||||
1
mayfly-go-front/src/views/db/index.ts
Normal file
1
mayfly-go-front/src/views/db/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { default } from './SelectData.vue';
|
||||||
@@ -8,7 +8,8 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
@click="openFormDialog(false)"
|
@click="openFormDialog(false)"
|
||||||
plain
|
plain
|
||||||
>添加</el-button>
|
>添加</el-button
|
||||||
|
>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
icon="el-icon-edit"
|
icon="el-icon-edit"
|
||||||
@@ -16,38 +17,51 @@
|
|||||||
:disabled="currentId == null"
|
:disabled="currentId == null"
|
||||||
@click="openFormDialog(currentData)"
|
@click="openFormDialog(currentData)"
|
||||||
plain
|
plain
|
||||||
>编辑</el-button>
|
>编辑</el-button
|
||||||
|
>
|
||||||
<el-button
|
<el-button
|
||||||
:disabled="currentId == null"
|
:disabled="currentId == null"
|
||||||
@click="deleteMachine(currentId)"
|
@click="deleteMachine(currentId)"
|
||||||
type="danger"
|
type="danger"
|
||||||
icon="el-icon-delete"
|
icon="el-icon-delete"
|
||||||
size="mini"
|
size="mini"
|
||||||
>删除</el-button>
|
>删除</el-button
|
||||||
|
>
|
||||||
<el-button
|
<el-button
|
||||||
type="success"
|
type="success"
|
||||||
:disabled="currentId == null"
|
:disabled="currentId == null"
|
||||||
@click="fileManage(currentData)"
|
@click="fileManage(currentData)"
|
||||||
size="mini"
|
size="mini"
|
||||||
plain
|
plain
|
||||||
>文件管理</el-button>
|
>文件管理</el-button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="float: right;">
|
<div style="float: right">
|
||||||
<el-input
|
<el-input
|
||||||
placeholder="host"
|
placeholder="host"
|
||||||
size="mini"
|
size="mini"
|
||||||
style="width: 140px;"
|
style="width: 140px"
|
||||||
v-model="params.host"
|
v-model="params.host"
|
||||||
@clear="search"
|
@clear="search"
|
||||||
plain
|
plain
|
||||||
clearable
|
clearable
|
||||||
></el-input>
|
></el-input>
|
||||||
<el-button @click="search" type="success" icon="el-icon-search" size="mini"></el-button>
|
<el-button
|
||||||
|
@click="search"
|
||||||
|
type="success"
|
||||||
|
icon="el-icon-search"
|
||||||
|
size="mini"
|
||||||
|
></el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table :data="data.list" stripe style="width: 100%" @current-change="choose">
|
<el-table
|
||||||
|
:data="data.list"
|
||||||
|
stripe
|
||||||
|
style="width: 100%"
|
||||||
|
@current-change="choose"
|
||||||
|
>
|
||||||
<el-table-column label="选择" width="55px">
|
<el-table-column label="选择" width="55px">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-radio v-model="currentId" :label="scope.row.id">
|
<el-radio v-model="currentId" :label="scope.row.id">
|
||||||
@@ -70,7 +84,8 @@
|
|||||||
icom="el-icon-tickets"
|
icom="el-icon-tickets"
|
||||||
size="mini"
|
size="mini"
|
||||||
plain
|
plain
|
||||||
>基本信息</el-button>
|
>基本信息</el-button
|
||||||
|
>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="monitor(scope.row.id)"
|
@click="monitor(scope.row.id)"
|
||||||
@@ -78,14 +93,24 @@
|
|||||||
icom="el-icon-tickets"
|
icom="el-icon-tickets"
|
||||||
size="mini"
|
size="mini"
|
||||||
plain
|
plain
|
||||||
>监控</el-button>
|
>监控</el-button
|
||||||
|
>
|
||||||
<el-button
|
<el-button
|
||||||
type="success"
|
type="success"
|
||||||
@click="serviceManager(scope.row)"
|
@click="serviceManager(scope.row)"
|
||||||
:ref="scope.row"
|
:ref="scope.row"
|
||||||
size="mini"
|
size="mini"
|
||||||
plain
|
plain
|
||||||
>服务管理</el-button>
|
>服务管理</el-button
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
type="success"
|
||||||
|
@click="showTerminal(scope.row)"
|
||||||
|
:ref="scope.row"
|
||||||
|
size="mini"
|
||||||
|
plain
|
||||||
|
>终端</el-button
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@@ -100,17 +125,32 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<el-dialog title="基本信息" :visible.sync="infoDialog.visible" width="30%">
|
<el-dialog title="基本信息" :visible.sync="infoDialog.visible" width="30%">
|
||||||
<div style="white-space: pre-line;">{{infoDialog.info}}</div>
|
<div style="white-space: pre-line">{{ infoDialog.info }}</div>
|
||||||
<!-- <span slot="footer" class="dialog-footer">
|
<!-- <span slot="footer" class="dialog-footer">
|
||||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
|
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
|
||||||
</span>-->
|
</span>-->
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog @close="closeMonitor" title="监控信息" :visible.sync="monitorDialog.visible" width="60%">
|
<el-dialog
|
||||||
|
@close="closeMonitor"
|
||||||
|
title="监控信息"
|
||||||
|
:visible.sync="monitorDialog.visible"
|
||||||
|
width="60%"
|
||||||
|
>
|
||||||
<monitor ref="monitorDialog" :machineId="monitorDialog.machineId" />
|
<monitor ref="monitorDialog" :machineId="monitorDialog.machineId" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog
|
||||||
|
title="终端"
|
||||||
|
:visible.sync="terminalDialog.visible"
|
||||||
|
width="70%"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@close="closeTermnial"
|
||||||
|
>
|
||||||
|
<ssh-terminal ref="terminal" :socketURI="terminalDialog.socketUri" />
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<!-- <FileManage
|
<!-- <FileManage
|
||||||
:title="dialog.title"
|
:title="dialog.title"
|
||||||
:visible.sync="dialog.visible"
|
:visible.sync="dialog.visible"
|
||||||
@@ -132,12 +172,14 @@ import { Component, Vue } from 'vue-property-decorator'
|
|||||||
import { DynamicFormDialog } from '@/components/dynamic-form'
|
import { DynamicFormDialog } from '@/components/dynamic-form'
|
||||||
import Monitor from './Monitor.vue'
|
import Monitor from './Monitor.vue'
|
||||||
import { machineApi } from './api'
|
import { machineApi } from './api'
|
||||||
|
import SshTerminal from './SshTerminal.vue'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
name: 'MachineList',
|
name: 'MachineList',
|
||||||
components: {
|
components: {
|
||||||
DynamicFormDialog,
|
DynamicFormDialog,
|
||||||
Monitor,
|
Monitor,
|
||||||
|
SshTerminal,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class MachineList extends Vue {
|
export default class MachineList extends Vue {
|
||||||
@@ -166,6 +208,10 @@ export default class MachineList extends Vue {
|
|||||||
visible: false,
|
visible: false,
|
||||||
title: '',
|
title: '',
|
||||||
}
|
}
|
||||||
|
terminalDialog = {
|
||||||
|
visible: false,
|
||||||
|
socketUri: '',
|
||||||
|
}
|
||||||
formDialog = {
|
formDialog = {
|
||||||
visible: false,
|
visible: false,
|
||||||
title: '',
|
title: '',
|
||||||
@@ -291,6 +337,18 @@ export default class MachineList extends Vue {
|
|||||||
md.cancelInterval()
|
md.cancelInterval()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showTerminal(row: any) {
|
||||||
|
this.terminalDialog.visible = true
|
||||||
|
this.terminalDialog.socketUri = `ws://localhost:8888/api/machines/${row.id}/terminal`
|
||||||
|
}
|
||||||
|
|
||||||
|
closeTermnial() {
|
||||||
|
this.terminalDialog.visible = false
|
||||||
|
this.terminalDialog.socketUri = ''
|
||||||
|
const t: any = this.$refs['terminal']
|
||||||
|
t.closeAll()
|
||||||
|
}
|
||||||
|
|
||||||
openFormDialog(redis: any) {
|
openFormDialog(redis: any) {
|
||||||
let dialogTitle
|
let dialogTitle
|
||||||
if (redis) {
|
if (redis) {
|
||||||
@@ -330,4 +388,7 @@ export default class MachineList extends Vue {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.el-dialog__body {
|
||||||
|
padding: 2px 2px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
138
mayfly-go-front/src/views/machine/SshTerminal.vue
Normal file
138
mayfly-go-front/src/views/machine/SshTerminal.vue
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
<template>
|
||||||
|
<div style="height: 600px" id="xterm" class="xterm" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import 'xterm/css/xterm.css'
|
||||||
|
import { Terminal } from 'xterm'
|
||||||
|
import { FitAddon } from 'xterm-addon-fit'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Xterm',
|
||||||
|
props: {
|
||||||
|
socketURI: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
socketURI(val) {
|
||||||
|
if (val !== '') {
|
||||||
|
this.initSocket()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.initSocket()
|
||||||
|
// this.initTerm()
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.socket.close()
|
||||||
|
this.term.dispose()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initXterm() {
|
||||||
|
const term = new Terminal({
|
||||||
|
fontSize: 14,
|
||||||
|
cursorBlink: true,
|
||||||
|
// cursorStyle: 'underline', //光标样式
|
||||||
|
disableStdin: false,
|
||||||
|
theme: {
|
||||||
|
foreground: "#7e9192", //字体
|
||||||
|
background: "#002833", //背景色
|
||||||
|
cursor: "help", //设置光标
|
||||||
|
lineHeight: 16
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const fitAddon = new FitAddon()
|
||||||
|
term.loadAddon(fitAddon)
|
||||||
|
term.open(document.getElementById('xterm'))
|
||||||
|
fitAddon.fit()
|
||||||
|
term.focus()
|
||||||
|
this.term = term
|
||||||
|
|
||||||
|
// / **
|
||||||
|
// *添加事件监听器,用于按下键时的事件。事件值包含
|
||||||
|
// *将在data事件以及DOM事件中发送的字符串
|
||||||
|
// *触发了它。
|
||||||
|
// * @返回一个IDisposable停止监听。
|
||||||
|
// * /
|
||||||
|
// / ** 更新:xterm 4.x(新增)
|
||||||
|
// *为数据事件触发时添加事件侦听器。发生这种情况
|
||||||
|
// *用户输入或粘贴到终端时的示例。事件值
|
||||||
|
// *是`string`结果的结果,在典型的设置中,应该通过
|
||||||
|
// *到支持pty。
|
||||||
|
// * @返回一个IDisposable停止监听。
|
||||||
|
// * /
|
||||||
|
// 支持输入与粘贴方法
|
||||||
|
term.onData((key) => {
|
||||||
|
const cmd = {
|
||||||
|
type: 'cmd',
|
||||||
|
msg: key,
|
||||||
|
}
|
||||||
|
this.send(cmd)
|
||||||
|
})
|
||||||
|
// 为解决窗体resize方法才会向后端发送列数和行数,所以页面加载时也要触发此方法
|
||||||
|
this.send({
|
||||||
|
type: 'resize',
|
||||||
|
Cols: parseInt(term.cols),
|
||||||
|
Rows: parseInt(term.rows),
|
||||||
|
})
|
||||||
|
},
|
||||||
|
initSocket() {
|
||||||
|
this.socket = new WebSocket(this.socketURI)
|
||||||
|
// 监听socket连接
|
||||||
|
this.socket.onopen = this.open
|
||||||
|
// 监听socket错误信息
|
||||||
|
this.socket.onerror = this.error
|
||||||
|
// 监听socket消息
|
||||||
|
this.socket.onmessage = this.getMessage
|
||||||
|
// 发送socket消息
|
||||||
|
this.socket.onsend = this.send
|
||||||
|
},
|
||||||
|
open: function () {
|
||||||
|
console.log('socket连接成功')
|
||||||
|
this.initXterm()
|
||||||
|
//开启心跳
|
||||||
|
// this.start();
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
console.log('连接错误')
|
||||||
|
//重连
|
||||||
|
this.reconnect()
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.socket.close()
|
||||||
|
console.log('socket已经关闭')
|
||||||
|
//重连
|
||||||
|
// this.reconnect()
|
||||||
|
},
|
||||||
|
getMessage: function (msg) {
|
||||||
|
// console.log(msg)
|
||||||
|
this.term.write(msg['data'])
|
||||||
|
//msg是返回的数据
|
||||||
|
// msg = JSON.parse(msg.data);
|
||||||
|
// this.socket.send("ping");//有事没事ping一下,看看ws还活着没
|
||||||
|
// //switch用于处理返回的数据,根据返回数据的格式去判断
|
||||||
|
// switch (msg["operation"]) {
|
||||||
|
// case "stdout":
|
||||||
|
// this.term.write(msg["data"]);//这里write也许不是固定的,失败后找后端看一下该怎么往term里面write
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// console.error("Unexpected message type:", msg);//但是错误是固定的。。。。
|
||||||
|
// }
|
||||||
|
//收到服务器信息,心跳重置
|
||||||
|
// this.reset();
|
||||||
|
},
|
||||||
|
send: function (msg) {
|
||||||
|
// console.log(msg)
|
||||||
|
this.socket.send(JSON.stringify(msg))
|
||||||
|
},
|
||||||
|
closeAll() {
|
||||||
|
this.close()
|
||||||
|
this.term.dispose()
|
||||||
|
this.term = null
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -22,4 +22,5 @@ export const machineApi = {
|
|||||||
addConf: Api.create("/devops/machines/{machineId}/files", 'post'),
|
addConf: Api.create("/devops/machines/{machineId}/files", 'post'),
|
||||||
// 删除配置的文件or目录
|
// 删除配置的文件or目录
|
||||||
delConf: Api.create("/devops/machines/files/{id}", 'delete'),
|
delConf: Api.create("/devops/machines/files/{id}", 'delete'),
|
||||||
|
terminal: Api.create("/api/machines/{id}/terminal", 'get')
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego/orm"
|
"mayfly-go/base/model"
|
||||||
"mayfly-go/base"
|
|
||||||
"mayfly-go/controllers/vo"
|
"mayfly-go/controllers/vo"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Account struct {
|
type Account struct {
|
||||||
base.Model
|
model.Model
|
||||||
|
|
||||||
Username string `orm:"column(username)" json:"username"`
|
Username string `orm:"column(username)" json:"username"`
|
||||||
Password string `orm:"column(password)" json:"-"`
|
Password string `orm:"column(password)" json:"-"`
|
||||||
@@ -18,8 +19,8 @@ func init() {
|
|||||||
orm.RegisterModelWithPrefix("t_", new(Account))
|
orm.RegisterModelWithPrefix("t_", new(Account))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListAccount(param *base.PageParam, args ...interface{}) base.PageResult {
|
func ListAccount(param *model.PageParam, args ...interface{}) model.PageResult {
|
||||||
sql := "SELECT a.id, a.username, a.create_time, a.creator_id, a.creator, r.Id AS 'Role.Id', r.Name AS 'Role.Name'" +
|
sql := "SELECT a.id, a.username, a.create_time, a.creator_id, a.creator, r.Id AS 'Role.Id', r.Name AS 'Role.Name'" +
|
||||||
" FROM t_account a LEFT JOIN t_role r ON a.id = r.account_id"
|
" FROM t_account a LEFT JOIN t_role r ON a.id = r.account_id"
|
||||||
return base.GetPageBySql(sql, new([]vo.AccountVO), param, args)
|
return model.GetPageBySql(sql, new([]vo.AccountVO), param, args)
|
||||||
}
|
}
|
||||||
|
|||||||
34
models/db.go
Normal file
34
models/db.go
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"mayfly-go/base/model"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Db struct {
|
||||||
|
model.Model
|
||||||
|
|
||||||
|
Name string `orm:"column(name)" json:"name"`
|
||||||
|
Type string `orm:"column(type)" json:"type"` // 类型,mysql oracle等
|
||||||
|
Host string `orm:"column(host)" json:"host"`
|
||||||
|
Port int `orm:"column(port)" json:"port"`
|
||||||
|
Network string `orm:"column(network)" json:"network"`
|
||||||
|
Username string `orm:"column(username)" json:"username"`
|
||||||
|
Passowrd string `orm:"column(password)" json:"-"`
|
||||||
|
Database string `orm:"column(database)" json:"database"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
orm.RegisterModelWithPrefix("t_", new(Db))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDbById(id uint64) *Db {
|
||||||
|
db := new(Db)
|
||||||
|
db.Id = id
|
||||||
|
err := model.GetBy(db)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return db
|
||||||
|
}
|
||||||
26
models/db_sql.go
Normal file
26
models/db_sql.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"mayfly-go/base/model"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DbSql struct {
|
||||||
|
model.Model `orm:"-"`
|
||||||
|
|
||||||
|
DbId uint64 `orm:"column(db_id)" json:"db_id"`
|
||||||
|
Type int `orm:"column(type)" json:"type"` // 类型
|
||||||
|
Sql string `orm:"column(sql)" json:"sql"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
orm.RegisterModelWithPrefix("t_", new(DbSql))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDbSqlByUser(userId uint64, dbId uint64, sqlType int) *Db {
|
||||||
|
db := new(Db)
|
||||||
|
query := model.QuerySetter(db).Filter("CreatorId", userId).Filter("DbId", dbId).Filter("Type", sqlType)
|
||||||
|
model.GetOne(query, db, db)
|
||||||
|
return db
|
||||||
|
}
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego/orm"
|
"mayfly-go/base/model"
|
||||||
"mayfly-go/base"
|
|
||||||
"mayfly-go/controllers/vo"
|
"mayfly-go/controllers/vo"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Machine struct {
|
type Machine struct {
|
||||||
base.Model
|
model.Model
|
||||||
Name string `orm:"column(name)"`
|
Name string `orm:"column(name)"`
|
||||||
// IP地址
|
// IP地址
|
||||||
Ip string `orm:"column(ip)" json:"ip"`
|
Ip string `orm:"column(ip)" json:"ip"`
|
||||||
@@ -25,7 +26,7 @@ func init() {
|
|||||||
func GetMachineById(id uint64) *Machine {
|
func GetMachineById(id uint64) *Machine {
|
||||||
machine := new(Machine)
|
machine := new(Machine)
|
||||||
machine.Id = id
|
machine.Id = id
|
||||||
err := base.GetBy(machine)
|
err := model.GetBy(machine)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -33,13 +34,13 @@ func GetMachineById(id uint64) *Machine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 分页获取机器信息列表
|
// 分页获取机器信息列表
|
||||||
func GetMachineList(pageParam *base.PageParam) base.PageResult {
|
func GetMachineList(pageParam *model.PageParam) model.PageResult {
|
||||||
m := new([]Machine)
|
m := new([]Machine)
|
||||||
querySetter := base.QuerySetter(new(Machine)).OrderBy("-Id")
|
querySetter := model.QuerySetter(new(Machine)).OrderBy("-Id")
|
||||||
return base.GetPage(querySetter, pageParam, m, new([]vo.MachineVO))
|
return model.GetPage(querySetter, pageParam, m, new([]vo.MachineVO))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有需要监控的机器信息列表
|
// 获取所有需要监控的机器信息列表
|
||||||
func GetNeedMonitorMachine() *[]orm.Params {
|
func GetNeedMonitorMachine() *[]orm.Params {
|
||||||
return base.GetListBySql("SELECT id FROM t_machine WHERE need_monitor = 1")
|
return model.GetListBySql("SELECT id FROM t_machine WHERE need_monitor = 1")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego/orm"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MachineMonitor struct {
|
type MachineMonitor struct {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego/orm"
|
"mayfly-go/base/model"
|
||||||
"mayfly-go/base"
|
|
||||||
|
"github.com/beego/beego/v2/client/orm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Role struct {
|
type Role struct {
|
||||||
base.Model
|
model.Model
|
||||||
|
|
||||||
Name string `orm:"column(name)" json:"username"`
|
Name string `orm:"column(name)" json:"username"`
|
||||||
//AccountId int64 `orm:"column(account_id)`
|
//AccountId int64 `orm:"column(account_id)`
|
||||||
|
|||||||
100
routers/commentsRouter_controllers.go
Normal file
100
routers/commentsRouter_controllers.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package routers
|
||||||
|
|
||||||
|
import (
|
||||||
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
|
"github.com/beego/beego/v2/server/web/context/param"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:AccountController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:AccountController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "Accounts",
|
||||||
|
Router: "/accounts",
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:AccountController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:AccountController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "Login",
|
||||||
|
Router: "/accounts/login",
|
||||||
|
AllowHTTPMethods: []string{"post"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:DbController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:DbController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "ColumnMA",
|
||||||
|
Router: "/api/db/:dbId/c-metadata",
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:DbController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:DbController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "ExecSql",
|
||||||
|
Router: "/api/db/:dbId/exec-sql",
|
||||||
|
AllowHTTPMethods: []string{"post"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:DbController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:DbController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "HintTables",
|
||||||
|
Router: "/api/db/:dbId/hint-tables",
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:DbController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:DbController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "SelectData",
|
||||||
|
Router: "/api/db/:dbId/select",
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:DbController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:DbController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "SaveSql",
|
||||||
|
Router: "/api/db/:dbId/sql",
|
||||||
|
AllowHTTPMethods: []string{"post"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:DbController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:DbController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "GetSql",
|
||||||
|
Router: "/api/db/:dbId/sql",
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:DbController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:DbController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "TableMA",
|
||||||
|
Router: "/api/db/:dbId/t-metadata",
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["mayfly-go/controllers:DbController"] = append(beego.GlobalControllerRouter["mayfly-go/controllers:DbController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "Dbs",
|
||||||
|
Router: "/api/dbs",
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,23 +1,34 @@
|
|||||||
package routers
|
package routers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/astaxie/beego"
|
|
||||||
"mayfly-go/controllers"
|
"mayfly-go/controllers"
|
||||||
|
|
||||||
|
"github.com/beego/beego/v2/server/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
//beego.Router("/account/login", &controllers.LoginController{})
|
//web.Router("/account/login", &controllers.LoginController{})
|
||||||
//beego.Router("/account", &controllers.AccountController{})
|
//web.Router("/account", &controllers.AccountController{})
|
||||||
//beego.Include(&controllers.AccountController{})
|
//web.Include(&controllers.AccountController{})
|
||||||
//beego.Include()
|
//web.Include()
|
||||||
beego.Router("/api/accounts/login", &controllers.AccountController{}, "post:Login")
|
web.Router("/api/accounts/login", &controllers.AccountController{}, "post:Login")
|
||||||
beego.Router("/api/accounts", &controllers.AccountController{}, "get:Accounts")
|
web.Router("/api/accounts", &controllers.AccountController{}, "get:Accounts")
|
||||||
|
|
||||||
machine := &controllers.MachineController{}
|
machine := &controllers.MachineController{}
|
||||||
beego.Router("/api/machines", machine, "get:Machines")
|
web.Router("/api/machines", machine, "get:Machines")
|
||||||
beego.Router("/api/machines/?:machineId/run", machine, "get:Run")
|
web.Router("/api/machines/?:machineId/run", machine, "get:Run")
|
||||||
beego.Router("/api/machines/?:machineId/top", machine, "get:Top")
|
web.Router("/api/machines/?:machineId/top", machine, "get:Top")
|
||||||
beego.Router("/api/machines/?:machineId/sysinfo", machine, "get:SysInfo")
|
web.Router("/api/machines/?:machineId/sysinfo", machine, "get:SysInfo")
|
||||||
beego.Router("/api/machines/?:machineId/process", machine, "get:GetProcessByName")
|
web.Router("/api/machines/?:machineId/process", machine, "get:GetProcessByName")
|
||||||
//beego.Router("/machines/?:machineId/ws", machine, "get:WsSSH")
|
web.Router("/api/machines/?:machineId/terminal", machine, "get:WsSSH")
|
||||||
|
|
||||||
|
web.Include(&controllers.DbController{})
|
||||||
|
// db := &controllers.DbController{}
|
||||||
|
// web.Router("/api/dbs", db, "get:Dbs")
|
||||||
|
// web.Router("/api/db/?:dbId/select", db, "get:SelectData")
|
||||||
|
// web.Router("/api/db/?:dbId/t-metadata", db, "get:TableMA")
|
||||||
|
// web.Router("/api/db/?:dbId/c-metadata", db, "get:ColumnMA")
|
||||||
|
// web.Router("/api/db/?:dbId/hint-tables", db, "get:HintTables")
|
||||||
|
// web.Router("/api/db/?:dbId/sql", db, "post:SaveSql")
|
||||||
|
// web.Router("/api/db/?:dbId/sql", db, "get:GetSql")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package scheduler
|
package scheduler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/siddontang/go/log"
|
"mayfly-go/base/model"
|
||||||
"mayfly-go/base"
|
|
||||||
"mayfly-go/base/utils"
|
"mayfly-go/base/utils"
|
||||||
"mayfly-go/machine"
|
"mayfly-go/machine"
|
||||||
"mayfly-go/models"
|
"mayfly-go/models"
|
||||||
|
|
||||||
|
"github.com/siddontang/go/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -17,11 +18,16 @@ func SaveMachineMonitor() {
|
|||||||
for _, m := range *models.GetNeedMonitorMachine() {
|
for _, m := range *models.GetNeedMonitorMachine() {
|
||||||
m := m
|
m := m
|
||||||
go func() {
|
go func() {
|
||||||
mm := machine.GetMonitorInfo(machine.GetCli(uint64(utils.GetInt4Map(m, "id"))))
|
cli, err := machine.GetCli(uint64(utils.GetInt4Map(m, "id")))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("获取客户端失败:", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mm := cli.GetMonitorInfo()
|
||||||
if mm != nil {
|
if mm != nil {
|
||||||
err := base.Insert(mm)
|
_, err := model.Insert(mm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("保存机器监控信息失败: %s", err.Error())
|
log.Error("保存机器监控信息失败: ", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package scheduler
|
package scheduler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"mayfly-go/base/model"
|
||||||
|
|
||||||
"github.com/robfig/cron/v3"
|
"github.com/robfig/cron/v3"
|
||||||
"mayfly-go/base"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var c = cron.New()
|
var c = cron.New()
|
||||||
@@ -22,7 +23,7 @@ func GetCron() *cron.Cron {
|
|||||||
func AddFun(spec string, cmd func()) cron.EntryID {
|
func AddFun(spec string, cmd func()) cron.EntryID {
|
||||||
id, err := c.AddFunc(spec, cmd)
|
id, err := c.AddFunc(spec, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(base.NewBizErr("添加任务失败:" + err.Error()))
|
panic(model.NewBizErr("添加任务失败:" + err.Error()))
|
||||||
}
|
}
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
package test
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "mayfly-go/routers"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego"
|
|
||||||
. "github.com/smartystreets/goconvey/convey"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
_, file, _, _ := runtime.Caller(0)
|
|
||||||
apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator))))
|
|
||||||
beego.TestBeegoInit(apppath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestBeego is a sample to run an endpoint test
|
|
||||||
func TestBeego(t *testing.T) {
|
|
||||||
r, _ := http.NewRequest("GET", "/", nil)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
beego.BeeApp.Handlers.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
beego.Trace("testing", "TestBeego", "Code[%d]\n%s", w.Code, w.Body.String())
|
|
||||||
|
|
||||||
Convey("Subject: Test Station Endpoint\n", t, func() {
|
|
||||||
Convey("Status Code Should Be 200", func() {
|
|
||||||
So(w.Code, ShouldEqual, 200)
|
|
||||||
})
|
|
||||||
Convey("The Result Should Not Be Empty", func() {
|
|
||||||
So(w.Body.Len(), ShouldBeGreaterThan, 0)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user