2020-08-04 14:28:25 +08:00
|
|
|
package controller
|
|
|
|
|
|
|
|
import (
|
2021-09-18 16:35:50 +08:00
|
|
|
"bytes"
|
2021-07-09 20:46:12 +08:00
|
|
|
"github.com/pkg/sftp"
|
2020-08-04 14:28:25 +08:00
|
|
|
"github.com/zhenorzz/goploy/core"
|
|
|
|
"github.com/zhenorzz/goploy/model"
|
|
|
|
"github.com/zhenorzz/goploy/utils"
|
2021-07-09 20:46:12 +08:00
|
|
|
"io"
|
2021-02-14 14:22:22 +08:00
|
|
|
"io/ioutil"
|
2021-09-18 16:35:50 +08:00
|
|
|
"os/exec"
|
2021-07-09 20:46:12 +08:00
|
|
|
"path"
|
|
|
|
"strconv"
|
2021-09-18 16:35:50 +08:00
|
|
|
"strings"
|
2020-08-04 14:28:25 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// Server struct
|
|
|
|
type Server Controller
|
|
|
|
|
2020-08-15 13:38:06 +08:00
|
|
|
// GetList -
|
2020-09-26 10:45:28 +08:00
|
|
|
func (Server) GetList(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
pagination, err := model.PaginationFrom(gp.URLQuery)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
serverList, err := model.Server{NamespaceID: gp.Namespace.ID}.GetList(pagination)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
Servers model.Servers `json:"list"`
|
|
|
|
}{Servers: serverList},
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
2020-08-15 13:38:06 +08:00
|
|
|
// GetTotal -
|
2020-09-26 10:45:28 +08:00
|
|
|
func (Server) GetTotal(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
total, err := model.Server{NamespaceID: gp.Namespace.ID}.GetTotal()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
Total int64 `json:"total"`
|
|
|
|
}{Total: total},
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
2020-08-15 13:38:06 +08:00
|
|
|
// GetOption -
|
2020-09-26 10:45:28 +08:00
|
|
|
func (Server) GetOption(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
serverList, err := model.Server{NamespaceID: gp.Namespace.ID}.GetAll()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
Servers model.Servers `json:"list"`
|
|
|
|
}{Servers: serverList},
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
2021-02-14 14:22:22 +08:00
|
|
|
// GetPublicKey -
|
|
|
|
func (Server) GetPublicKey(gp *core.Goploy) *core.Response {
|
|
|
|
path := gp.URLQuery.Get("path")
|
|
|
|
|
|
|
|
contentByte, err := ioutil.ReadFile(path + ".pub")
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
return &core.Response{
|
2021-06-22 19:59:39 +08:00
|
|
|
Data: struct {
|
|
|
|
Key string `json:"key"`
|
|
|
|
}{Key: string(contentByte)},
|
2021-02-14 14:22:22 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-15 13:38:06 +08:00
|
|
|
// Check server
|
2020-09-26 10:45:28 +08:00
|
|
|
func (Server) Check(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
type ReqData struct {
|
2021-02-07 15:43:02 +08:00
|
|
|
IP string `json:"ip" validate:"required,ip|hostname"`
|
|
|
|
Port int `json:"port" validate:"min=0,max=65535"`
|
|
|
|
Owner string `json:"owner" validate:"required,max=255"`
|
|
|
|
Path string `json:"path" validate:"required,max=255"`
|
|
|
|
Password string `json:"password" validate:"max=255"`
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
var reqData ReqData
|
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2021-09-18 16:35:50 +08:00
|
|
|
if Conn, err := utils.DialSSH(reqData.Owner, reqData.Password, reqData.Path, reqData.IP, reqData.Port); err != nil {
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
2021-09-18 16:35:50 +08:00
|
|
|
} else {
|
|
|
|
_ = Conn.Close()
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
return &core.Response{Message: "Connected"}
|
|
|
|
}
|
|
|
|
|
2020-08-15 13:38:06 +08:00
|
|
|
// Add server
|
2021-09-18 16:35:50 +08:00
|
|
|
func (s Server) Add(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
type ReqData struct {
|
|
|
|
Name string `json:"name" validate:"required"`
|
2021-02-26 16:45:13 +08:00
|
|
|
NamespaceID int64 `json:"namespaceId" validate:"gte=0"`
|
|
|
|
IP string `json:"ip" validate:"ip|hostname"`
|
2020-08-04 14:28:25 +08:00
|
|
|
Port int `json:"port" validate:"min=0,max=65535"`
|
2021-02-07 15:43:02 +08:00
|
|
|
Owner string `json:"owner" validate:"required,max=255"`
|
|
|
|
Path string `json:"path" validate:"required,max=255"`
|
|
|
|
Password string `json:"password"`
|
2020-08-04 14:28:25 +08:00
|
|
|
Description string `json:"description" validate:"max=255"`
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
|
2020-08-04 14:28:25 +08:00
|
|
|
var reqData ReqData
|
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
id, err := model.Server{
|
2021-02-26 16:45:13 +08:00
|
|
|
NamespaceID: reqData.NamespaceID,
|
2020-08-04 14:28:25 +08:00
|
|
|
Name: reqData.Name,
|
|
|
|
IP: reqData.IP,
|
|
|
|
Port: reqData.Port,
|
|
|
|
Owner: reqData.Owner,
|
2021-02-07 15:43:02 +08:00
|
|
|
Path: reqData.Path,
|
|
|
|
Password: reqData.Password,
|
2020-08-04 14:28:25 +08:00
|
|
|
Description: reqData.Description,
|
2021-09-18 16:35:50 +08:00
|
|
|
OSInfo: s.getOSInfo(reqData.Owner, reqData.IP, strconv.Itoa(reqData.Port), reqData.Path),
|
2020-08-04 14:28:25 +08:00
|
|
|
}.AddRow()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
ID int64 `json:"id"`
|
|
|
|
}{ID: id},
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
2020-08-15 13:38:06 +08:00
|
|
|
// Edit server
|
2021-09-18 16:35:50 +08:00
|
|
|
func (s Server) Edit(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
type ReqData struct {
|
|
|
|
ID int64 `json:"id" validate:"gt=0"`
|
2021-02-26 16:45:13 +08:00
|
|
|
NamespaceID int64 `json:"namespaceId" validate:"gte=0"`
|
2020-08-04 14:28:25 +08:00
|
|
|
Name string `json:"name" validate:"required"`
|
2021-02-04 11:15:43 +08:00
|
|
|
IP string `json:"ip" validate:"required,ip|hostname"`
|
2020-08-04 14:28:25 +08:00
|
|
|
Port int `json:"port" validate:"min=0,max=65535"`
|
2021-02-07 15:43:02 +08:00
|
|
|
Owner string `json:"owner" validate:"required,max=255"`
|
|
|
|
Path string `json:"path" validate:"required,max=255"`
|
|
|
|
Password string `json:"password" validate:"max=255"`
|
2020-08-04 14:28:25 +08:00
|
|
|
Description string `json:"description" validate:"max=255"`
|
|
|
|
}
|
|
|
|
var reqData ReqData
|
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
err := model.Server{
|
|
|
|
ID: reqData.ID,
|
2021-02-26 16:45:13 +08:00
|
|
|
NamespaceID: reqData.NamespaceID,
|
2020-08-04 14:28:25 +08:00
|
|
|
Name: reqData.Name,
|
|
|
|
IP: reqData.IP,
|
|
|
|
Port: reqData.Port,
|
|
|
|
Owner: reqData.Owner,
|
2021-02-07 15:43:02 +08:00
|
|
|
Path: reqData.Path,
|
|
|
|
Password: reqData.Password,
|
2020-08-04 14:28:25 +08:00
|
|
|
Description: reqData.Description,
|
2021-09-18 16:35:50 +08:00
|
|
|
OSInfo: s.getOSInfo(reqData.Owner, reqData.IP, strconv.Itoa(reqData.Port), reqData.Path),
|
2020-08-04 14:28:25 +08:00
|
|
|
}.EditRow()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
return &core.Response{}
|
|
|
|
}
|
|
|
|
|
2021-05-25 16:12:08 +08:00
|
|
|
// Toggle server
|
|
|
|
func (Server) Toggle(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
type ReqData struct {
|
2021-06-22 19:59:39 +08:00
|
|
|
ID int64 `json:"id" validate:"gt=0"`
|
|
|
|
State int8 `json:"state" validate:"oneof=0 1"`
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
var reqData ReqData
|
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
2021-05-25 16:12:08 +08:00
|
|
|
if err := (model.Server{ID: reqData.ID, State: reqData.State}).ToggleRow(); err != nil {
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
return &core.Response{}
|
|
|
|
}
|
2021-07-09 20:46:12 +08:00
|
|
|
|
2021-09-29 15:59:42 +08:00
|
|
|
// DownloadFile sftp download file
|
|
|
|
func (Server) DownloadFile(gp *core.Goploy) *core.Response {
|
2021-07-09 20:46:12 +08:00
|
|
|
id, err := strconv.ParseInt(gp.URLQuery.Get("id"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: "invalid server id"}
|
|
|
|
}
|
|
|
|
|
|
|
|
server, err := (model.Server{ID: id}).GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
client, err := utils.DialSSH(server.Owner, server.Password, server.Path, server.IP, server.Port)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2021-09-29 15:59:42 +08:00
|
|
|
defer client.Close()
|
2021-07-09 20:46:12 +08:00
|
|
|
sftpClient, err := sftp.NewClient(client)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2021-09-29 15:59:42 +08:00
|
|
|
filename := gp.URLQuery.Get("file")
|
2021-07-09 20:46:12 +08:00
|
|
|
srcFile, _ := sftpClient.Open(filename) //远程
|
|
|
|
FileStat, _ := srcFile.Stat()
|
|
|
|
FileSize := strconv.FormatInt(FileStat.Size(), 10)
|
|
|
|
gp.ResponseWriter.Header().Set("Content-Disposition", "attachment; filename="+path.Base(filename))
|
|
|
|
gp.ResponseWriter.Header().Set("Content-Type", "application/octet-stream")
|
|
|
|
gp.ResponseWriter.Header().Set("Content-Length", FileSize)
|
|
|
|
_, _ = io.Copy(gp.ResponseWriter, srcFile)
|
|
|
|
_ = srcFile.Close()
|
|
|
|
_ = sftpClient.Close()
|
|
|
|
return nil
|
|
|
|
}
|
2021-09-18 16:35:50 +08:00
|
|
|
|
2021-09-29 15:59:42 +08:00
|
|
|
// UploadFile sftp upload file
|
|
|
|
func (Server) UploadFile(gp *core.Goploy) *core.Response {
|
|
|
|
id, err := strconv.ParseInt(gp.URLQuery.Get("id"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: "invalid server id"}
|
|
|
|
}
|
|
|
|
server, err := (model.Server{ID: id}).GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
file, fileHandler, err := gp.Request.FormFile("file")
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
fileBytes, err := ioutil.ReadAll(file)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
client, err := utils.DialSSH(server.Owner, server.Password, server.Path, server.IP, server.Port)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
sftpClient, err := sftp.NewClient(client)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
defer sftpClient.Close()
|
|
|
|
|
|
|
|
filePath := gp.URLQuery.Get("filePath")
|
|
|
|
remoteFile, err := sftpClient.Create(filePath + "/" + fileHandler.Filename)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err = remoteFile.Write(fileBytes)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-09-18 16:35:50 +08:00
|
|
|
// version|cpu cores|mem
|
|
|
|
func (Server) getOSInfo(owner, ip, port, path string) string {
|
|
|
|
osInfoScript := `cat /etc/os-release | grep "PRETTY_NAME" | awk -F\" '{print $2}' && cat /proc/cpuinfo | grep "processor" | wc -l && cat /proc/meminfo | grep MemTotal | awk '{print $2}'`
|
|
|
|
|
|
|
|
cmd := exec.Command("ssh",
|
|
|
|
owner+"@"+ip,
|
|
|
|
"-p", port,
|
|
|
|
"-i", path,
|
|
|
|
"-o", "StrictHostKeyChecking=no",
|
|
|
|
osInfoScript)
|
|
|
|
var out bytes.Buffer
|
|
|
|
cmd.Stdout = &out
|
|
|
|
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
// version|cpu cores|mem
|
|
|
|
return strings.Replace(strings.Trim(out.String(), "\n"), "\n", "|", -1)
|
|
|
|
}
|