mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-02 20:00:26 +08:00
增加创建本地节点命令
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAdmin/internal/nodes"
|
"github.com/TeaOSLab/EdgeAdmin/internal/nodes"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
_ "github.com/TeaOSLab/EdgeAdmin/internal/web"
|
_ "github.com/TeaOSLab/EdgeAdmin/internal/web"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
|
||||||
_ "github.com/TeaOSLab/EdgeCommon/pkg/langs/messages"
|
_ "github.com/TeaOSLab/EdgeCommon/pkg/langs/messages"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
_ "github.com/iwind/TeaGo/bootstrap"
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
@@ -40,7 +41,8 @@ func main() {
|
|||||||
Option("demo", "switch to demo mode").
|
Option("demo", "switch to demo mode").
|
||||||
Option("dev", "switch to 'dev' mode").
|
Option("dev", "switch to 'dev' mode").
|
||||||
Option("prod", "switch to 'prod' mode").
|
Option("prod", "switch to 'prod' mode").
|
||||||
Option("upgrade [--url=URL]", "upgrade from official site or an url")
|
Option("upgrade [--url=URL]", "upgrade from official site or an url").
|
||||||
|
Option("install-local-node", "install a local node")
|
||||||
|
|
||||||
app.On("daemon", func() {
|
app.On("daemon", func() {
|
||||||
nodes.NewAdminNode().Daemon()
|
nodes.NewAdminNode().Daemon()
|
||||||
@@ -76,7 +78,7 @@ func main() {
|
|||||||
fmt.Println("done")
|
fmt.Println("done")
|
||||||
})
|
})
|
||||||
app.On("recover", func() {
|
app.On("recover", func() {
|
||||||
sock := gosock.NewTmpSock(teaconst.ProcessName)
|
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||||
if !sock.IsListening() {
|
if !sock.IsListening() {
|
||||||
fmt.Println("[ERROR]the service not started yet, you should start the service first")
|
fmt.Println("[ERROR]the service not started yet, you should start the service first")
|
||||||
return
|
return
|
||||||
@@ -89,7 +91,7 @@ func main() {
|
|||||||
fmt.Println("enter recovery mode successfully")
|
fmt.Println("enter recovery mode successfully")
|
||||||
})
|
})
|
||||||
app.On("demo", func() {
|
app.On("demo", func() {
|
||||||
sock := gosock.NewTmpSock(teaconst.ProcessName)
|
var sock = gosock.NewTmpSock(teaconst.ProcessName)
|
||||||
if !sock.IsListening() {
|
if !sock.IsListening() {
|
||||||
fmt.Println("[ERROR]the service not started yet, you should start the service first")
|
fmt.Println("[ERROR]the service not started yet, you should start the service first")
|
||||||
return
|
return
|
||||||
@@ -178,6 +180,14 @@ func main() {
|
|||||||
log.Println("restarting ...")
|
log.Println("restarting ...")
|
||||||
app.RunRestart()
|
app.RunRestart()
|
||||||
})
|
})
|
||||||
|
app.On("install-local-node", func() {
|
||||||
|
err := nodeutils.InstallLocalNode()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("[ERROR]" + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("success")
|
||||||
|
})
|
||||||
app.Run(func() {
|
app.Run(func() {
|
||||||
var adminNode = nodes.NewAdminNode()
|
var adminNode = nodes.NewAdminNode()
|
||||||
adminNode.Run()
|
adminNode.Run()
|
||||||
|
|||||||
@@ -4,12 +4,23 @@ package nodeutils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
|
||||||
|
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
|
||||||
|
executils "github.com/TeaOSLab/EdgeAdmin/internal/utils/exec"
|
||||||
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
"github.com/TeaOSLab/EdgeCommon/pkg/langs/codes"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitNodeInfo 初始化节点信息
|
// InitNodeInfo 初始化节点信息
|
||||||
@@ -104,3 +115,124 @@ func InitNodeInfo(parentAction *actionutils.ParentAction, nodeId int64) (*pb.Nod
|
|||||||
|
|
||||||
return nodeResp.Node, nil
|
return nodeResp.Node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InstallLocalNode 安装本地节点
|
||||||
|
func InstallLocalNode() error {
|
||||||
|
var targetDir = Tea.Root
|
||||||
|
var nodeDir = targetDir + "/edge-node"
|
||||||
|
var apiAddr = "http://127.0.0.1:8001" // 先固定
|
||||||
|
|
||||||
|
// 查找节点安装文件
|
||||||
|
var zipFile = Tea.Root + "/edge-api/deploy/edge-node-linux-" + runtime.GOARCH + "-v" + teaconst.Version /** 默认和管理系统一致 **/ + ".zip"
|
||||||
|
{
|
||||||
|
stat, err := os.Stat(zipFile)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return errors.New("installer file not found in '" + zipFile + "'")
|
||||||
|
}
|
||||||
|
return fmt.Errorf("open installer file failed: %w", err)
|
||||||
|
}
|
||||||
|
if stat.IsDir() {
|
||||||
|
return errors.New("invalid installer file '" + zipFile + "'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解压节点
|
||||||
|
var unzip = utils.NewUnzip(zipFile, targetDir)
|
||||||
|
err := unzip.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unzip installer file failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建节点
|
||||||
|
rpcClient, err := rpc.SharedRPC()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create rpc client failed: %w", err)
|
||||||
|
}
|
||||||
|
var ctx = rpcClient.Context(0)
|
||||||
|
nodeClustersResp, err := rpcClient.NodeClusterRPC().ListEnabledNodeClusters(ctx, &pb.ListEnabledNodeClustersRequest{
|
||||||
|
IdDesc: true,
|
||||||
|
Offset: 0,
|
||||||
|
Size: 1,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(nodeClustersResp.NodeClusters) == 0 {
|
||||||
|
return errors.New("no clusters yet, please create a cluster at least")
|
||||||
|
}
|
||||||
|
var clusterId = nodeClustersResp.NodeClusters[0].Id
|
||||||
|
|
||||||
|
// 检查节点是否已生成
|
||||||
|
countNodesResp, err := rpcClient.NodeRPC().CountAllEnabledNodesMatch(ctx, &pb.CountAllEnabledNodesMatchRequest{
|
||||||
|
NodeClusterId: clusterId,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if countNodesResp.Count > 0 {
|
||||||
|
// 这里先不判断是否有本地节点,只要有节点,就不允许再次执行
|
||||||
|
return errors.New("there are already nodes in the cluster")
|
||||||
|
}
|
||||||
|
|
||||||
|
createNodeResp, err := rpcClient.NodeRPC().CreateNode(ctx, &pb.CreateNodeRequest{
|
||||||
|
Name: "本地节点",
|
||||||
|
NodeClusterId: clusterId,
|
||||||
|
NodeLogin: nil,
|
||||||
|
NodeGroupId: 0,
|
||||||
|
DnsRoutes: nil,
|
||||||
|
NodeRegionId: 0,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var nodeId = createNodeResp.NodeId
|
||||||
|
nodeResp, err := rpcClient.NodeRPC().FindEnabledNode(ctx, &pb.FindEnabledNodeRequest{NodeId: nodeId})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if nodeResp.Node == nil {
|
||||||
|
return errors.New("could not find local node with created id '" + types.String(nodeId) + "'")
|
||||||
|
}
|
||||||
|
var node = nodeResp.Node
|
||||||
|
|
||||||
|
// 生成节点配置
|
||||||
|
var apiConfig = &configs.APIConfig{
|
||||||
|
RPCEndpoints: []string{apiAddr},
|
||||||
|
RPCDisableUpdate: true,
|
||||||
|
NodeId: node.UniqueId,
|
||||||
|
Secret: node.Secret,
|
||||||
|
}
|
||||||
|
apiConfigYAML, err := yaml.Marshal(apiConfig)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("encode config failed: %w", err)
|
||||||
|
}
|
||||||
|
err = os.WriteFile(nodeDir+"/configs/api_node.yaml", apiConfigYAML, 0666)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("write config file failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试节点
|
||||||
|
{
|
||||||
|
var cmd = executils.NewTimeoutCmd(5*time.Second, nodeDir+"/bin/edge-node", "test")
|
||||||
|
cmd.WithStdout()
|
||||||
|
cmd.WithStderr()
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("node test failed: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动节点
|
||||||
|
{
|
||||||
|
var cmd = executils.NewTimeoutCmd(5*time.Second, nodeDir+"/bin/edge-node", "start")
|
||||||
|
cmd.WithStdout()
|
||||||
|
cmd.WithStderr()
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("node start failed: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package nodeutils_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInstallLocalNode(t *testing.T) {
|
||||||
|
err := nodeutils.InstallLocalNode()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user