mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-11-03 23:20:26 +08:00
实现单体实例安装工具
This commit is contained in:
2
cmd/standalone-instance-installer/.gitignore
vendored
Normal file
2
cmd/standalone-instance-installer/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
standalone-instance-installer*
|
||||||
|
prepare.sh
|
||||||
17
cmd/standalone-instance-installer/build.sh
Executable file
17
cmd/standalone-instance-installer/build.sh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
OS="${1}"
|
||||||
|
ARCH="${2}"
|
||||||
|
TAG="${3}"
|
||||||
|
|
||||||
|
if [ -z "$OS" ]; then
|
||||||
|
echo "usage: build.sh OS ARCH"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$ARCH" ]; then
|
||||||
|
echo "usage: build.sh OS ARCH"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
env GOOS=linux GOARCH="${ARCH}" go build -tags="${TAG}" -trimpath -ldflags="-s -w" -o "standalone-instance-installer-${OS}-${ARCH}" main.go
|
||||||
74
cmd/standalone-instance-installer/main.go
Normal file
74
cmd/standalone-instance-installer/main.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/instances"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
"github.com/iwind/TeaGo/lists"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
dbPasswordData, err := os.ReadFile("/usr/local/mysql/generated-password.txt")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("[ERROR]read mysql password failed: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var dbPassword = strings.TrimSpace(string(dbPasswordData))
|
||||||
|
|
||||||
|
var isTesting = lists.ContainsString(os.Args, "-test") || lists.ContainsString(os.Args, "--test")
|
||||||
|
if isTesting {
|
||||||
|
fmt.Println("testing mode ...")
|
||||||
|
}
|
||||||
|
|
||||||
|
var instance = instances.NewInstance(instances.Options{
|
||||||
|
IsTesting: isTesting,
|
||||||
|
Verbose: lists.ContainsString(os.Args, "-v"),
|
||||||
|
Cacheable: true,
|
||||||
|
WorkDir: "",
|
||||||
|
SrcDir: "/usr/local/goedge/src",
|
||||||
|
DB: struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Name string
|
||||||
|
}{
|
||||||
|
Host: "127.0.0.1",
|
||||||
|
Port: 3306,
|
||||||
|
Username: "root",
|
||||||
|
Password: dbPassword,
|
||||||
|
Name: "edges",
|
||||||
|
},
|
||||||
|
AdminNode: struct {
|
||||||
|
Port int
|
||||||
|
}{
|
||||||
|
Port: 7788,
|
||||||
|
},
|
||||||
|
APINode: struct {
|
||||||
|
HTTPPort int
|
||||||
|
RestHTTPPort int
|
||||||
|
}{
|
||||||
|
HTTPPort: 8001,
|
||||||
|
RestHTTPPort: 8002,
|
||||||
|
},
|
||||||
|
Node: struct{ HTTPPort int }{
|
||||||
|
HTTPPort: 8080,
|
||||||
|
},
|
||||||
|
UserNode: struct {
|
||||||
|
HTTPPort int
|
||||||
|
}{
|
||||||
|
HTTPPort: 7799,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
err = instance.SetupAll()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("[ERROR]setup failed: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("ok")
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/go-sql-driver/mysql"
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
@@ -759,10 +758,5 @@ func (this *MetricStatDAO) canIgnore(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 忽略 Error 1213: Deadlock found 错误
|
// 忽略 Error 1213: Deadlock found 错误
|
||||||
mysqlErr, ok := err.(*mysql.MySQLError)
|
return CheckSQLErrCode(err, 1213)
|
||||||
if ok && mysqlErr.Number == 1213 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
"github.com/TeaOSLab/EdgeAPI/internal/goman"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/go-sql-driver/mysql"
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
@@ -289,10 +288,5 @@ func (this *MetricSumStatDAO) canIgnore(err error) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 忽略 Error 1213: Deadlock found 错误
|
// 忽略 Error 1213: Deadlock found 错误
|
||||||
mysqlErr, ok := err.(*mysql.MySQLError)
|
return CheckSQLErrCode(err, 1213)
|
||||||
if ok && mysqlErr.Number == 1213 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/go-sql-driver/mysql"
|
"github.com/go-sql-driver/mysql"
|
||||||
"github.com/iwind/TeaGo/dbs"
|
"github.com/iwind/TeaGo/dbs"
|
||||||
"github.com/iwind/TeaGo/types"
|
"github.com/iwind/TeaGo/types"
|
||||||
@@ -60,8 +61,8 @@ func CheckSQLErrCode(err error, code uint16) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 快速判断错误方法
|
// 快速判断错误方法
|
||||||
mysqlErr, ok := err.(*mysql.MySQLError)
|
var mysqlErr *mysql.MySQLError
|
||||||
if ok && mysqlErr.Number == code { // Error 1050: Table 'xxx' already exists
|
if errors.As(err, &mysqlErr) && mysqlErr.Number == code { // Error 1050: Table 'xxx' already exists
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +87,6 @@ func IsMySQLError(err error) bool {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_, ok := err.(*mysql.MySQLError)
|
var mysqlErr *mysql.MySQLError
|
||||||
return ok
|
return errors.As(err, &mysqlErr)
|
||||||
}
|
}
|
||||||
|
|||||||
39
internal/db/models/utils_test.go
Normal file
39
internal/db/models/utils_test.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package models_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
|
"github.com/iwind/TeaGo/assert"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIsMySQLError(t *testing.T) {
|
||||||
|
var a = assert.NewAssertion(t)
|
||||||
|
|
||||||
|
{
|
||||||
|
var err error
|
||||||
|
a.IsFalse(models.IsMySQLError(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var err = errors.New("hello")
|
||||||
|
a.IsFalse(models.IsMySQLError(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
db, err := dbs.Default()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = db.Close()
|
||||||
|
}()
|
||||||
|
_, err = db.Exec("SELECT abc")
|
||||||
|
a.IsTrue(models.IsMySQLError(err))
|
||||||
|
a.IsTrue(models.CheckSQLErrCode(err, 1054))
|
||||||
|
a.IsFalse(models.CheckSQLErrCode(err, 1000))
|
||||||
|
}
|
||||||
|
}
|
||||||
39
internal/instances/README.md
Normal file
39
internal/instances/README.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# 实例
|
||||||
|
|
||||||
|
## 目录结构:
|
||||||
|
~~~
|
||||||
|
/opt/cache
|
||||||
|
/usr/local/goedge/
|
||||||
|
edge-admin/
|
||||||
|
configs/
|
||||||
|
api_admin.yaml
|
||||||
|
api_db.yaml
|
||||||
|
server.yaml
|
||||||
|
edge-api/
|
||||||
|
configs/api.yaml
|
||||||
|
configs/db.yaml
|
||||||
|
api-node/
|
||||||
|
configs/api_node.yaml
|
||||||
|
api-user/
|
||||||
|
configs/api_user.yaml
|
||||||
|
src/
|
||||||
|
/usr/bin/
|
||||||
|
edge-admin -> ...
|
||||||
|
edge-api -> ...
|
||||||
|
edge-node -> ...
|
||||||
|
edge-user -> ...
|
||||||
|
/usr/local/mysql
|
||||||
|
~~~
|
||||||
|
|
||||||
|
* 其中 `->` 表示软链接。
|
||||||
|
* `src/` 目录下放置zip格式的待安装压缩包
|
||||||
|
|
||||||
|
## 端口
|
||||||
|
* Admin:7788
|
||||||
|
* API:8001
|
||||||
|
* API HTTP:8002
|
||||||
|
* User: 7799
|
||||||
|
* Server: 8080
|
||||||
|
|
||||||
|
## 数据库
|
||||||
|
数据库名称为 `edges`
|
||||||
16
internal/instances/api_config.go
Normal file
16
internal/instances/api_config.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package instances
|
||||||
|
|
||||||
|
import "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
type APIConfig struct {
|
||||||
|
RPCEndpoints []string `yaml:"rpc.endpoints,flow,omitempty" json:"rpc.endpoints"`
|
||||||
|
RPCDisableUpdate bool `yaml:"rpc.disableUpdate,omitempty" json:"rpc.disableUpdate"`
|
||||||
|
NodeId string `yaml:"nodeId" json:"nodeId"`
|
||||||
|
Secret string `yaml:"secret" json:"secret"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *APIConfig) AsYAML() ([]byte, error) {
|
||||||
|
return yaml.Marshal(this)
|
||||||
|
}
|
||||||
1009
internal/instances/instance.go
Normal file
1009
internal/instances/instance.go
Normal file
File diff suppressed because it is too large
Load Diff
98
internal/instances/instance_test.go
Normal file
98
internal/instances/instance_test.go
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package instances_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/instances"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var instance = instances.NewInstance(instances.Options{
|
||||||
|
Cacheable: true,
|
||||||
|
WorkDir: Tea.Root + "/standalone-instance",
|
||||||
|
SrcDir: Tea.Root + "/standalone-instance/src",
|
||||||
|
DB: struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Name string
|
||||||
|
}{
|
||||||
|
Host: "127.0.0.1",
|
||||||
|
Port: 3306,
|
||||||
|
Username: "root",
|
||||||
|
Password: "123456",
|
||||||
|
Name: "edges2",
|
||||||
|
},
|
||||||
|
AdminNode: struct {
|
||||||
|
Port int
|
||||||
|
}{
|
||||||
|
Port: 7788,
|
||||||
|
},
|
||||||
|
APINode: struct {
|
||||||
|
HTTPPort int
|
||||||
|
RestHTTPPort int
|
||||||
|
}{
|
||||||
|
HTTPPort: 8001,
|
||||||
|
RestHTTPPort: 8002,
|
||||||
|
},
|
||||||
|
Node: struct{ HTTPPort int }{
|
||||||
|
HTTPPort: 8080,
|
||||||
|
},
|
||||||
|
UserNode: struct {
|
||||||
|
HTTPPort int
|
||||||
|
}{
|
||||||
|
HTTPPort: 7799,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
func TestInstanceSetupAll(t *testing.T) {
|
||||||
|
err := instance.SetupAll()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstance_SetupDB(t *testing.T) {
|
||||||
|
err := instance.SetupDB()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstance_SetupAdminNode(t *testing.T) {
|
||||||
|
err := instance.SetupAdminNode()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstance_SetupAPINode(t *testing.T) {
|
||||||
|
err := instance.SetupAPINode()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstance_SetupUserNode(t *testing.T) {
|
||||||
|
err := instance.SetupUserNode()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstance_SetupNode(t *testing.T) {
|
||||||
|
err := instance.SetupNode()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInstance_Clean(t *testing.T) {
|
||||||
|
err := instance.Clean()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
32
internal/instances/options.go
Normal file
32
internal/instances/options.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2024 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package instances
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
IsTesting bool
|
||||||
|
Verbose bool
|
||||||
|
Cacheable bool
|
||||||
|
|
||||||
|
WorkDir string
|
||||||
|
SrcDir string
|
||||||
|
DB struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
AdminNode struct {
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
APINode struct {
|
||||||
|
HTTPPort int
|
||||||
|
RestHTTPPort int
|
||||||
|
}
|
||||||
|
Node struct {
|
||||||
|
HTTPPort int
|
||||||
|
}
|
||||||
|
UserNode struct {
|
||||||
|
HTTPPort int
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user