Files
EdgeAPI/internal/setup/setup.go
GoEdgeLab 5a17ae9d79 v1.4.1
2024-07-27 14:15:25 +08:00

211 lines
5.2 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package setup
import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"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/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/cmd"
"github.com/iwind/TeaGo/types"
)
type Setup struct {
config *Config
// 要返回的数据
AdminNodeId string
AdminNodeSecret string
logFp *os.File
}
func NewSetup(config *Config) *Setup {
return &Setup{
config: config,
}
}
func NewSetupFromCmd() *Setup {
var args = cmd.ParseArgs(strings.Join(os.Args[1:], " "))
var config = &Config{}
for _, arg := range args {
var index = strings.Index(arg, "=")
if index <= 0 {
continue
}
var 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)
}
}
var setup = NewSetup(config)
// log writer
var tmpDir = os.TempDir()
if len(tmpDir) > 0 {
fp, err := os.OpenFile(tmpDir+"/edge-install.log", os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0666)
if err == nil {
setup.logFp = fp
}
}
return setup
}
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, err := configs.LoadDBConfig()
if err != nil {
return err
}
for _, db := range config.DBs {
// 可以同时运行多条语句
if !strings.Contains(db.Dsn, "multiStatements=") {
if strings.Contains(db.Dsn, "?") {
db.Dsn += "&multiStatements=true"
} else {
db.Dsn += "?multiStatements=true"
}
}
}
dbConfig, ok := config.DBs[Tea.Env]
if !ok {
return errors.New("can not find database config for env '" + Tea.Env + "'")
}
var executor = NewSQLExecutor(dbConfig)
if this.logFp != nil {
executor.SetLogWriter(this.logFp)
defer func() {
_ = this.logFp.Close()
_ = os.Remove(this.logFp.Name())
}()
}
err = executor.Run(false)
if err != nil {
return err
}
// Admin节点信息
var apiTokenDAO = models.NewApiTokenDAO()
token, err := apiTokenDAO.FindEnabledTokenWithRole(nil, "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节点
var dao = models.NewAPINodeDAO()
apiNodeId, err := dao.FindEnabledAPINodeIdWithAddr(nil, this.config.APINodeProtocol, this.config.APINodeHost, this.config.APINodePort)
if err != nil {
return err
}
if apiNodeId == 0 {
var 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 fmt.Errorf("json encode api node addr failed: %w", err)
}
var httpJSON []byte = nil
var httpsJSON []byte = nil
if this.config.APINodeProtocol == "http" {
httpConfig := &serverconfigs.HTTPProtocolConfig{}
httpConfig.IsOn = true
httpConfig.Listen = []*serverconfigs.NetworkAddressConfig{
{
Protocol: "http",
PortRange: strconv.Itoa(this.config.APINodePort),
},
}
httpJSON, err = json.Marshal(httpConfig)
if err != nil {
return fmt.Errorf("json encode api node http config failed: %w", err)
}
}
if this.config.APINodeProtocol == "https" {
// TODO 如果在安装过程中开启了HTTPS需要同时上传SSL证书
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
httpsConfig.IsOn = true
httpsConfig.Listen = []*serverconfigs.NetworkAddressConfig{
{
Protocol: "https",
PortRange: strconv.Itoa(this.config.APINodePort),
},
}
httpsJSON, err = json.Marshal(httpsConfig)
if err != nil {
return fmt.Errorf("json encode api node https config failed: %w", err)
}
}
// 创建API节点
nodeId, err := dao.CreateAPINode(nil, "默认API节点", "这是默认创建的第一个API节点", httpJSON, httpsJSON, false, nil, nil, addrsJSON, true)
if err != nil {
return fmt.Errorf("create api node in database failed: %w", err)
}
apiNodeId = nodeId
}
apiNode, err := dao.FindEnabledAPINode(nil, apiNodeId, nil)
if err != nil {
return err
}
if apiNode == nil {
return errors.New("apiNode should not be nil")
}
// 保存配置
var apiConfig = &configs.APIConfig{
NodeId: apiNode.UniqueId,
Secret: apiNode.Secret,
}
err = apiConfig.WriteFile(Tea.ConfigFile("api.yaml"))
if err != nil {
return fmt.Errorf("save config failed: %w", err)
}
return nil
}