2020-10-13 20:05:13 +08:00
|
|
|
|
package setup
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"encoding/json"
|
2023-08-11 16:13:33 +08:00
|
|
|
|
"fmt"
|
2024-07-27 14:15:25 +08:00
|
|
|
|
"os"
|
|
|
|
|
|
"strconv"
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
|
2020-10-13 20:05:13 +08:00
|
|
|
|
"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
|
2022-11-11 21:48:00 +08:00
|
|
|
|
|
|
|
|
|
|
logFp *os.File
|
2020-10-13 20:05:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewSetup(config *Config) *Setup {
|
|
|
|
|
|
return &Setup{
|
|
|
|
|
|
config: config,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func NewSetupFromCmd() *Setup {
|
2022-11-11 21:48:00 +08:00
|
|
|
|
var args = cmd.ParseArgs(strings.Join(os.Args[1:], " "))
|
2020-10-13 20:05:13 +08:00
|
|
|
|
|
2022-11-11 21:48:00 +08:00
|
|
|
|
var config = &Config{}
|
2020-10-13 20:05:13 +08:00
|
|
|
|
for _, arg := range args {
|
2022-11-11 21:48:00 +08:00
|
|
|
|
var index = strings.Index(arg, "=")
|
2020-10-13 20:05:13 +08:00
|
|
|
|
if index <= 0 {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
2022-11-11 21:48:00 +08:00
|
|
|
|
var value = arg[index+1:]
|
2020-10-13 20:05:13 +08:00
|
|
|
|
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)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-11 21:48:00 +08:00
|
|
|
|
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
|
2020-10-13 20:05:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2024-05-06 17:31:08 +08:00
|
|
|
|
config, err := configs.LoadDBConfig()
|
2020-10-13 20:05:13 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
for _, db := range config.DBs {
|
|
|
|
|
|
// 可以同时运行多条语句
|
2023-07-04 22:02:17 +08:00
|
|
|
|
if !strings.Contains(db.Dsn, "multiStatements=") {
|
|
|
|
|
|
if strings.Contains(db.Dsn, "?") {
|
|
|
|
|
|
db.Dsn += "&multiStatements=true"
|
|
|
|
|
|
} else {
|
|
|
|
|
|
db.Dsn += "?multiStatements=true"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2020-10-13 20:05:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
dbConfig, ok := config.DBs[Tea.Env]
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return errors.New("can not find database config for env '" + Tea.Env + "'")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-11-11 21:48:00 +08:00
|
|
|
|
var executor = NewSQLExecutor(dbConfig)
|
|
|
|
|
|
if this.logFp != nil {
|
|
|
|
|
|
executor.SetLogWriter(this.logFp)
|
|
|
|
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
|
|
_ = this.logFp.Close()
|
|
|
|
|
|
_ = os.Remove(this.logFp.Name())
|
|
|
|
|
|
}()
|
|
|
|
|
|
}
|
2021-08-05 19:53:54 +08:00
|
|
|
|
err = executor.Run(false)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Admin节点信息
|
2022-11-11 21:48:00 +08:00
|
|
|
|
var apiTokenDAO = models.NewApiTokenDAO()
|
2021-01-01 23:31:30 +08:00
|
|
|
|
token, err := apiTokenDAO.FindEnabledTokenWithRole(nil, "admin")
|
2020-10-13 20:05:13 +08:00
|
|
|
|
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节点
|
2022-11-11 21:48:00 +08:00
|
|
|
|
var dao = models.NewAPINodeDAO()
|
2021-01-01 23:31:30 +08:00
|
|
|
|
apiNodeId, err := dao.FindEnabledAPINodeIdWithAddr(nil, this.config.APINodeProtocol, this.config.APINodeHost, this.config.APINodePort)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if apiNodeId == 0 {
|
2024-05-06 17:31:08 +08:00
|
|
|
|
var addr = &serverconfigs.NetworkAddressConfig{
|
2020-10-13 20:05:13 +08:00
|
|
|
|
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 {
|
2023-08-11 16:13:33 +08:00
|
|
|
|
return fmt.Errorf("json encode api node addr failed: %w", err)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var httpJSON []byte = nil
|
|
|
|
|
|
var httpsJSON []byte = nil
|
|
|
|
|
|
if this.config.APINodeProtocol == "http" {
|
|
|
|
|
|
httpConfig := &serverconfigs.HTTPProtocolConfig{}
|
|
|
|
|
|
httpConfig.IsOn = true
|
|
|
|
|
|
httpConfig.Listen = []*serverconfigs.NetworkAddressConfig{
|
|
|
|
|
|
{
|
2021-11-21 19:28:05 +08:00
|
|
|
|
Protocol: "http",
|
2020-10-13 20:05:13 +08:00
|
|
|
|
PortRange: strconv.Itoa(this.config.APINodePort),
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
httpJSON, err = json.Marshal(httpConfig)
|
|
|
|
|
|
if err != nil {
|
2023-08-11 16:13:33 +08:00
|
|
|
|
return fmt.Errorf("json encode api node http config failed: %w", err)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if this.config.APINodeProtocol == "https" {
|
|
|
|
|
|
// TODO 如果在安装过程中开启了HTTPS,需要同时上传SSL证书
|
2024-05-06 17:31:08 +08:00
|
|
|
|
var httpsConfig = &serverconfigs.HTTPSProtocolConfig{}
|
2020-10-13 20:05:13 +08:00
|
|
|
|
httpsConfig.IsOn = true
|
|
|
|
|
|
httpsConfig.Listen = []*serverconfigs.NetworkAddressConfig{
|
|
|
|
|
|
{
|
2020-10-14 18:44:34 +08:00
|
|
|
|
Protocol: "https",
|
2020-10-13 20:05:13 +08:00
|
|
|
|
PortRange: strconv.Itoa(this.config.APINodePort),
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
httpsJSON, err = json.Marshal(httpsConfig)
|
|
|
|
|
|
if err != nil {
|
2023-08-11 16:13:33 +08:00
|
|
|
|
return fmt.Errorf("json encode api node https config failed: %w", err)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建API节点
|
2021-01-01 23:31:30 +08:00
|
|
|
|
nodeId, err := dao.CreateAPINode(nil, "默认API节点", "这是默认创建的第一个API节点", httpJSON, httpsJSON, false, nil, nil, addrsJSON, true)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
if err != nil {
|
2023-08-11 16:13:33 +08:00
|
|
|
|
return fmt.Errorf("create api node in database failed: %w", err)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
apiNodeId = nodeId
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-01-19 16:53:52 +08:00
|
|
|
|
apiNode, err := dao.FindEnabledAPINode(nil, apiNodeId, nil)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if apiNode == nil {
|
|
|
|
|
|
return errors.New("apiNode should not be nil")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 保存配置
|
2022-11-11 21:48:00 +08:00
|
|
|
|
var apiConfig = &configs.APIConfig{
|
2020-10-13 20:05:13 +08:00
|
|
|
|
NodeId: apiNode.UniqueId,
|
|
|
|
|
|
Secret: apiNode.Secret,
|
|
|
|
|
|
}
|
|
|
|
|
|
err = apiConfig.WriteFile(Tea.ConfigFile("api.yaml"))
|
|
|
|
|
|
if err != nil {
|
2023-08-11 16:13:33 +08:00
|
|
|
|
return fmt.Errorf("save config failed: %w", err)
|
2020-10-13 20:05:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|