mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 13:10:26 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			246 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package setup
 | 
						||
 | 
						||
import (
 | 
						||
	"bytes"
 | 
						||
	"encoding/json"
 | 
						||
	"github.com/TeaOSLab/EdgeAdmin/internal/configs"
 | 
						||
	"github.com/TeaOSLab/EdgeAdmin/internal/nodes"
 | 
						||
	"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
 | 
						||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
						||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
						||
	"github.com/go-yaml/yaml"
 | 
						||
	"github.com/iwind/TeaGo/Tea"
 | 
						||
	"github.com/iwind/TeaGo/actions"
 | 
						||
	"github.com/iwind/TeaGo/dbs"
 | 
						||
	"github.com/iwind/TeaGo/maps"
 | 
						||
	"io/ioutil"
 | 
						||
	"os"
 | 
						||
	"os/exec"
 | 
						||
	"time"
 | 
						||
)
 | 
						||
 | 
						||
type InstallAction struct {
 | 
						||
	actionutils.ParentAction
 | 
						||
}
 | 
						||
 | 
						||
func (this *InstallAction) RunPost(params struct {
 | 
						||
	ApiNodeJSON []byte
 | 
						||
	DbJSON      []byte
 | 
						||
	AdminJSON   []byte
 | 
						||
 | 
						||
	Must *actions.Must
 | 
						||
}) {
 | 
						||
	// API节点配置
 | 
						||
	apiNodeMap := maps.Map{}
 | 
						||
	err := json.Unmarshal(params.ApiNodeJSON, &apiNodeMap)
 | 
						||
	if err != nil {
 | 
						||
		this.Fail("API节点配置数据解析错误,请刷新页面后重新尝试安装,错误信息:" + err.Error())
 | 
						||
	}
 | 
						||
 | 
						||
	// 数据库
 | 
						||
	dbMap := maps.Map{}
 | 
						||
	err = json.Unmarshal(params.DbJSON, &dbMap)
 | 
						||
	if err != nil {
 | 
						||
		this.Fail("数据库配置数据解析错误,请刷新页面后重新尝试安装,错误信息:" + err.Error())
 | 
						||
	}
 | 
						||
 | 
						||
	// 管理员
 | 
						||
	adminMap := maps.Map{}
 | 
						||
	err = json.Unmarshal(params.AdminJSON, &adminMap)
 | 
						||
	if err != nil {
 | 
						||
		this.Fail("管理员数据解析错误,请刷新页面后重新尝试安装,错误信息:" + err.Error())
 | 
						||
	}
 | 
						||
 | 
						||
	// 安装API节点
 | 
						||
	mode := apiNodeMap.GetString("mode")
 | 
						||
	if mode == "new" {
 | 
						||
		// 整个系统目录结构为:
 | 
						||
		//  edge-admin/
 | 
						||
		//    edge-api/
 | 
						||
		//    bin/
 | 
						||
		//    ...
 | 
						||
 | 
						||
		// 检查环境
 | 
						||
		apiNodeDir := Tea.Root + "/edge-api"
 | 
						||
		for _, dir := range []string{"edge-api", "edge-api/configs", "edge-api/bin"} {
 | 
						||
			apiNodeDir := Tea.Root + "/" + dir
 | 
						||
			_, err = os.Stat(apiNodeDir)
 | 
						||
			if err != nil {
 | 
						||
				if os.IsNotExist(err) {
 | 
						||
					this.Fail("在当前目录下找不到" + dir + "目录,请将" + dir + "目录上传或者重新下载解压")
 | 
						||
				}
 | 
						||
				this.Fail("无法检查" + dir + "目录,发生错误:" + err.Error())
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		// 保存数据库配置
 | 
						||
		dsn := dbMap.GetString("username") + ":" + dbMap.GetString("password") + "@tcp(" + dbMap.GetString("host") + ":" + dbMap.GetString("port") + ")/" + dbMap.GetString("database") + "?charset=utf8mb4&timeout=30s"
 | 
						||
		dbConfig := &dbs.Config{
 | 
						||
			DBs: map[string]*dbs.DBConfig{
 | 
						||
				"prod": {
 | 
						||
					Driver: "mysql",
 | 
						||
					Dsn:    dsn,
 | 
						||
					Prefix: "edge",
 | 
						||
				}},
 | 
						||
		}
 | 
						||
		dbConfigData, err := yaml.Marshal(dbConfig)
 | 
						||
		if err != nil {
 | 
						||
			this.Fail("生成数据库配置失败:" + err.Error())
 | 
						||
		}
 | 
						||
		err = ioutil.WriteFile(apiNodeDir+"/configs/db.yaml", dbConfigData, 0666)
 | 
						||
		if err != nil {
 | 
						||
			this.Fail("保存数据库配置失败:" + err.Error())
 | 
						||
		}
 | 
						||
 | 
						||
		// 生成备份文件
 | 
						||
		homeDir, _ := os.UserHomeDir()
 | 
						||
		backupDirs := []string{"/etc/edge-api"}
 | 
						||
		if len(homeDir) > 0 {
 | 
						||
			backupDirs = append(backupDirs, homeDir+"/.edge-api")
 | 
						||
		}
 | 
						||
		for _, backupDir := range backupDirs {
 | 
						||
			stat, err := os.Stat(backupDir)
 | 
						||
			if err == nil && stat.IsDir() {
 | 
						||
				_ = ioutil.WriteFile(backupDir+"/db.yaml", dbConfigData, 0666)
 | 
						||
			} else if err != nil && os.IsNotExist(err) {
 | 
						||
				err = os.Mkdir(backupDir, 0777)
 | 
						||
				if err == nil {
 | 
						||
					_ = ioutil.WriteFile(backupDir+"/db.yaml", dbConfigData, 0666)
 | 
						||
				}
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		err = ioutil.WriteFile(Tea.ConfigFile("/api_db.yaml"), dbConfigData, 0666)
 | 
						||
		if err != nil {
 | 
						||
			this.Fail("保存数据库配置失败:" + err.Error())
 | 
						||
		}
 | 
						||
 | 
						||
		// 生成备份文件
 | 
						||
		backupDirs = []string{"/etc/edge-admin"}
 | 
						||
		if len(homeDir) > 0 {
 | 
						||
			backupDirs = append(backupDirs, homeDir+"/.edge-admin")
 | 
						||
		}
 | 
						||
		for _, backupDir := range backupDirs {
 | 
						||
			stat, err := os.Stat(backupDir)
 | 
						||
			if err == nil && stat.IsDir() {
 | 
						||
				_ = ioutil.WriteFile(backupDir+"/api_db.yaml", dbConfigData, 0666)
 | 
						||
			} else if err != nil && os.IsNotExist(err) {
 | 
						||
				err = os.Mkdir(backupDir, 0777)
 | 
						||
				if err == nil {
 | 
						||
					_ = ioutil.WriteFile(backupDir+"/api_db.yaml", dbConfigData, 0666)
 | 
						||
				}
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		// 开始安装
 | 
						||
		var resultMap = maps.Map{}
 | 
						||
		{
 | 
						||
			cmd := exec.Command(apiNodeDir+"/bin/edge-api", "setup", "-api-node-protocol=http", "-api-node-host=\""+apiNodeMap.GetString("newHost")+"\"", "-api-node-port=\""+apiNodeMap.GetString("newPort")+"\"")
 | 
						||
			output := bytes.NewBuffer([]byte{})
 | 
						||
			cmd.Stdout = output
 | 
						||
			err = cmd.Run()
 | 
						||
			if err != nil {
 | 
						||
				this.Fail("安装失败:" + err.Error())
 | 
						||
			}
 | 
						||
 | 
						||
			resultData := output.Bytes()
 | 
						||
			err = json.Unmarshal(resultData, &resultMap)
 | 
						||
			if err != nil {
 | 
						||
				this.Fail("安装节点时返回数据错误:" + err.Error() + "(" + string(resultData) + ")")
 | 
						||
			}
 | 
						||
			if !resultMap.GetBool("isOk") {
 | 
						||
				this.Fail("节点安装错误:" + resultMap.GetString("error"))
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
		// 启动API节点
 | 
						||
		{
 | 
						||
			cmd := exec.Command(apiNodeDir + "/bin/edge-api")
 | 
						||
			err = cmd.Start()
 | 
						||
			if err != nil {
 | 
						||
				this.Fail("API节点启动失败:" + err.Error())
 | 
						||
			}
 | 
						||
 | 
						||
			// 记录子PID方便退出的时候一起退出
 | 
						||
			nodes.SharedAdminNode.AddSubPID(cmd.Process.Pid)
 | 
						||
 | 
						||
			// 等待API节点初始化完成
 | 
						||
			time.Sleep(2 * time.Second)
 | 
						||
		}
 | 
						||
 | 
						||
		// 写入API节点配置,完成安装
 | 
						||
		apiConfig := &configs.APIConfig{
 | 
						||
			RPC: struct {
 | 
						||
				Endpoints []string `yaml:"endpoints"`
 | 
						||
			}{
 | 
						||
				Endpoints: []string{"http://" + apiNodeMap.GetString("newHost") + ":" + apiNodeMap.GetString("newPort")},
 | 
						||
			},
 | 
						||
			NodeId: resultMap.GetString("adminNodeId"),
 | 
						||
			Secret: resultMap.GetString("adminNodeSecret"),
 | 
						||
		}
 | 
						||
 | 
						||
		// 设置管理员
 | 
						||
		client, err := rpc.NewRPCClient(apiConfig)
 | 
						||
		if err != nil {
 | 
						||
			this.FailField("oldHost", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
 | 
						||
		}
 | 
						||
		ctx := client.Context(0)
 | 
						||
		for i := 0; i < 3; i++ {
 | 
						||
			_, err = client.AdminRPC().CreateOrUpdateAdmin(ctx, &pb.CreateOrUpdateAdminRequest{
 | 
						||
				Username: adminMap.GetString("username"),
 | 
						||
				Password: adminMap.GetString("password"),
 | 
						||
			})
 | 
						||
			// 这里我们尝试多次是为了当代API节点启动完毕
 | 
						||
			if err != nil {
 | 
						||
				time.Sleep(1 * time.Second)
 | 
						||
			}
 | 
						||
		}
 | 
						||
		if err != nil {
 | 
						||
			this.Fail("设置管理员账号出错:" + err.Error())
 | 
						||
		}
 | 
						||
 | 
						||
		err = apiConfig.WriteFile(Tea.ConfigFile("api.yaml"))
 | 
						||
		if err != nil {
 | 
						||
			this.Fail("保存配置失败,原因:" + err.Error())
 | 
						||
		}
 | 
						||
 | 
						||
		this.Success()
 | 
						||
	} else if mode == "old" {
 | 
						||
		// 构造RPC
 | 
						||
		apiConfig := &configs.APIConfig{
 | 
						||
			RPC: struct {
 | 
						||
				Endpoints []string `yaml:"endpoints"`
 | 
						||
			}{
 | 
						||
				Endpoints: []string{apiNodeMap.GetString("oldProtocol") + "://" + apiNodeMap.GetString("oldHost") + ":" + apiNodeMap.GetString("oldPort")},
 | 
						||
			},
 | 
						||
			NodeId: apiNodeMap.GetString("oldNodeId"),
 | 
						||
			Secret: apiNodeMap.GetString("oldNodeSecret"),
 | 
						||
		}
 | 
						||
		client, err := rpc.NewRPCClient(apiConfig)
 | 
						||
		if err != nil {
 | 
						||
			this.FailField("oldHost", "测试API节点时出错,请检查配置,错误信息:"+err.Error())
 | 
						||
		}
 | 
						||
 | 
						||
		// 设置管理员
 | 
						||
		ctx := client.APIContext(0)
 | 
						||
		_, err = client.AdminRPC().CreateOrUpdateAdmin(ctx, &pb.CreateOrUpdateAdminRequest{
 | 
						||
			Username: adminMap.GetString("username"),
 | 
						||
			Password: adminMap.GetString("password"),
 | 
						||
		})
 | 
						||
		if err != nil {
 | 
						||
			this.Fail("设置管理员账号出错:" + err.Error())
 | 
						||
		}
 | 
						||
 | 
						||
		// 写入API节点配置,完成安装
 | 
						||
		err = apiConfig.WriteFile(Tea.ConfigFile("api.yaml"))
 | 
						||
		if err != nil {
 | 
						||
			this.Fail("保存配置失败,原因:" + err.Error())
 | 
						||
		}
 | 
						||
 | 
						||
		// 成功
 | 
						||
		this.Success()
 | 
						||
	} else {
 | 
						||
		this.Fail("错误的API节点模式:'" + mode + "'")
 | 
						||
	}
 | 
						||
}
 |