feat: 代码结构优化

This commit is contained in:
meilin.huang
2021-05-08 20:50:34 +08:00
parent 4660757de5
commit af0d51293e
19 changed files with 134 additions and 238 deletions

Binary file not shown.

View File

@@ -7,7 +7,6 @@ import (
"mayfly-go/devops/apis/form" "mayfly-go/devops/apis/form"
"mayfly-go/devops/application" "mayfly-go/devops/application"
"mayfly-go/devops/domain/entity" "mayfly-go/devops/domain/entity"
"mayfly-go/devops/models"
) )
type Account struct { type Account struct {
@@ -30,5 +29,5 @@ func (a *Account) Login(rc *ctx.ReqCtx) {
// @router /accounts [get] // @router /accounts [get]
func (a *Account) Accounts(rc *ctx.ReqCtx) { func (a *Account) Accounts(rc *ctx.ReqCtx) {
rc.ResData = models.ListAccount(ginx.GetPageParam(rc.GinCtx)) // rc.ResData = models.ListAccount(ginx.GetPageParam(rc.GinCtx))
} }

View File

@@ -10,7 +10,6 @@ import (
"mayfly-go/devops/apis/vo" "mayfly-go/devops/apis/vo"
"mayfly-go/devops/application" "mayfly-go/devops/application"
"mayfly-go/devops/domain/entity" "mayfly-go/devops/domain/entity"
"mayfly-go/devops/models"
"strconv" "strconv"
"strings" "strings"
@@ -104,11 +103,11 @@ func (d *Db) SaveSql(rc *ctx.ReqCtx) {
dbId := GetDbId(g) dbId := GetDbId(g)
// 判断dbId是否存在 // 判断dbId是否存在
err := model.GetById(new(models.Db), dbId) err := model.GetById(new(entity.Db), dbId)
biz.ErrIsNil(err, "该数据库信息不存在") biz.ErrIsNil(err, "该数据库信息不存在")
// 获取用于是否有该dbsql的保存记录有则更改否则新增 // 获取用于是否有该dbsql的保存记录有则更改否则新增
dbSql := &models.DbSql{Type: dbSqlForm.Type, DbId: dbId} dbSql := &entity.DbSql{Type: dbSqlForm.Type, DbId: dbId}
dbSql.CreatorId = account.Id dbSql.CreatorId = account.Id
e := model.GetBy(dbSql) e := model.GetBy(dbSql)
@@ -125,7 +124,7 @@ func (d *Db) SaveSql(rc *ctx.ReqCtx) {
// @router /api/db/:dbId/sql [get] // @router /api/db/:dbId/sql [get]
func (d *Db) GetSql(rc *ctx.ReqCtx) { func (d *Db) GetSql(rc *ctx.ReqCtx) {
// 获取用于是否有该dbsql的保存记录有则更改否则新增 // 获取用于是否有该dbsql的保存记录有则更改否则新增
dbSql := &models.DbSql{Type: 1, DbId: GetDbId(rc.GinCtx)} dbSql := &entity.DbSql{Type: 1, DbId: GetDbId(rc.GinCtx)}
dbSql.CreatorId = rc.LoginAccount.Id dbSql.CreatorId = rc.LoginAccount.Id
e := model.GetBy(dbSql) e := model.GetBy(dbSql)
if e != nil { if e != nil {

View File

@@ -40,7 +40,6 @@ func (m *Machine) SaveMachine(rc *ctx.ReqCtx) {
entity := new(entity.Machine) entity := new(entity.Machine)
utils.Copy(entity, machineForm) utils.Copy(entity, machineForm)
biz.ErrIsNil(machine.TestConn(entity), "无法连接")
entity.SetBaseInfo(rc.LoginAccount) entity.SetBaseInfo(rc.LoginAccount)
m.MachineApp.Save(entity) m.MachineApp.Save(entity)

View File

@@ -2,7 +2,6 @@ package apis
import ( import (
"fmt" "fmt"
"io"
"io/fs" "io/fs"
"io/ioutil" "io/ioutil"
"mayfly-go/base/biz" "mayfly-go/base/biz"
@@ -13,7 +12,6 @@ import (
"mayfly-go/devops/apis/vo" "mayfly-go/devops/apis/vo"
"mayfly-go/devops/application" "mayfly-go/devops/application"
"mayfly-go/devops/domain/entity" "mayfly-go/devops/domain/entity"
"os"
"strconv" "strconv"
"strings" "strings"
@@ -46,7 +44,6 @@ func (m *MachineFile) SaveMachineFiles(rc *ctx.ReqCtx) {
entity := new(entity.MachineFile) entity := new(entity.MachineFile)
utils.Copy(entity, fileForm) utils.Copy(entity, fileForm)
biz.NotNil(m.MachineApp.GetById(entity.MachineId, "Id"), "机器不存在")
entity.SetBaseInfo(rc.LoginAccount) entity.SetBaseInfo(rc.LoginAccount)
m.MachineFileApp.Save(entity) m.MachineFileApp.Save(entity)
@@ -63,28 +60,14 @@ func (m *MachineFile) DeleteFile(rc *ctx.ReqCtx) {
func (m *MachineFile) ReadFileContent(rc *ctx.ReqCtx) { func (m *MachineFile) ReadFileContent(rc *ctx.ReqCtx) {
g := rc.GinCtx g := rc.GinCtx
fid := GetMachineFileId(g) fid := GetMachineFileId(g)
machineId := GetMachineId(g)
readPath := g.Query("path") readPath := g.Query("path")
readType := g.Query("type") readType := g.Query("type")
readPath = m.checkAndReturnPath(machineId, fid, readPath) dataByte, fileInfo := m.MachineFileApp.ReadFile(fid, readPath)
sftpCli := m.MachineApp.GetCli(machineId).GetSftpCli()
// 读取文件内容
fc, err := sftpCli.Open(readPath)
biz.ErrIsNilAppendErr(err, "打开文件失败:%s")
defer fc.Close()
fileInfo, _ := fc.Stat()
biz.IsTrue(!fileInfo.IsDir(), "该文件为目录")
// 如果是读取文件内容,则校验文件大小 // 如果是读取文件内容,则校验文件大小
if readType != "1" { if readType != "1" {
biz.IsTrue(fileInfo.Size() < max_read_size, "文件超过5m请使用下载查看") biz.IsTrue(fileInfo.Size() < max_read_size, "文件超过5m请使用下载查看")
} }
dataByte, err := ioutil.ReadAll(fc)
if err != nil && err != io.EOF {
panic(biz.NewBizErr("读取文件内容失败"))
}
rc.ReqParam = fmt.Sprintf("path: %s", readPath) rc.ReqParam = fmt.Sprintf("path: %s", readPath)
// 如果读取类型为下载,则下载文件,否则获取文件内容 // 如果读取类型为下载,则下载文件,否则获取文件内容
@@ -100,17 +83,12 @@ func (m *MachineFile) ReadFileContent(rc *ctx.ReqCtx) {
func (m *MachineFile) GetDirEntry(rc *ctx.ReqCtx) { func (m *MachineFile) GetDirEntry(rc *ctx.ReqCtx) {
g := rc.GinCtx g := rc.GinCtx
fid := GetMachineFileId(g) fid := GetMachineFileId(g)
machineId := GetMachineId(g)
readPath := g.Query("path") readPath := g.Query("path")
readPath = m.checkAndReturnPath(machineId, fid, readPath)
if !strings.HasSuffix(readPath, "/") { if !strings.HasSuffix(readPath, "/") {
readPath = readPath + "/" readPath = readPath + "/"
} }
fis := m.MachineFileApp.ReadDir(fid, readPath)
sftpCli := m.MachineApp.GetCli(machineId).GetSftpCli()
fis, err := sftpCli.ReadDir(readPath)
biz.ErrIsNilAppendErr(err, "读取目录失败: %s")
fisVO := make([]vo.MachineFileInfo, 0) fisVO := make([]vo.MachineFileInfo, 0)
for _, fi := range fis { for _, fi := range fis {
fisVO = append(fisVO, vo.MachineFileInfo{ fisVO = append(fisVO, vo.MachineFileInfo{
@@ -127,21 +105,12 @@ func (m *MachineFile) GetDirEntry(rc *ctx.ReqCtx) {
func (m *MachineFile) WriteFileContent(rc *ctx.ReqCtx) { func (m *MachineFile) WriteFileContent(rc *ctx.ReqCtx) {
g := rc.GinCtx g := rc.GinCtx
fid := GetMachineFileId(g) fid := GetMachineFileId(g)
machineId := GetMachineId(g)
form := new(form.MachineFileUpdateForm) form := new(form.MachineFileUpdateForm)
ginx.BindJsonAndValid(g, form) ginx.BindJsonAndValid(g, form)
path := form.Path path := form.Path
path = m.checkAndReturnPath(machineId, fid, path)
sftpCli := m.MachineApp.GetCli(machineId).GetSftpCli() m.MachineFileApp.WriteFileContent(fid, path, []byte(form.Content))
f, err := sftpCli.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE|os.O_RDWR)
biz.ErrIsNilAppendErr(err, "打开文件失败: %s")
defer f.Close()
fi, _ := f.Stat()
biz.IsTrue(!fi.IsDir(), "该路径不是文件")
f.Write([]byte(form.Content))
rc.ReqParam = fmt.Sprintf("path: %s", path) rc.ReqParam = fmt.Sprintf("path: %s", path)
} }
@@ -149,24 +118,13 @@ func (m *MachineFile) WriteFileContent(rc *ctx.ReqCtx) {
func (m *MachineFile) UploadFile(rc *ctx.ReqCtx) { func (m *MachineFile) UploadFile(rc *ctx.ReqCtx) {
g := rc.GinCtx g := rc.GinCtx
fid := GetMachineFileId(g) fid := GetMachineFileId(g)
mid := GetMachineId(g)
path := g.PostForm("path") path := g.PostForm("path")
fileheader, err := g.FormFile("file") fileheader, err := g.FormFile("file")
biz.ErrIsNilAppendErr(err, "读取文件失败: %s") biz.ErrIsNilAppendErr(err, "读取文件失败: %s")
path = m.checkAndReturnPath(mid, fid, path)
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
sftpCli := m.MachineApp.GetCli(mid).GetSftpCli()
createfile, err := sftpCli.Create(path + fileheader.Filename)
biz.ErrIsNilAppendErr(err, "创建文件失败: %s")
defer createfile.Close()
file, _ := fileheader.Open() file, _ := fileheader.Open()
bytes, err := ioutil.ReadAll(file) bytes, err := ioutil.ReadAll(file)
createfile.Write(bytes) m.MachineFileApp.UploadFile(fid, path, fileheader.Filename, bytes)
rc.ReqParam = fmt.Sprintf("path: %s", path) rc.ReqParam = fmt.Sprintf("path: %s", path)
} }
@@ -174,39 +132,14 @@ func (m *MachineFile) UploadFile(rc *ctx.ReqCtx) {
func (m *MachineFile) RemoveFile(rc *ctx.ReqCtx) { func (m *MachineFile) RemoveFile(rc *ctx.ReqCtx) {
g := rc.GinCtx g := rc.GinCtx
fid := GetMachineFileId(g) fid := GetMachineFileId(g)
mid := GetMachineId(g) // mid := GetMachineId(g)
path := g.Query("path") path := g.Query("path")
path = m.checkAndReturnPath(mid, fid, path) m.MachineFileApp.RemoveFile(fid, path)
sftpCli := m.MachineApp.GetCli(mid).GetSftpCli()
file, err := sftpCli.Open(path)
biz.ErrIsNilAppendErr(err, "打开文件失败: %s")
fi, err := file.Stat()
if fi.IsDir() {
err = sftpCli.RemoveDirectory(path)
} else {
err = sftpCli.Remove(path)
}
biz.ErrIsNilAppendErr(err, "删除文件失败: %s")
rc.ReqParam = fmt.Sprintf("path: %s", path) rc.ReqParam = fmt.Sprintf("path: %s", path)
} }
// 校验并返回实际可访问的文件path
func (m *MachineFile) checkAndReturnPath(mid, fid uint64, inputPath string) string {
biz.IsTrue(fid != 0, "文件id不能为空")
mf := m.MachineFileApp.GetById(uint64(fid))
biz.NotNil(mf, "文件不存在")
biz.IsEquals(mid, mf.MachineId, "机器id与文件id不匹配")
if inputPath != "" {
biz.IsTrue(strings.HasPrefix(inputPath, mf.Path), "无权访问该目录或文件")
return inputPath
} else {
return mf.Path
}
}
func getFileType(fm fs.FileMode) string { func getFileType(fm fs.FileMode) string {
if fm.IsDir() { if fm.IsDir() {
return dir return dir

View File

@@ -38,6 +38,7 @@ func (m *machineApp) GetMachineList(condition *entity.Machine, pageParam *model.
// 根据条件获取机器信息 // 根据条件获取机器信息
func (m *machineApp) Save(entity *entity.Machine) { func (m *machineApp) Save(entity *entity.Machine) {
biz.ErrIsNil(machine.TestConn(entity), "该机器无法连接")
if entity.Id != 0 { if entity.Id != 0 {
m.machineRepo.UpdateById(entity) m.machineRepo.UpdateById(entity)
} else { } else {

View File

@@ -1,11 +1,18 @@
package application package application
import ( import (
"io"
"io/fs"
"io/ioutil"
"mayfly-go/base/biz" "mayfly-go/base/biz"
"mayfly-go/base/model" "mayfly-go/base/model"
"mayfly-go/devops/domain/entity" "mayfly-go/devops/domain/entity"
"mayfly-go/devops/domain/repository" "mayfly-go/devops/domain/repository"
"mayfly-go/devops/infrastructure/persistence" "mayfly-go/devops/infrastructure/persistence"
"os"
"strings"
"github.com/pkg/sftp"
) )
type IMachineFile interface { type IMachineFile interface {
@@ -21,6 +28,23 @@ type IMachineFile interface {
Save(entity *entity.MachineFile) Save(entity *entity.MachineFile)
Delete(id uint64) Delete(id uint64)
/** sftp 相关操作 **/
// 读取目录
ReadDir(fid uint64, path string) []fs.FileInfo
// 读取文件内容
ReadFile(fileId uint64, path string) ([]byte, fs.FileInfo)
// 写文件
WriteFileContent(fileId uint64, path string, content []byte)
// 文件上传
UploadFile(fileId uint64, path, filename string, content []byte)
// 移除文件
RemoveFile(fileId uint64, path string)
} }
type machineFileApp struct { type machineFileApp struct {
@@ -48,7 +72,7 @@ func (m *machineFileApp) GetById(id uint64, cols ...string) *entity.MachineFile
return m.machineFileRepo.GetById(id, cols...) return m.machineFileRepo.GetById(id, cols...)
} }
// 保存机器脚本 // 保存机器文件配置
func (m *machineFileApp) Save(entity *entity.MachineFile) { func (m *machineFileApp) Save(entity *entity.MachineFile) {
biz.NotNil(m.machineFileRepo.GetById(entity.MachineId, "Name"), "该机器不存在") biz.NotNil(m.machineFileRepo.GetById(entity.MachineId, "Name"), "该机器不存在")
@@ -63,3 +87,96 @@ func (m *machineFileApp) Save(entity *entity.MachineFile) {
func (m *machineFileApp) Delete(id uint64) { func (m *machineFileApp) Delete(id uint64) {
m.machineFileRepo.Delete(id) m.machineFileRepo.Delete(id)
} }
func (m *machineFileApp) ReadDir(fid uint64, path string) []fs.FileInfo {
path, machineId := m.checkAndReturnPathMid(fid, path)
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
sftpCli := m.getSftpCli(machineId)
fis, err := sftpCli.ReadDir(path)
biz.ErrIsNilAppendErr(err, "读取目录失败: %s")
return fis
}
func (m *machineFileApp) ReadFile(fileId uint64, path string) ([]byte, fs.FileInfo) {
path, machineId := m.checkAndReturnPathMid(fileId, path)
sftpCli := m.getSftpCli(machineId)
// 读取文件内容
fc, err := sftpCli.Open(path)
biz.ErrIsNilAppendErr(err, "打开文件失败:%s")
defer fc.Close()
fileInfo, _ := fc.Stat()
biz.IsTrue(!fileInfo.IsDir(), "该文件为目录")
dataByte, err := ioutil.ReadAll(fc)
if err != nil && err != io.EOF {
panic(biz.NewBizErr("读取文件内容失败"))
}
return dataByte, fileInfo
}
// 写文件内容
func (m *machineFileApp) WriteFileContent(fileId uint64, path string, content []byte) {
_, machineId := m.checkAndReturnPathMid(fileId, path)
sftpCli := m.getSftpCli(machineId)
f, err := sftpCli.OpenFile(path, os.O_WRONLY|os.O_TRUNC|os.O_CREATE|os.O_RDWR)
biz.ErrIsNilAppendErr(err, "打开文件失败: %s")
defer f.Close()
fi, _ := f.Stat()
biz.IsTrue(!fi.IsDir(), "该路径不是文件")
f.Write(content)
}
// 上传文件
func (m *machineFileApp) UploadFile(fileId uint64, path, filename string, content []byte) {
path, machineId := m.checkAndReturnPathMid(fileId, path)
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
sftpCli := m.getSftpCli(machineId)
createfile, err := sftpCli.Create(path + filename)
biz.ErrIsNilAppendErr(err, "创建文件失败: %s")
defer createfile.Close()
createfile.Write(content)
}
// 删除文件
func (m *machineFileApp) RemoveFile(fileId uint64, path string) {
path, machineId := m.checkAndReturnPathMid(fileId, path)
sftpCli := m.getSftpCli(machineId)
file, err := sftpCli.Open(path)
biz.ErrIsNilAppendErr(err, "打开文件失败: %s")
fi, err := file.Stat()
if fi.IsDir() {
err = sftpCli.RemoveDirectory(path)
} else {
err = sftpCli.Remove(path)
}
biz.ErrIsNilAppendErr(err, "删除文件失败: %s")
}
// 获取sftp client
func (m *machineFileApp) getSftpCli(machineId uint64) *sftp.Client {
return Machine.GetCli(machineId).GetSftpCli()
}
// 校验并返回实际可访问的文件path
func (m *machineFileApp) checkAndReturnPathMid(fid uint64, inputPath string) (string, uint64) {
biz.IsTrue(fid != 0, "文件id不能为空")
mf := m.GetById(uint64(fid))
biz.NotNil(mf, "文件不存在")
if inputPath != "" {
// 接口传入的地址需为配置路径的子路径
biz.IsTrue(strings.HasPrefix(inputPath, mf.Path), "无权访问该目录或文件")
return inputPath, mf.MachineId
} else {
return mf.Path, mf.MachineId
}
}

View File

@@ -9,7 +9,7 @@ import (
func TestSSH(t *testing.T) { func TestSSH(t *testing.T) {
//ssh.ListenAndServe("148.70.36.197") //ssh.ListenAndServe("148.70.36.197")
//cli := New("148.70.36.197", "root", "gea&630_..91mn#", 22) //cli := New("148.70.36.197", "root", "g..91mn#", 22)
////output, err := cli.Run("free -h") ////output, err := cli.Run("free -h")
////fmt.Printf("%v\n%v", output, err) ////fmt.Printf("%v\n%v", output, err)
//err := cli.RunTerminal("tail -f /usr/local/java/logs/eatlife-info.log", os.Stdout, os.Stdin) //err := cli.RunTerminal("tail -f /usr/local/java/logs/eatlife-info.log", os.Stdout, os.Stdin)

View File

@@ -5,7 +5,7 @@ import (
"mayfly-go/base/biz" "mayfly-go/base/biz"
"mayfly-go/base/global" "mayfly-go/base/global"
"mayfly-go/base/utils" "mayfly-go/base/utils"
"mayfly-go/devops/models" "mayfly-go/devops/domain/entity"
"time" "time"
) )
@@ -24,8 +24,8 @@ func (c *Cli) GetSystemInfo() (*string, error) {
return c.Run(getShellContent("system_info")) return c.Run(getShellContent("system_info"))
} }
func (c *Cli) GetMonitorInfo() *models.MachineMonitor { func (c *Cli) GetMonitorInfo() *entity.MachineMonitor {
mm := new(models.MachineMonitor) mm := new(entity.MachineMonitor)
res, _ := c.Run(getShellContent("monitor")) res, _ := c.Run(getShellContent("monitor"))
if res == nil { if res == nil {
return nil return nil

View File

@@ -1,20 +0,0 @@
package models
import (
"mayfly-go/base/model"
"mayfly-go/devops/apis/vo"
)
type Account struct {
model.Model
Username string `json:"username"`
Password string `json:"-"`
Status int8 `json:"status"`
}
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'" +
" FROM t_account a LEFT JOIN t_role r ON a.id = r.account_id"
return model.GetPageBySql(sql, param, new([]vo.AccountVO), args)
}

View File

@@ -1,18 +0,0 @@
package models
import (
"mayfly-go/base/model"
)
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"`
Password string `orm:"column(password)" json:"-"`
Database string `orm:"column(database)" json:"database"`
}

View File

@@ -1,13 +0,0 @@
package models
import (
"mayfly-go/base/model"
)
type DbSql struct {
model.Model `orm:"-"`
DbId uint64 `json:"db_id"`
Type int `json:"type"` // 类型
Sql string `json:"sql"`
}

View File

@@ -1,17 +0,0 @@
package models
import (
"mayfly-go/base/model"
)
type Machine struct {
model.Model
Name string `json:"name"`
// IP地址
Ip string `json:"ip"`
// 用户名
Username string `json:"username"`
Password string `json:"-"`
// 端口号
Port int `json:"port"`
}

View File

@@ -1,14 +0,0 @@
package models
import (
"time"
)
type MachineMonitor struct {
Id uint64 `json:"id"`
MachineId uint64 `json:"machineId"`
CpuRate float32 `json:"cpuRate"`
MemRate float32 `json:"memRate"`
SysLoad string `json:"sysLoad"`
CreateTime time.Time `json:"createTime"`
}

View File

@@ -1,15 +0,0 @@
package models
import "mayfly-go/base/model"
type MachineScript struct {
model.Model
Name string `json:"name"`
// 机器id
MachineId uint64 `json:"machineId"`
Type int `json:"type"`
// 脚本内容
Description string `json:"description"`
// 脚本内容
Script string `json:"script"`
}

View File

@@ -32,7 +32,7 @@ func InitMachineFileRouter(router *gin.RouterGroup) {
getContent := ctx.NewLogInfo("读取机器文件内容") getContent := ctx.NewLogInfo("读取机器文件内容")
machineFile.GET(":machineId/files/:fileId/read", func(c *gin.Context) { machineFile.GET(":machineId/files/:fileId/read", func(c *gin.Context) {
rc := ctx.NewReqCtxWithGin(c).WithNeedToken(false).WithLog(getContent) rc := ctx.NewReqCtxWithGin(c).WithLog(getContent)
rc.Handle(mf.ReadFileContent) rc.Handle(mf.ReadFileContent)
}) })

View File

@@ -1,19 +0,0 @@
package service
import (
"mayfly-go/base/model"
"mayfly-go/devops/models"
)
type dbService struct {
}
func (d *dbService) GetDbById(id uint64) *models.Db {
db := new(models.Db)
db.Id = id
err := model.GetBy(db)
if err != nil {
return nil
}
return db
}

View File

@@ -1,30 +0,0 @@
package service
import (
"mayfly-go/base/model"
"mayfly-go/devops/apis/vo"
"mayfly-go/devops/models"
)
type machineService struct {
}
func (m *machineService) GetMachineById(id uint64) *models.Machine {
machine := new(models.Machine)
machine.Id = id
err := model.GetBy(machine)
if err != nil {
return nil
}
return machine
}
// 分页获取机器信息列表
func (m *machineService) GetMachineList(pageParam *model.PageParam) model.PageResult {
return model.GetPage(pageParam, new(models.Machine), new([]vo.MachineVO), "Id desc")
}
// 获取所有需要监控的机器信息列表
func (m *machineService) GetNeedMonitorMachine() []map[string]interface{} {
return model.GetListBySql("SELECT id FROM t_machine WHERE need_monitor = 1")
}

View File

@@ -1,6 +0,0 @@
package service
var (
Machine = new(machineService)
Db = new(dbService)
)