diff --git a/devops/__debug_bin b/devops/__debug_bin index ffffc6c5..ae733d84 100755 Binary files a/devops/__debug_bin and b/devops/__debug_bin differ diff --git a/devops/apis/account.go b/devops/apis/account.go index 8726dab2..6a8d9bbc 100644 --- a/devops/apis/account.go +++ b/devops/apis/account.go @@ -7,7 +7,6 @@ import ( "mayfly-go/devops/apis/form" "mayfly-go/devops/application" "mayfly-go/devops/domain/entity" - "mayfly-go/devops/models" ) type Account struct { @@ -30,5 +29,5 @@ func (a *Account) Login(rc *ctx.ReqCtx) { // @router /accounts [get] func (a *Account) Accounts(rc *ctx.ReqCtx) { - rc.ResData = models.ListAccount(ginx.GetPageParam(rc.GinCtx)) + // rc.ResData = models.ListAccount(ginx.GetPageParam(rc.GinCtx)) } diff --git a/devops/apis/db.go b/devops/apis/db.go index bbab5178..7407d6ed 100644 --- a/devops/apis/db.go +++ b/devops/apis/db.go @@ -10,7 +10,6 @@ import ( "mayfly-go/devops/apis/vo" "mayfly-go/devops/application" "mayfly-go/devops/domain/entity" - "mayfly-go/devops/models" "strconv" "strings" @@ -104,11 +103,11 @@ func (d *Db) SaveSql(rc *ctx.ReqCtx) { dbId := GetDbId(g) // 判断dbId是否存在 - err := model.GetById(new(models.Db), dbId) + err := model.GetById(new(entity.Db), dbId) biz.ErrIsNil(err, "该数据库信息不存在") // 获取用于是否有该dbsql的保存记录,有则更改,否则新增 - dbSql := &models.DbSql{Type: dbSqlForm.Type, DbId: dbId} + dbSql := &entity.DbSql{Type: dbSqlForm.Type, DbId: dbId} dbSql.CreatorId = account.Id e := model.GetBy(dbSql) @@ -125,7 +124,7 @@ func (d *Db) SaveSql(rc *ctx.ReqCtx) { // @router /api/db/:dbId/sql [get] func (d *Db) GetSql(rc *ctx.ReqCtx) { // 获取用于是否有该dbsql的保存记录,有则更改,否则新增 - dbSql := &models.DbSql{Type: 1, DbId: GetDbId(rc.GinCtx)} + dbSql := &entity.DbSql{Type: 1, DbId: GetDbId(rc.GinCtx)} dbSql.CreatorId = rc.LoginAccount.Id e := model.GetBy(dbSql) if e != nil { diff --git a/devops/apis/machine.go b/devops/apis/machine.go index 8eeda07a..4c28bac6 100644 --- a/devops/apis/machine.go +++ b/devops/apis/machine.go @@ -40,7 +40,6 @@ func (m *Machine) SaveMachine(rc *ctx.ReqCtx) { entity := new(entity.Machine) utils.Copy(entity, machineForm) - biz.ErrIsNil(machine.TestConn(entity), "无法连接") entity.SetBaseInfo(rc.LoginAccount) m.MachineApp.Save(entity) diff --git a/devops/apis/machine_file.go b/devops/apis/machine_file.go index 41bbb660..5bbd37a5 100644 --- a/devops/apis/machine_file.go +++ b/devops/apis/machine_file.go @@ -2,7 +2,6 @@ package apis import ( "fmt" - "io" "io/fs" "io/ioutil" "mayfly-go/base/biz" @@ -13,7 +12,6 @@ import ( "mayfly-go/devops/apis/vo" "mayfly-go/devops/application" "mayfly-go/devops/domain/entity" - "os" "strconv" "strings" @@ -46,7 +44,6 @@ func (m *MachineFile) SaveMachineFiles(rc *ctx.ReqCtx) { entity := new(entity.MachineFile) utils.Copy(entity, fileForm) - biz.NotNil(m.MachineApp.GetById(entity.MachineId, "Id"), "机器不存在") entity.SetBaseInfo(rc.LoginAccount) m.MachineFileApp.Save(entity) @@ -63,28 +60,14 @@ func (m *MachineFile) DeleteFile(rc *ctx.ReqCtx) { func (m *MachineFile) ReadFileContent(rc *ctx.ReqCtx) { g := rc.GinCtx fid := GetMachineFileId(g) - machineId := GetMachineId(g) readPath := g.Query("path") readType := g.Query("type") - readPath = m.checkAndReturnPath(machineId, 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(), "该文件为目录") + dataByte, fileInfo := m.MachineFileApp.ReadFile(fid, readPath) // 如果是读取文件内容,则校验文件大小 if readType != "1" { 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) // 如果读取类型为下载,则下载文件,否则获取文件内容 @@ -100,17 +83,12 @@ func (m *MachineFile) ReadFileContent(rc *ctx.ReqCtx) { func (m *MachineFile) GetDirEntry(rc *ctx.ReqCtx) { g := rc.GinCtx fid := GetMachineFileId(g) - machineId := GetMachineId(g) readPath := g.Query("path") - readPath = m.checkAndReturnPath(machineId, fid, readPath) if !strings.HasSuffix(readPath, "/") { readPath = readPath + "/" } - - sftpCli := m.MachineApp.GetCli(machineId).GetSftpCli() - fis, err := sftpCli.ReadDir(readPath) - biz.ErrIsNilAppendErr(err, "读取目录失败: %s") + fis := m.MachineFileApp.ReadDir(fid, readPath) fisVO := make([]vo.MachineFileInfo, 0) for _, fi := range fis { fisVO = append(fisVO, vo.MachineFileInfo{ @@ -127,21 +105,12 @@ func (m *MachineFile) GetDirEntry(rc *ctx.ReqCtx) { func (m *MachineFile) WriteFileContent(rc *ctx.ReqCtx) { g := rc.GinCtx fid := GetMachineFileId(g) - machineId := GetMachineId(g) form := new(form.MachineFileUpdateForm) ginx.BindJsonAndValid(g, form) path := form.Path - path = m.checkAndReturnPath(machineId, fid, path) - sftpCli := m.MachineApp.GetCli(machineId).GetSftpCli() - 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)) + m.MachineFileApp.WriteFileContent(fid, path, []byte(form.Content)) 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) { g := rc.GinCtx fid := GetMachineFileId(g) - mid := GetMachineId(g) path := g.PostForm("path") fileheader, err := g.FormFile("file") 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() bytes, err := ioutil.ReadAll(file) - createfile.Write(bytes) + m.MachineFileApp.UploadFile(fid, path, fileheader.Filename, bytes) 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) { g := rc.GinCtx fid := GetMachineFileId(g) - mid := GetMachineId(g) + // mid := GetMachineId(g) path := g.Query("path") - path = m.checkAndReturnPath(mid, 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") + m.MachineFileApp.RemoveFile(fid, 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 { if fm.IsDir() { return dir diff --git a/devops/application/machine_app.go b/devops/application/machine_app.go index d9e16146..c4409c10 100644 --- a/devops/application/machine_app.go +++ b/devops/application/machine_app.go @@ -38,6 +38,7 @@ func (m *machineApp) GetMachineList(condition *entity.Machine, pageParam *model. // 根据条件获取机器信息 func (m *machineApp) Save(entity *entity.Machine) { + biz.ErrIsNil(machine.TestConn(entity), "该机器无法连接") if entity.Id != 0 { m.machineRepo.UpdateById(entity) } else { diff --git a/devops/application/machine_file_app.go b/devops/application/machine_file_app.go index 6bebc44f..2f30d7eb 100644 --- a/devops/application/machine_file_app.go +++ b/devops/application/machine_file_app.go @@ -1,11 +1,18 @@ package application import ( + "io" + "io/fs" + "io/ioutil" "mayfly-go/base/biz" "mayfly-go/base/model" "mayfly-go/devops/domain/entity" "mayfly-go/devops/domain/repository" "mayfly-go/devops/infrastructure/persistence" + "os" + "strings" + + "github.com/pkg/sftp" ) type IMachineFile interface { @@ -21,6 +28,23 @@ type IMachineFile interface { Save(entity *entity.MachineFile) 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 { @@ -48,7 +72,7 @@ func (m *machineFileApp) GetById(id uint64, cols ...string) *entity.MachineFile return m.machineFileRepo.GetById(id, cols...) } -// 保存机器脚本 +// 保存机器文件配置 func (m *machineFileApp) Save(entity *entity.MachineFile) { 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) { 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 + } +} diff --git a/devops/infrastructure/machine/machine_test.go b/devops/infrastructure/machine/machine_test.go index 8fe618f2..7042b882 100644 --- a/devops/infrastructure/machine/machine_test.go +++ b/devops/infrastructure/machine/machine_test.go @@ -9,7 +9,7 @@ import ( func TestSSH(t *testing.T) { //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") ////fmt.Printf("%v\n%v", output, err) //err := cli.RunTerminal("tail -f /usr/local/java/logs/eatlife-info.log", os.Stdout, os.Stdin) diff --git a/devops/infrastructure/machine/shell.go b/devops/infrastructure/machine/shell.go index 56b71c7e..d75194ba 100644 --- a/devops/infrastructure/machine/shell.go +++ b/devops/infrastructure/machine/shell.go @@ -5,7 +5,7 @@ import ( "mayfly-go/base/biz" "mayfly-go/base/global" "mayfly-go/base/utils" - "mayfly-go/devops/models" + "mayfly-go/devops/domain/entity" "time" ) @@ -24,8 +24,8 @@ func (c *Cli) GetSystemInfo() (*string, error) { return c.Run(getShellContent("system_info")) } -func (c *Cli) GetMonitorInfo() *models.MachineMonitor { - mm := new(models.MachineMonitor) +func (c *Cli) GetMonitorInfo() *entity.MachineMonitor { + mm := new(entity.MachineMonitor) res, _ := c.Run(getShellContent("monitor")) if res == nil { return nil diff --git a/devops/models/account.go b/devops/models/account.go deleted file mode 100644 index 28402730..00000000 --- a/devops/models/account.go +++ /dev/null @@ -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) -} diff --git a/devops/models/db.go b/devops/models/db.go deleted file mode 100644 index d44bccb5..00000000 --- a/devops/models/db.go +++ /dev/null @@ -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"` -} diff --git a/devops/models/db_sql.go b/devops/models/db_sql.go deleted file mode 100644 index bb5fcdab..00000000 --- a/devops/models/db_sql.go +++ /dev/null @@ -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"` -} diff --git a/devops/models/machine.go b/devops/models/machine.go deleted file mode 100644 index 4f5d9923..00000000 --- a/devops/models/machine.go +++ /dev/null @@ -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"` -} diff --git a/devops/models/machine_monitor.go b/devops/models/machine_monitor.go deleted file mode 100644 index dd24aff6..00000000 --- a/devops/models/machine_monitor.go +++ /dev/null @@ -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"` -} diff --git a/devops/models/machine_script.go b/devops/models/machine_script.go deleted file mode 100644 index bb2a08a8..00000000 --- a/devops/models/machine_script.go +++ /dev/null @@ -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"` -} diff --git a/devops/routers/machine_file.go b/devops/routers/machine_file.go index a75018e8..b2dc487f 100644 --- a/devops/routers/machine_file.go +++ b/devops/routers/machine_file.go @@ -32,7 +32,7 @@ func InitMachineFileRouter(router *gin.RouterGroup) { getContent := ctx.NewLogInfo("读取机器文件内容") 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) }) diff --git a/devops/service/Db.go b/devops/service/Db.go deleted file mode 100644 index fc94c4d7..00000000 --- a/devops/service/Db.go +++ /dev/null @@ -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 -} diff --git a/devops/service/machine.go b/devops/service/machine.go deleted file mode 100644 index 45c61474..00000000 --- a/devops/service/machine.go +++ /dev/null @@ -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") -} diff --git a/devops/service/service.go b/devops/service/service.go deleted file mode 100644 index f236e5a6..00000000 --- a/devops/service/service.go +++ /dev/null @@ -1,6 +0,0 @@ -package service - -var ( - Machine = new(machineService) - Db = new(dbService) -)