Skip to content

Commit

Permalink
增加打包功能和上传功能
Browse files Browse the repository at this point in the history
  • Loading branch information
pixelmaxQm committed Apr 5, 2024
1 parent 54268de commit 6ec572f
Show file tree
Hide file tree
Showing 9 changed files with 371 additions and 117 deletions.
226 changes: 201 additions & 25 deletions server/api/v1/cloud/server.go
Original file line number Diff line number Diff line change
@@ -1,41 +1,157 @@
package cloud

import (
"archive/zip"
"context"
"github.com/flipped-aurora/gin-vue-admin/server/constant"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/cloud"
"github.com/flipped-aurora/gin-vue-admin/server/model/cloud/request"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/flipped-aurora/gin-vue-admin/server/utils"
"github.com/gin-gonic/gin"
"github.com/pkg/sftp"
"golang.org/x/crypto/ssh"
"io"
"os"
"os/exec"
"path/filepath"
"time"
)

type ServerApi struct{}

// 环境检测
func (s *ServerApi) Check(c *gin.Context) {
// 整体为使用docker-compose部署项目
// 前端使用nginx容器,nginx.conf需要映射到本地文件
// 打包待发布的项目,先找到前端目录,在目录下执行npm run build,获得dist目录
// 然后到后端文件下,根据传入的不同的system系统,设置环境变量,执行go build -o server
// windows变量 GOOS=windows GOARCH=amd64
// linux变量 GOOS=linux GOARCH=amd64
// mac变量 GOOS=darwin GOARCH=amd64
// 然后将前端dist目录和后端server文件+ 后端resource + 后端 config.yaml 打包成zip文件
// 根据config.yaml文件中的system的数据库类型设置和数据库具体配置来创建docker-compose.yml文件
// 如果数据库地址不为127.0.0.1,则需要在docker-compose.yml文件中设置数据库地址
// 如果数据库地址为127.0.0.1,则需要创建mysql容器,并且在docker-compose.yml文件中设置数据库地址,且挂盘数据到本地
// 然后将zip文件传输到服务器上,解压到服务器/www-gva目录下
// 进入/www-gva目录下,执行docker-compose up -d
func (s *ServerApi) Zip(c *gin.Context) {
var de request.Deploy
err := c.ShouldBindJSON(&de)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}

// 创建一个带有超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Hour) // 设置为1小时
defer cancel()
webPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Web, "..")

// 将新的上下文传递给需要长时间运行的操作
c.Request = c.Request.WithContext(ctx)
// 执行一个命令,获取错误输出
webCmd := exec.Command("npm", "run", "build")
webCmd.Dir = webPath
webOut, err := webCmd.CombinedOutput()
if err != nil {
response.FailWithMessage(string(webOut), c)
return
}

checkDocker := cloud.CmdNode{
Cmd: "docker version",
serverCmd := exec.Command("go", "build", "-o", "gin-vue-admin")
switch de.SystemType {
case "windows":
serverCmd.Env = append(os.Environ(), "GOOS=windows", "GOARCH=amd64")
case "linux":
serverCmd.Env = append(os.Environ(), "GOOS=linux", "GOARCH=amd64")
case "mac":
serverCmd.Env = append(os.Environ(), "GOOS=darwin", "GOARCH=amd64")
}

checkDockerCompose := cloud.CmdNode{
Cmd: "docker-compose version",
serverPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server)
serverCmd.Dir = serverPath
serverOut, err := serverCmd.CombinedOutput()

if err != nil {
response.FailWithMessage(string(serverOut), c)
return
}

fileName := "deploy.zip"
// 创建一个新的zip文件
zipFile, err := os.Create(fileName)
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
defer zipFile.Close()

Run([]cloud.CmdNode{checkDocker, checkDockerCompose}, c)
// 创建一个zip写入器
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()

err = utils.DoZip(zipWriter, filepath.Join(webPath, "dist"), "dist")
if err != nil {
response.FailWithMessage(err.Error(), c)
return
}
response.OkWithMessage("打包成功", c)
}

// 安装环境
func (s *ServerApi) Install(c *gin.Context) {
func (s *ServerApi) Down(c *gin.Context) {
//Run([]cloud.CmdNode{checkDocker, checkDockerCompose}, c)
}

func (s *ServerApi) Deploy(c *gin.Context) {
c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")
// 将新的上下文传递给需要长时间运行的操作
var checkRequest request.SSHRequest
err := c.ShouldBindJSON(&checkRequest)
if err != nil {
c.SSEvent(constant.FAIL, err.Error())
return
}

client, err := checkRequest.Connection()
if err != nil {
c.SSEvent(constant.FAIL, err.Error())
return
}

serverPath := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server)

serverFile := filepath.Join(serverPath, "gin-vue-admin")
webFile := filepath.Join(serverPath, "deploy.zip")

err = SftpUpload(serverFile, "/www-gva/server", "/www-gva/server/gin-vue-admin", client)
if err != nil {
c.SSEvent(constant.FAIL, err.Error())
return
}
err = SftpUpload(webFile, "/www-gva/web", "/www-gva/web/deploy.zip", client)
if err != nil {
c.SSEvent(constant.FAIL, err.Error())
return
}
}

// 环境检测
func (s *ServerApi) Check(c *gin.Context) {

c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")
// 将新的上下文传递给需要长时间运行的操作
var checkRequest request.SSHRequest
err := c.ShouldBindJSON(&checkRequest)
if err != nil {
c.SSEvent(constant.FAIL, err.Error())
return
}

client, err := checkRequest.Connection()
if err != nil {
c.SSEvent(constant.FAIL, err.Error())
return
}
defer client.Close()

// 创建一个带有超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Hour) // 设置为1小时
Expand All @@ -44,30 +160,26 @@ func (s *ServerApi) Install(c *gin.Context) {
// 将新的上下文传递给需要长时间运行的操作
c.Request = c.Request.WithContext(ctx)

docker := cloud.CmdNode{
Cmd: "curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh",
checkDocker := cloud.CmdNode{
Cmd: "docker version",
}

dockerCompose := cloud.CmdNode{
Cmd: "sudo curl -L \"https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose && docker-compose version",
checkDockerCompose := cloud.CmdNode{
Cmd: "docker-compose version",
}

Run([]cloud.CmdNode{docker, dockerCompose}, c)
Run([]cloud.CmdNode{checkDocker, checkDockerCompose}, client, c)

}

// 发布
func (s *ServerApi) Deploy() {

}
// 安装环境
func (s *ServerApi) Install(c *gin.Context) {

func Run(cmds []cloud.CmdNode, c *gin.Context) {
c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")
// 将新的上下文传递给需要长时间运行的操作
var checkRequest request.SSHRequest
msg := make(chan cloud.MsgInfo, 100)
err := c.ShouldBindJSON(&checkRequest)
if err != nil {
c.SSEvent(constant.FAIL, err.Error())
Expand All @@ -81,6 +193,28 @@ func Run(cmds []cloud.CmdNode, c *gin.Context) {
}
defer client.Close()

// 创建一个带有超时的上下文
ctx, cancel := context.WithTimeout(c.Request.Context(), 1*time.Hour) // 设置为1小时
defer cancel()

// 将新的上下文传递给需要长时间运行的操作
c.Request = c.Request.WithContext(ctx)

docker := cloud.CmdNode{
Cmd: "curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh",
}

dockerCompose := cloud.CmdNode{
Cmd: "sudo curl -L \"https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose && docker-compose version",
}

Run([]cloud.CmdNode{docker, dockerCompose}, client, c)

}

func Run(cmds []cloud.CmdNode, client *ssh.Client, c *gin.Context) {
msg := make(chan cloud.MsgInfo, 100)

go func() {
c.Stream(func(w io.Writer) bool {
select {
Expand All @@ -103,3 +237,45 @@ func Run(cmds []cloud.CmdNode, c *gin.Context) {

msg <- cloud.MsgInfo{Msg: "complete", Status: constant.COMPLETE}
}

func SftpUpload(localFile string, dir, remoteFile string, client *ssh.Client) error {
sftpClient, err := sftp.NewClient(client)
if err != nil {
return err
}
defer sftpClient.Close()
// Open the source file
srcFile, err := os.Open(localFile)
if err != nil {
return err
}
defer srcFile.Close()

//remoteFile所在目录不存在时候 创建目录

if _, err := sftpClient.Stat(dir); err != nil {
session, err := client.NewSession()
if err != nil {
return err
}
err = session.Run("mkdir -p " + dir)
if err != nil {
return err
}
session.Close()
}

// Create the destination file
dstFile, err := sftpClient.Create(remoteFile)
if err != nil {
return err
}
defer dstFile.Close()

// Copy the file
_, err = dstFile.ReadFrom(srcFile)
if err != nil {
return err
}
return nil
}
2 changes: 2 additions & 0 deletions server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ require (
github.com/mojocn/base64Captcha v1.3.5
github.com/otiai10/copy v1.7.0
github.com/pkg/errors v0.9.1
github.com/pkg/sftp v1.13.1
github.com/qiniu/api.v7/v7 v7.4.1
github.com/qiniu/qmgo v1.1.8
github.com/redis/go-redis/v9 v9.0.5
Expand Down Expand Up @@ -87,6 +88,7 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
Expand Down
2 changes: 2 additions & 0 deletions server/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
Expand Down Expand Up @@ -335,6 +336,7 @@ github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzL
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down
6 changes: 6 additions & 0 deletions server/model/cloud/request/deploy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package request

type Deploy struct {
Origin string `json:"origin"`
SystemType string `json:"systemType"`
}
3 changes: 3 additions & 0 deletions server/router/cloud/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ func (e *ServerRouter) InitServerRouter(Router *gin.RouterGroup) {
{
customerRouter.POST("check", serverApi.Check) // 检测环境
customerRouter.POST("install", serverApi.Install) // 安装环境
customerRouter.POST("zip", serverApi.Zip) // 打包测试
customerRouter.POST("deploy", serverApi.Deploy) // 上传部署

}
}
Loading

0 comments on commit 6ec572f

Please sign in to comment.