mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 16:00:24 +08:00 
			
		
		
		
	
		
			
	
	
		
			188 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			188 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package setup
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								import (
							 | 
						|||
| 
								 | 
							
									"encoding/json"
							 | 
						|||
| 
								 | 
							
									"github.com/TeaOSLab/EdgeAPI/internal/configs"
							 | 
						|||
| 
								 | 
							
									"github.com/TeaOSLab/EdgeAPI/internal/db/models"
							 | 
						|||
| 
								 | 
							
									"github.com/TeaOSLab/EdgeAPI/internal/errors"
							 | 
						|||
| 
								 | 
							
									"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
							 | 
						|||
| 
								 | 
							
									"github.com/go-yaml/yaml"
							 | 
						|||
| 
								 | 
							
									"github.com/iwind/TeaGo/Tea"
							 | 
						|||
| 
								 | 
							
									"github.com/iwind/TeaGo/cmd"
							 | 
						|||
| 
								 | 
							
									"github.com/iwind/TeaGo/dbs"
							 | 
						|||
| 
								 | 
							
									"github.com/iwind/TeaGo/types"
							 | 
						|||
| 
								 | 
							
									"io/ioutil"
							 | 
						|||
| 
								 | 
							
									"os"
							 | 
						|||
| 
								 | 
							
									"strconv"
							 | 
						|||
| 
								 | 
							
									"strings"
							 | 
						|||
| 
								 | 
							
								)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								type Setup struct {
							 | 
						|||
| 
								 | 
							
									config *Config
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// 要返回的数据
							 | 
						|||
| 
								 | 
							
									AdminNodeId     string
							 | 
						|||
| 
								 | 
							
									AdminNodeSecret string
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func NewSetup(config *Config) *Setup {
							 | 
						|||
| 
								 | 
							
									return &Setup{
							 | 
						|||
| 
								 | 
							
										config: config,
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func NewSetupFromCmd() *Setup {
							 | 
						|||
| 
								 | 
							
									args := cmd.ParseArgs(strings.Join(os.Args[1:], " "))
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									config := &Config{}
							 | 
						|||
| 
								 | 
							
									for _, arg := range args {
							 | 
						|||
| 
								 | 
							
										index := strings.Index(arg, "=")
							 | 
						|||
| 
								 | 
							
										if index <= 0 {
							 | 
						|||
| 
								 | 
							
											continue
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										value := arg[index+1:]
							 | 
						|||
| 
								 | 
							
										value = strings.Trim(value, "\"'")
							 | 
						|||
| 
								 | 
							
										switch arg[:index] {
							 | 
						|||
| 
								 | 
							
										case "-api-node-protocol":
							 | 
						|||
| 
								 | 
							
											config.APINodeProtocol = value
							 | 
						|||
| 
								 | 
							
										case "-api-node-host":
							 | 
						|||
| 
								 | 
							
											config.APINodeHost = value
							 | 
						|||
| 
								 | 
							
										case "-api-node-port":
							 | 
						|||
| 
								 | 
							
											config.APINodePort = types.Int(value)
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									return NewSetup(config)
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func (this *Setup) Run() error {
							 | 
						|||
| 
								 | 
							
									if this.config == nil {
							 | 
						|||
| 
								 | 
							
										return errors.New("config should not be nil")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									if len(this.config.APINodeProtocol) == 0 {
							 | 
						|||
| 
								 | 
							
										return errors.New("api node protocol should not be empty")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									if this.config.APINodeProtocol != "http" && this.config.APINodeProtocol != "https" {
							 | 
						|||
| 
								 | 
							
										return errors.New("invalid api node protocol: " + this.config.APINodeProtocol)
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									if len(this.config.APINodeHost) == 0 {
							 | 
						|||
| 
								 | 
							
										return errors.New("api node host should not be empty")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									if this.config.APINodePort <= 0 {
							 | 
						|||
| 
								 | 
							
										return errors.New("api node port should not be less than 1")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// 执行SQL
							 | 
						|||
| 
								 | 
							
									config := &dbs.Config{}
							 | 
						|||
| 
								 | 
							
									configData, err := ioutil.ReadFile(Tea.ConfigFile("db.yaml"))
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									err = yaml.Unmarshal(configData, config)
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									for _, db := range config.DBs {
							 | 
						|||
| 
								 | 
							
										// 可以同时运行多条语句
							 | 
						|||
| 
								 | 
							
										db.Dsn += "&multiStatements=true"
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									dbConfig, ok := config.DBs[Tea.Env]
							 | 
						|||
| 
								 | 
							
									if !ok {
							 | 
						|||
| 
								 | 
							
										return errors.New("can not find database config for env '" + Tea.Env + "'")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									executor := NewSQLExecutor(dbConfig)
							 | 
						|||
| 
								 | 
							
									err = executor.Run()
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// Admin节点信息
							 | 
						|||
| 
								 | 
							
									apiTokenDAO := models.NewApiTokenDAO()
							 | 
						|||
| 
								 | 
							
									token, err := apiTokenDAO.FindEnabledTokenWithRole("admin")
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									if token == nil {
							 | 
						|||
| 
								 | 
							
										return errors.New("can not find admin node token, please run the setup again")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									this.AdminNodeId = token.NodeId
							 | 
						|||
| 
								 | 
							
									this.AdminNodeSecret = token.Secret
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// 检查API节点
							 | 
						|||
| 
								 | 
							
									dao := models.NewAPINodeDAO()
							 | 
						|||
| 
								 | 
							
									apiNodeId, err := dao.FindEnabledAPINodeIdWithAddr(this.config.APINodeProtocol, this.config.APINodeHost, this.config.APINodePort)
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									if apiNodeId == 0 {
							 | 
						|||
| 
								 | 
							
										addr := &serverconfigs.NetworkAddressConfig{
							 | 
						|||
| 
								 | 
							
											Protocol:  serverconfigs.Protocol(this.config.APINodeProtocol),
							 | 
						|||
| 
								 | 
							
											Host:      this.config.APINodeHost,
							 | 
						|||
| 
								 | 
							
											PortRange: strconv.Itoa(this.config.APINodePort),
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										addrsJSON, err := json.Marshal([]*serverconfigs.NetworkAddressConfig{addr})
							 | 
						|||
| 
								 | 
							
										if err != nil {
							 | 
						|||
| 
								 | 
							
											return errors.New("json encode api node addr failed: " + err.Error())
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										var httpJSON []byte = nil
							 | 
						|||
| 
								 | 
							
										var httpsJSON []byte = nil
							 | 
						|||
| 
								 | 
							
										if this.config.APINodeProtocol == "http" {
							 | 
						|||
| 
								 | 
							
											httpConfig := &serverconfigs.HTTPProtocolConfig{}
							 | 
						|||
| 
								 | 
							
											httpConfig.IsOn = true
							 | 
						|||
| 
								 | 
							
											httpConfig.Listen = []*serverconfigs.NetworkAddressConfig{
							 | 
						|||
| 
								 | 
							
												{
							 | 
						|||
| 
								 | 
							
													PortRange: strconv.Itoa(this.config.APINodePort),
							 | 
						|||
| 
								 | 
							
												},
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											httpJSON, err = json.Marshal(httpConfig)
							 | 
						|||
| 
								 | 
							
											if err != nil {
							 | 
						|||
| 
								 | 
							
												return errors.New("json encode api node http config failed: " + err.Error())
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										if this.config.APINodeProtocol == "https" {
							 | 
						|||
| 
								 | 
							
											// TODO 如果在安装过程中开启了HTTPS,需要同时上传SSL证书
							 | 
						|||
| 
								 | 
							
											httpsConfig := &serverconfigs.HTTPSProtocolConfig{}
							 | 
						|||
| 
								 | 
							
											httpsConfig.IsOn = true
							 | 
						|||
| 
								 | 
							
											httpsConfig.Listen = []*serverconfigs.NetworkAddressConfig{
							 | 
						|||
| 
								 | 
							
												{
							 | 
						|||
| 
								 | 
							
													PortRange: strconv.Itoa(this.config.APINodePort),
							 | 
						|||
| 
								 | 
							
												},
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
											httpsJSON, err = json.Marshal(httpsConfig)
							 | 
						|||
| 
								 | 
							
											if err != nil {
							 | 
						|||
| 
								 | 
							
												return errors.New("json encode api node https config failed: " + err.Error())
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										// 创建API节点
							 | 
						|||
| 
								 | 
							
										nodeId, err := dao.CreateAPINode("默认API节点", "这是默认创建的第一个API节点", httpJSON, httpsJSON, addrsJSON, true)
							 | 
						|||
| 
								 | 
							
										if err != nil {
							 | 
						|||
| 
								 | 
							
											return errors.New("create api node in database failed: " + err.Error())
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										apiNodeId = nodeId
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									apiNode, err := dao.FindEnabledAPINode(apiNodeId)
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									if apiNode == nil {
							 | 
						|||
| 
								 | 
							
										return errors.New("apiNode should not be nil")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// 保存配置
							 | 
						|||
| 
								 | 
							
									apiConfig := &configs.APIConfig{
							 | 
						|||
| 
								 | 
							
										NodeId: apiNode.UniqueId,
							 | 
						|||
| 
								 | 
							
										Secret: apiNode.Secret,
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									err = apiConfig.WriteFile(Tea.ConfigFile("api.yaml"))
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return errors.New("save config failed: " + err.Error())
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									return nil
							 | 
						|||
| 
								 | 
							
								}
							 |