Compare commits

..

50 Commits

Author SHA1 Message Date
刘祥超
7d4c80eedb 调整版本为0.2.2 2021-06-17 18:08:14 +08:00
刘祥超
af4bd950b7 用户增加AccessKey管理 2021-06-16 10:48:45 +08:00
刘祥超
f85f9b0920 调整版本为0.2.1 2021-06-16 08:30:44 +08:00
刘祥超
89ea96c28e Update README.md 2021-06-15 14:32:04 +08:00
刘祥超
6f2e3f5f13 ReadMe增加对Gitee的感谢 2021-06-15 11:15:03 +08:00
刘祥超
ee91e8312f 优化界面 2021-06-15 10:32:40 +08:00
刘祥超
004a29846e 优化界面 2021-06-14 19:53:53 +08:00
刘祥超
01eb22a0fe WAF的出站规则支持请求相关参数 2021-06-12 10:53:59 +08:00
刘祥超
bb2d2c5c86 优化安装过程中的错误提示 2021-06-11 12:00:11 +08:00
刘祥超
e0c36e3c45 优化界面 2021-06-10 19:19:43 +08:00
刘祥超
9fa9f74b90 优化界面 2021-06-10 10:39:05 +08:00
刘祥超
7308748957 去除一处不必要的注释 2021-06-09 22:15:23 +08:00
刘祥超
748105eae1 路径规则、重写规则、URL跳转规则均支持匹配条件;URL跳转规则增加排序、是否启用功能 2021-06-09 21:45:26 +08:00
刘祥超
33f45dfc92 请求条件支持参数匹配 2021-06-09 17:14:31 +08:00
刘祥超
dda1e3054a 优化代码 2021-06-08 22:58:39 +08:00
刘祥超
a8030fa045 优化缓存条件设置,支持不缓存条件设置,支持条件排序等 2021-06-08 22:46:08 +08:00
刘祥超
9de66f080d 优化代码 2021-06-08 15:20:59 +08:00
刘祥超
7a57180ecd 请求统计增加即时、按天 2021-06-08 15:08:38 +08:00
刘祥超
48e1e0b631 增加服务流量统计 2021-06-08 11:22:44 +08:00
刘祥超
d5fe38ba8d 优化界面 2021-06-07 16:23:37 +08:00
刘祥超
cb8035452b 支持UDP代理 2021-06-07 15:43:43 +08:00
刘祥超
c2cab60940 边缘节点IP支持IPV6 2021-06-07 10:00:06 +08:00
刘祥超
58e7e1b283 WAF策略列表支持搜索 2021-06-07 08:58:54 +08:00
刘祥超
5d108b1b6f 优化界面 2021-06-07 08:44:06 +08:00
刘祥超
8fbbbd65c4 缓存策略列表支持搜索 2021-06-07 08:43:57 +08:00
刘祥超
7e0a96857c 创建服务的时候默认增加http和https端口绑定 2021-06-06 14:10:45 +08:00
刘祥超
139b0e037e 日志级别增加success 2021-06-06 13:40:47 +08:00
刘祥超
7cbfa2458b 优化交互 2021-06-06 09:22:59 +08:00
刘祥超
abc5162bca 优化添加端口、添加源站相关交互 2021-06-05 20:27:57 +08:00
刘祥超
d3cf71dad8 改进界面 2021-06-05 16:53:26 +08:00
刘祥超
0909164a06 域名服务集群创建时可以选择开启访问日志 2021-06-05 15:38:57 +08:00
刘祥超
6df50d97e9 改进RPC相关提示 2021-06-05 11:35:36 +08:00
刘祥超
98f8fb3bec 服务访问日志增加关键词搜索 2021-06-04 10:15:31 +08:00
刘祥超
0f5f175f08 DNS访问日志可以使用关键词搜索 2021-06-04 09:09:23 +08:00
刘祥超
16a2a6cb35 修改域名服务界面细节 2021-06-03 22:09:12 +08:00
刘祥超
da38fcaa0c 实现在域名解析中使用EdgeDNS 2021-06-02 18:14:00 +08:00
刘祥超
b6fd9aeb14 域名服务增加访问日志 2021-06-02 11:53:08 +08:00
刘祥超
201c3e2f97 优化域名服务相关功能 2021-06-01 16:42:25 +08:00
刘祥超
d834c2517a [域名服务]实现基本的线路配置 2021-05-30 16:31:12 +08:00
刘祥超
dc98081a92 更新go.mod 2021-05-30 11:48:30 +08:00
刘祥超
30e9753c80 实现基本的域名、记录管理 2021-05-27 17:09:53 +08:00
刘祥超
70cd06dc85 实现最基本的域名服务节点管理 2021-05-26 14:43:29 +08:00
刘祥超
194a919a73 延长缓存相关操作超时时间 2021-05-25 18:24:45 +08:00
刘祥超
b57b242232 优化API命名 2021-05-25 17:48:51 +08:00
刘祥超
cc76172a46 实现域名服务器集群管理 2021-05-25 15:47:40 +08:00
刘祥超
5858f98ec6 改进节点日志显示 2021-05-25 14:14:57 +08:00
刘祥超
941e000142 修改版本号为0.2.0 2021-05-25 12:14:53 +08:00
刘祥超
7dd58fd9dc 优化日志显示 2021-05-25 12:14:21 +08:00
刘祥超
2b560a225e 修改版本号为0.1.2 2021-05-24 16:51:57 +08:00
刘祥超
c768f22059 使用CodeMirror高亮各处的配置信息 2021-05-24 11:23:20 +08:00
355 changed files with 9733 additions and 1580 deletions

View File

@@ -9,7 +9,8 @@
* `高扩展性` - 可以自由扩展新的节点,支持亿级数据
## 文档
[点这里查看文档](http://edge.teaos.cn/docs)
* [新手指南](https://edge.teaos.cn/docs/QuickStart/Index.md)
* [文档](http://edge.teaos.cn/docs)
## 架构
![架构](doc/architect-zh.jpg)
@@ -23,4 +24,5 @@
有什么问题和建议都可以加入QQ群 `659832182`
## 感谢
* 感谢[JetBrains公司](https://www.jetbrains.com/)提供免费的IDE开发Licence。
* 感谢[JetBrains公司](https://www.jetbrains.com/)提供免费的IDE开发Licence。
* 感谢[Gitee](https://gitee.com/)提供国内源代码托管平台

5
go.mod
View File

@@ -9,13 +9,12 @@ require (
github.com/cespare/xxhash v1.1.0
github.com/go-sql-driver/mysql v1.5.0
github.com/go-yaml/yaml v2.1.0+incompatible
github.com/iwind/TeaGo v0.0.0-20201206115018-cdd967bfb13d
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f
github.com/miekg/dns v1.1.35
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/tealeg/xlsx/v3 v3.2.3
github.com/xlzd/gotp v0.0.0-20181030022105-c8557ba2c119
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c // indirect
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c
google.golang.org/grpc v1.32.0
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
)

12
go.sum
View File

@@ -9,6 +9,7 @@ github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiU
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@@ -53,9 +54,8 @@ github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iwind/TeaGo v0.0.0-20200923021120-f5d76441fe9e/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20201206115018-cdd967bfb13d h1:J4ohNUwOqCQkY62LFwaygfGtHJj+87pnzr+RJxEYSBo=
github.com/iwind/TeaGo v0.0.0-20201206115018-cdd967bfb13d/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f h1:r2O8PONj/KiuZjJHVHn7KlCePUIjNtgAmvLfgRafQ8o=
github.com/iwind/TeaGo v0.0.0-20210411134150-ddf57e240c2f/go.mod h1:KU4mS7QNiZ7QWEuDBk1zw0/Q2LrAPZv3tycEFBsuUwc=
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@@ -65,12 +65,10 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/miekg/dns v1.1.35 h1:oTfOaDH+mZkdcgdIjH6yBajRGtIwcwcaR+rt23ZSrJs=
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=

View File

@@ -1,6 +1,7 @@
package configloaders
import (
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
@@ -14,6 +15,7 @@ const (
AdminModuleCodeServer AdminModuleCode = "server" // 网站
AdminModuleCodeNode AdminModuleCode = "node" // 节点
AdminModuleCodeDNS AdminModuleCode = "dns" // DNS
AdminModuleCodeNS AdminModuleCode = "ns" // 域名服务
AdminModuleCodeAdmin AdminModuleCode = "admin" // 系统用户
AdminModuleCodeUser AdminModuleCode = "user" // 平台用户
AdminModuleCodeFinance AdminModuleCode = "finance" // 财务
@@ -68,7 +70,7 @@ func NotifyAdminModuleMappingChange() error {
return err
}
// 检查用户是否存在
// CheckAdmin 检查用户是否存在
func CheckAdmin(adminId int64) bool {
locker.Lock()
defer locker.Unlock()
@@ -82,7 +84,7 @@ func CheckAdmin(adminId int64) bool {
return ok
}
// 检查模块是否允许访问
// AllowModule 检查模块是否允许访问
func AllowModule(adminId int64, module string) bool {
locker.Lock()
defer locker.Unlock()
@@ -103,7 +105,7 @@ func AllowModule(adminId int64, module string) bool {
return false
}
// 获取管理员第一个可访问模块
// FindFirstAdminModule 获取管理员第一个可访问模块
func FindFirstAdminModule(adminId int64) (module AdminModuleCode, ok bool) {
locker.Lock()
defer locker.Unlock()
@@ -118,7 +120,7 @@ func FindFirstAdminModule(adminId int64) (module AdminModuleCode, ok bool) {
return
}
// 查找某个管理员名称
// FindAdminFullname 查找某个管理员名称
func FindAdminFullname(adminId int64) string {
locker.Lock()
defer locker.Unlock()
@@ -130,9 +132,9 @@ func FindAdminFullname(adminId int64) string {
return ""
}
// 所有权限列表
// AllModuleMaps 所有权限列表
func AllModuleMaps() []maps.Map {
return []maps.Map{
m := []maps.Map{
{
"name": "看板",
"code": AdminModuleCodeDashboard,
@@ -153,6 +155,15 @@ func AllModuleMaps() []maps.Map {
"code": AdminModuleCodeDNS,
"url": "/dns",
},
}
if teaconst.IsPlus {
m = append(m, maps.Map{
"name": "域名服务",
"code": AdminModuleCodeNS,
"url": "/ns",
})
}
m = append(m, []maps.Map{
{
"name": "平台用户",
"code": AdminModuleCodeUser,
@@ -178,5 +189,6 @@ func AllModuleMaps() []maps.Map {
"code": AdminModuleCodeSetting,
"url": "/settings",
},
}
}...)
return m
}

View File

@@ -1,7 +1,7 @@
package teaconst
const (
Version = "0.1.1"
Version = "0.2.2"
ProductName = "Edge Admin"
ProcessName = "edge-admin"

View File

@@ -131,6 +131,10 @@ func (this *RPCClient) ServerHTTPFirewallDailyStatRPC() pb.ServerHTTPFirewallDai
return pb.NewServerHTTPFirewallDailyStatServiceClient(this.pickConn())
}
func (this *RPCClient) ServerDailyStatRPC() pb.ServerDailyStatServiceClient {
return pb.NewServerDailyStatServiceClient(this.pickConn())
}
func (this *RPCClient) ServerGroupRPC() pb.ServerGroupServiceClient {
return pb.NewServerGroupServiceClient(this.pickConn())
}
@@ -332,6 +336,10 @@ func (this *RPCClient) UserBillRPC() pb.UserBillServiceClient {
return pb.NewUserBillServiceClient(this.pickConn())
}
func (this *RPCClient) UserAccessKeyRPC() pb.UserAccessKeyServiceClient {
return pb.NewUserAccessKeyServiceClient(this.pickConn())
}
func (this *RPCClient) LoginRPC() pb.LoginServiceClient {
return pb.NewLoginServiceClient(this.pickConn())
}
@@ -352,6 +360,30 @@ func (this *RPCClient) LatestItemRPC() pb.LatestItemServiceClient {
return pb.NewLatestItemServiceClient(this.pickConn())
}
func (this *RPCClient) NSClusterRPC() pb.NSClusterServiceClient {
return pb.NewNSClusterServiceClient(this.pickConn())
}
func (this *RPCClient) NSNodeRPC() pb.NSNodeServiceClient {
return pb.NewNSNodeServiceClient(this.pickConn())
}
func (this *RPCClient) NSDomainRPC() pb.NSDomainServiceClient {
return pb.NewNSDomainServiceClient(this.pickConn())
}
func (this *RPCClient) NSRecordRPC() pb.NSRecordServiceClient {
return pb.NewNSRecordServiceClient(this.pickConn())
}
func (this *RPCClient) NSRouteRPC() pb.NSRouteServiceClient {
return pb.NewNSRouteServiceClient(this.pickConn())
}
func (this *RPCClient) NSAccessLogRPC() pb.NSAccessLogServiceClient {
return pb.NewNSAccessLogServiceClient(this.pickConn())
}
// Context 构造Admin上下文
func (this *RPCClient) Context(adminId int64) context.Context {
ctx := context.Background()

View File

@@ -6,6 +6,7 @@ import (
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
"github.com/TeaOSLab/EdgeAdmin/internal/events"
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/logs"
@@ -34,7 +35,7 @@ func (this *AuthorityTask) Start() {
}
// 初始化的时候先获取一次
timeout := time.NewTimer(5 * time.Second)
timeout := time.NewTimer(3 * time.Second)
<-timeout.C
err := this.Loop()
if err != nil {
@@ -51,6 +52,11 @@ func (this *AuthorityTask) Start() {
}
func (this *AuthorityTask) Loop() error {
// 如果还没有安装直接返回
if !setup.IsConfigured() {
return nil
}
rpcClient, err := rpc.SharedRPC()
if err != nil {
return err

View File

@@ -4,6 +4,7 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/configs"
"github.com/TeaOSLab/EdgeAdmin/internal/events"
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeAdmin/internal/setup"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/Tea"
"github.com/iwind/TeaGo/logs"
@@ -42,6 +43,11 @@ func (this *SyncAPINodesTask) Start() {
}
func (this *SyncAPINodesTask) Loop() error {
// 如果还没有安装直接返回
if !setup.IsConfigured() {
return nil
}
// 获取所有可用的节点
rpcClient, err := rpc.SharedRPC()
if err != nil {

View File

@@ -20,7 +20,7 @@ func init() {
})
}
// 自动同步集群任务
// SyncClusterTask 自动同步集群任务
type SyncClusterTask struct {
}

View File

@@ -20,7 +20,7 @@ type ParentAction struct {
rpcClient *rpc.RPCClient
}
// 可以调用自身的一个简便方法
// Parent 可以调用自身的一个简便方法
func (this *ParentAction) Parent() *ParentAction {
return this
}
@@ -97,7 +97,7 @@ func (this *ParentAction) CreateLogInfo(description string, args ...interface{})
this.CreateLog(oplogs.LevelInfo, description, args...)
}
// 获取RPC
// RPC 获取RPC
func (this *ParentAction) RPC() *rpc.RPCClient {
if this.rpcClient != nil {
return this.rpcClient
@@ -114,7 +114,7 @@ func (this *ParentAction) RPC() *rpc.RPCClient {
return rpcClient
}
// 获取Context
// AdminContext 获取Context
func (this *ParentAction) AdminContext() context.Context {
if this.rpcClient == nil {
rpcClient, err := rpc.SharedRPC()

View File

@@ -3,6 +3,7 @@ package actionutils
import (
"fmt"
teaconst "github.com/TeaOSLab/EdgeAdmin/internal/const"
rpcerrors "github.com/TeaOSLab/EdgeCommon/pkg/rpc/errors"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/logs"
"net/http"
@@ -13,19 +14,20 @@ import (
"strings"
)
// 提示服务器错误信息
// Fail 提示服务器错误信息
func Fail(action actions.ActionWrapper, err error) {
if err != nil {
logs.Println("[" + reflect.TypeOf(action).String() + "]" + findStack(err.Error()))
}
action.Object().Fail(teaconst.ErrServer)
action.Object().Fail(teaconst.ErrServer + "" + err.Error() + "")
}
// 提示页面错误信息
// FailPage 提示页面错误信息
func FailPage(action actions.ActionWrapper, err error) {
if err != nil {
logs.Println("[" + reflect.TypeOf(action).String() + "]" + findStack(err.Error()))
}
err = rpcerrors.HumanError(err)
action.Object().ResponseWriter.WriteHeader(http.StatusInternalServerError)
if len(action.Object().Request.Header.Get("X-Requested-With")) > 0 {
action.Object().WriteString(teaconst.ErrServer)
@@ -37,18 +39,20 @@ func FailPage(action actions.ActionWrapper, err error) {
<div style="background: #eee; border: 1px #ccc solid; padding: 10px; font-size: 12px; line-height: 1.8">
` + teaconst.ErrServer + `
<div>可以通过查看 <strong><em>$安装目录/logs/run.log</em></strong> 日志文件查看具体的错误提示。</div>
<hr style="border-top: 1px #ccc solid"/>
<div style="color: red">Error: ` + err.Error() + `</pre>
</div>
</body>
</html>`)
}
}
// 判断动作的文件路径是否相当
// MatchPath 判断动作的文件路径是否相当
func MatchPath(action *actions.ActionObject, path string) bool {
return action.Request.URL.Path == path
}
// 查找父级Action
// FindParentAction 查找父级Action
func FindParentAction(actionPtr actions.ActionWrapper) *ParentAction {
parentActionValue := reflect.ValueOf(actionPtr).Elem().FieldByName("ParentAction")
if parentActionValue.IsValid() {

View File

@@ -2,6 +2,7 @@ package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
@@ -18,7 +19,18 @@ func (this *LogsAction) Init() {
func (this *LogsAction) RunGet(params struct {
NodeId int64
DayFrom string
DayTo string
Keyword string
Level string
}) {
this.Data["nodeId"] = params.NodeId
this.Data["dayFrom"] = params.DayFrom
this.Data["dayTo"] = params.DayTo
this.Data["keyword"] = params.Keyword
this.Data["level"] = params.Level
apiNodeResp, err := this.RPC().APINodeRPC().FindEnabledAPINode(this.AdminContext(), &pb.FindEnabledAPINodeRequest{NodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
@@ -36,8 +48,12 @@ func (this *LogsAction) RunGet(params struct {
}
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
Role: "api",
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleAPI,
NodeId: params.NodeId,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
})
if err != nil {
this.ErrorPage(err)
@@ -47,8 +63,13 @@ func (this *LogsAction) RunGet(params struct {
page := this.NewPage(count, 20)
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
NodeId: params.NodeId,
Role: "api",
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleAPI,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
Offset: page.Offset,
Size: page.Size,
})

View File

@@ -3,6 +3,7 @@ package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/lists"
@@ -79,9 +80,9 @@ func (this *CreateBatchAction) RunPost(params struct {
resp, err := this.RPC().NodeRPC().CreateNode(this.AdminContext(), &pb.CreateNodeRequest{
Name: ip,
NodeClusterId: params.ClusterId,
GroupId: params.GroupId,
RegionId: params.RegionId,
Login: nil,
NodeGroupId: params.GroupId,
NodeRegionId: params.RegionId,
NodeLogin: nil,
})
if err != nil {
this.ErrorPage(err)
@@ -90,6 +91,7 @@ func (this *CreateBatchAction) RunPost(params struct {
nodeId := resp.NodeId
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: nodeconfigs.NodeRoleNode,
Name: "IP地址",
Ip: ip,
CanAccess: true,

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
@@ -133,9 +134,9 @@ func (this *CreateNodeAction) RunPost(params struct {
createResp, err := this.RPC().NodeRPC().CreateNode(this.AdminContext(), &pb.CreateNodeRequest{
Name: params.Name,
NodeClusterId: params.ClusterId,
GroupId: params.GroupId,
RegionId: params.RegionId,
Login: loginInfo,
NodeGroupId: params.GroupId,
NodeRegionId: params.RegionId,
NodeLogin: loginInfo,
DnsDomainId: params.DnsDomainId,
DnsRoutes: dnsRouteCodes,
})
@@ -156,6 +157,7 @@ func (this *CreateNodeAction) RunPost(params struct {
} else {
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: nodeconfigs.NodeRoleNode,
Name: address.GetString("name"),
Ip: address.GetString("ip"),
CanAccess: address.GetBool("canAccess"),

View File

@@ -43,12 +43,12 @@ func (this *CreatePopupAction) RunPost(params struct {
}
this.Data["group"] = maps.Map{
"id": createResp.GroupId,
"id": createResp.NodeGroupId,
"name": params.Name,
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "创建集群分组", createResp.GroupId)
defer this.CreateLog(oplogs.LevelInfo, "创建节点分组", createResp.NodeGroupId)
this.Success()
}

View File

@@ -24,7 +24,7 @@ func (this *DeleteAction) RunPost(params struct {
this.Fail("此分组正在被使用不能删除,请修改节点后再删除")
}
_, err = this.RPC().NodeGroupRPC().DeleteNodeGroup(this.AdminContext(), &pb.DeleteNodeGroupRequest{GroupId: params.GroupId})
_, err = this.RPC().NodeGroupRPC().DeleteNodeGroup(this.AdminContext(), &pb.DeleteNodeGroupRequest{NodeGroupId: params.GroupId})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -18,7 +18,7 @@ func (this *IndexAction) Init() {
func (this *IndexAction) RunGet(params struct {
ClusterId int64
}) {
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithClusterIdRequest{
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithNodeClusterIdRequest{
NodeClusterId: params.ClusterId,
})
if err != nil {
@@ -27,7 +27,7 @@ func (this *IndexAction) RunGet(params struct {
}
groupMaps := []maps.Map{}
for _, group := range groupsResp.Groups {
for _, group := range groupsResp.NodeGroups {
countResp, err := this.RPC().NodeRPC().CountAllEnabledNodesWithNodeGroupId(this.AdminContext(), &pb.CountAllEnabledNodesWithNodeGroupIdRequest{NodeGroupId: group.Id})
if err != nil {
this.ErrorPage(err)

View File

@@ -18,13 +18,13 @@ func (this *SelectPopupAction) Init() {
func (this *SelectPopupAction) RunGet(params struct {
ClusterId int64
}) {
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithClusterIdRequest{NodeClusterId: params.ClusterId})
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithNodeClusterIdRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
}
groupMaps := []maps.Map{}
for _, group := range groupsResp.Groups {
for _, group := range groupsResp.NodeGroups {
groupMaps = append(groupMaps, maps.Map{
"id": group.Id,
"name": group.Name,
@@ -44,12 +44,12 @@ func (this *SelectPopupAction) RunPost(params struct {
this.Fail("请选择要使用的分组")
}
groupResp, err := this.RPC().NodeGroupRPC().FindEnabledNodeGroup(this.AdminContext(), &pb.FindEnabledNodeGroupRequest{GroupId: params.GroupId})
groupResp, err := this.RPC().NodeGroupRPC().FindEnabledNodeGroup(this.AdminContext(), &pb.FindEnabledNodeGroupRequest{NodeGroupId: params.GroupId})
if err != nil {
this.ErrorPage(err)
return
}
group := groupResp.Group
group := groupResp.NodeGroup
if group == nil {
this.NotFound("nodeGroup", params.GroupId)
return

View File

@@ -13,7 +13,7 @@ type SortAction struct {
func (this *SortAction) RunPost(params struct {
GroupIds []int64
}) {
_, err := this.RPC().NodeGroupRPC().UpdateNodeGroupOrders(this.AdminContext(), &pb.UpdateNodeGroupOrdersRequest{GroupIds: params.GroupIds})
_, err := this.RPC().NodeGroupRPC().UpdateNodeGroupOrders(this.AdminContext(), &pb.UpdateNodeGroupOrdersRequest{NodeGroupIds: params.GroupIds})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -19,12 +19,12 @@ func (this *UpdatePopupAction) Init() {
func (this *UpdatePopupAction) RunGet(params struct {
GroupId int64
}) {
groupResp, err := this.RPC().NodeGroupRPC().FindEnabledNodeGroup(this.AdminContext(), &pb.FindEnabledNodeGroupRequest{GroupId: params.GroupId})
groupResp, err := this.RPC().NodeGroupRPC().FindEnabledNodeGroup(this.AdminContext(), &pb.FindEnabledNodeGroupRequest{NodeGroupId: params.GroupId})
if err != nil {
this.ErrorPage(err)
return
}
group := groupResp.Group
group := groupResp.NodeGroup
if group == nil {
this.NotFound("nodeGroup", params.GroupId)
return
@@ -48,8 +48,8 @@ func (this *UpdatePopupAction) RunPost(params struct {
Field("name", params.Name).
Require("请输入分组名称")
_, err := this.RPC().NodeGroupRPC().UpdateNodeGroup(this.AdminContext(), &pb.UpdateNodeGroupRequest{
GroupId: params.GroupId,
Name: params.Name,
NodeGroupId: params.GroupId,
Name: params.Name,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -47,8 +47,8 @@ func (this *IndexAction) RunGet(params struct {
countResp, err := this.RPC().NodeRPC().CountAllEnabledNodesMatch(this.AdminContext(), &pb.CountAllEnabledNodesMatchRequest{
NodeClusterId: params.ClusterId,
GroupId: params.GroupId,
RegionId: params.RegionId,
NodeGroupId: params.GroupId,
NodeRegionId: params.RegionId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
@@ -65,12 +65,16 @@ func (this *IndexAction) RunGet(params struct {
Offset: page.Offset,
Size: page.Size,
NodeClusterId: params.ClusterId,
GroupId: params.GroupId,
RegionId: params.RegionId,
NodeGroupId: params.GroupId,
NodeRegionId: params.RegionId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
nodeMaps := []maps.Map{}
for _, node := range nodesResp.Nodes {
// 状态
@@ -87,7 +91,10 @@ func (this *IndexAction) RunGet(params struct {
}
// IP
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{NodeId: node.Id})
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: node.Id,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return
@@ -104,19 +111,19 @@ func (this *IndexAction) RunGet(params struct {
// 分组
var groupMap maps.Map = nil
if node.Group != nil {
if node.NodeGroup != nil {
groupMap = maps.Map{
"id": node.Group.Id,
"name": node.Group.Name,
"id": node.NodeGroup.Id,
"name": node.NodeGroup.Name,
}
}
// 区域
var regionMap maps.Map = nil
if node.Region != nil {
if node.NodeRegion != nil {
regionMap = maps.Map{
"id": node.Region.Id,
"name": node.Region.Name,
"id": node.NodeRegion.Id,
"name": node.NodeRegion.Name,
}
}
@@ -162,14 +169,14 @@ func (this *IndexAction) RunGet(params struct {
// 所有分组
groupMaps := []maps.Map{}
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithClusterIdRequest{
groupsResp, err := this.RPC().NodeGroupRPC().FindAllEnabledNodeGroupsWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodeGroupsWithNodeClusterIdRequest{
NodeClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
for _, group := range groupsResp.Groups {
for _, group := range groupsResp.NodeGroups {
countResp, err := this.RPC().NodeRPC().CountAllEnabledNodesWithNodeGroupId(this.AdminContext(), &pb.CountAllEnabledNodesWithNodeGroupIdRequest{NodeGroupId: group.Id})
if err != nil {
this.ErrorPage(err)

View File

@@ -30,7 +30,7 @@ func init() {
GetPost("/installManual", new(InstallManualAction)).
// 节点相关
Get("/node", new(node.NodeAction)).
Get("/node", new(node.IndexAction)).
GetPost("/node/update", new(node.UpdateAction)).
GetPost("/node/install", new(node.InstallAction)).
Post("/node/updateInstallStatus", new(node.UpdateInstallStatusAction)).

View File

@@ -21,7 +21,7 @@ func (this *InstallManualAction) RunGet(params struct {
}) {
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(this.AdminContext(), params.ClusterId, "manual")
nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithNodeClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithNodeClusterIdRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -23,7 +23,7 @@ func (this *InstallRemoteAction) RunGet(params struct {
}) {
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(this.AdminContext(), params.ClusterId, "install")
nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
nodesResp, err := this.RPC().NodeRPC().FindAllNotInstalledNodesWithNodeClusterId(this.AdminContext(), &pb.FindAllNotInstalledNodesWithNodeClusterIdRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -12,16 +12,16 @@ import (
"time"
)
type NodeAction struct {
type IndexAction struct {
actionutils.ParentAction
}
func (this *NodeAction) Init() {
func (this *IndexAction) Init() {
this.Nav("", "node", "node")
this.SecondMenu("nodes")
}
func (this *NodeAction) RunGet(params struct {
func (this *IndexAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
@@ -56,7 +56,10 @@ func (this *NodeAction) RunGet(params struct {
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{NodeId: params.NodeId})
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return
@@ -170,19 +173,19 @@ func (this *NodeAction) RunGet(params struct {
// 分组
var groupMap maps.Map = nil
if node.Group != nil {
if node.NodeGroup != nil {
groupMap = maps.Map{
"id": node.Group.Id,
"name": node.Group.Name,
"id": node.NodeGroup.Id,
"name": node.NodeGroup.Name,
}
}
// 区域
var regionMap maps.Map = nil
if node.Region != nil {
if node.NodeRegion != nil {
regionMap = maps.Map{
"id": node.Region.Id,
"name": node.Region.Name,
"id": node.NodeRegion.Id,
"name": node.NodeRegion.Name,
}
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/grants/grantutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/ipAddresses/ipaddressutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/shared"
"github.com/iwind/TeaGo/actions"
@@ -46,7 +47,10 @@ func (this *UpdateAction) RunGet(params struct {
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{NodeId: params.NodeId})
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return
@@ -141,19 +145,19 @@ func (this *UpdateAction) RunGet(params struct {
// 分组
var groupMap maps.Map = nil
if node.Group != nil {
if node.NodeGroup != nil {
groupMap = maps.Map{
"id": node.Group.Id,
"name": node.Group.Name,
"id": node.NodeGroup.Id,
"name": node.NodeGroup.Name,
}
}
// 区域
var regionMap maps.Map = nil
if node.Region != nil {
if node.NodeRegion != nil {
regionMap = maps.Map{
"id": node.Region.Id,
"name": node.Region.Name,
"id": node.NodeRegion.Id,
"name": node.NodeRegion.Name,
}
}
@@ -322,11 +326,11 @@ func (this *UpdateAction) RunPost(params struct {
// 保存
_, err := this.RPC().NodeRPC().UpdateNode(this.AdminContext(), &pb.UpdateNodeRequest{
NodeId: params.NodeId,
GroupId: params.GroupId,
RegionId: params.RegionId,
NodeGroupId: params.GroupId,
NodeRegionId: params.RegionId,
Name: params.Name,
NodeClusterId: params.ClusterId,
Login: loginInfo,
NodeLogin: loginInfo,
MaxCPU: params.MaxCPU,
IsOn: params.IsOn,
DnsDomainId: params.DnsDomainId,
@@ -340,14 +344,17 @@ func (this *UpdateAction) RunPost(params struct {
}
// 禁用老的IP地址
_, err = this.RPC().NodeIPAddressRPC().DisableAllIPAddressesWithNodeId(this.AdminContext(), &pb.DisableAllIPAddressesWithNodeIdRequest{NodeId: params.NodeId})
_, err = this.RPC().NodeIPAddressRPC().DisableAllIPAddressesWithNodeId(this.AdminContext(), &pb.DisableAllIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return
}
// 添加新的IP地址
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, params.IPAddressesJSON)
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, nodeconfigs.NodeRoleNode, params.IPAddressesJSON)
if err != nil {
this.ErrorPage(err)
return

View File

@@ -35,8 +35,8 @@ func (this *IndexAction) RunGet(params struct {
// 认证
var grantMap interface{} = nil
if cluster.GrantId > 0 {
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: cluster.GrantId})
if cluster.NodeGrantId > 0 {
grantResp, err := this.RPC().NodeGrantRPC().FindEnabledNodeGrant(this.AdminContext(), &pb.FindEnabledNodeGrantRequest{NodeGrantId: cluster.NodeGrantId})
if err != nil {
this.ErrorPage(err)
return
@@ -81,7 +81,7 @@ func (this *IndexAction) RunPost(params struct {
_, err := this.RPC().NodeClusterRPC().UpdateNodeCluster(this.AdminContext(), &pb.UpdateNodeClusterRequest{
NodeClusterId: params.ClusterId,
Name: params.Name,
GrantId: params.GrantId,
NodeGrantId: params.GrantId,
InstallDir: params.InstallDir,
})
if err != nil {

View File

@@ -108,8 +108,8 @@ func (this *UpdateNodeSSHAction) RunPost(params struct {
}
_, err := this.RPC().NodeRPC().UpdateNodeLogin(this.AdminContext(), &pb.UpdateNodeLoginRequest{
NodeId: params.NodeId,
Login: login,
NodeId: params.NodeId,
NodeLogin: login,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -24,7 +24,7 @@ func (this *UpgradeRemoteAction) RunGet(params struct {
this.Data["leftMenuItems"] = LeftMenuItemsForInstall(this.AdminContext(), params.ClusterId, "upgrade")
nodes := []maps.Map{}
resp, err := this.RPC().NodeRPC().FindAllUpgradeNodesWithClusterId(this.AdminContext(), &pb.FindAllUpgradeNodesWithClusterIdRequest{NodeClusterId: params.ClusterId})
resp, err := this.RPC().NodeRPC().FindAllUpgradeNodesWithNodeClusterId(this.AdminContext(), &pb.FindAllUpgradeNodesWithNodeClusterIdRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -9,20 +9,20 @@ import (
"strconv"
)
// 安装升级相关的左侧菜单
// LeftMenuItemsForInstall 安装升级相关的左侧菜单
func LeftMenuItemsForInstall(ctx context.Context, clusterId int64, selectedItem string) []maps.Map {
rpcClient, _ := rpc.SharedRPC()
countNotInstalled := int64(0)
countUpgrade := int64(0)
if rpcClient != nil {
{
resp, err := rpcClient.NodeRPC().CountAllNotInstalledNodesWithClusterId(ctx, &pb.CountAllNotInstalledNodesWithClusterIdRequest{NodeClusterId: clusterId})
resp, err := rpcClient.NodeRPC().CountAllNotInstalledNodesWithNodeClusterId(ctx, &pb.CountAllNotInstalledNodesWithNodeClusterIdRequest{NodeClusterId: clusterId})
if err == nil {
countNotInstalled = resp.Count
}
}
{
resp, err := rpcClient.NodeRPC().CountAllUpgradeNodesWithClusterId(ctx, &pb.CountAllUpgradeNodesWithClusterIdRequest{NodeClusterId: clusterId})
resp, err := rpcClient.NodeRPC().CountAllUpgradeNodesWithNodeClusterId(ctx, &pb.CountAllUpgradeNodesWithNodeClusterIdRequest{NodeClusterId: clusterId})
if err == nil {
countUpgrade = resp.Count
}

View File

@@ -97,7 +97,7 @@ func (this *CreateAction) RunPost(params struct {
createResp, err := this.RPC().NodeClusterRPC().CreateNodeCluster(this.AdminContext(), &pb.CreateNodeClusterRequest{
Name: params.Name,
GrantId: params.GrantId,
NodeGrantId: params.GrantId,
InstallDir: params.InstallDir,
DnsDomainId: params.DnsDomainId,
DnsName: params.DnsName,

View File

@@ -17,8 +17,8 @@ func (this *DeleteAction) RunPost(params struct {
defer this.CreateLog(oplogs.LevelInfo, "删除SSH认证 %d", params.GrantId)
// 检查是否有别的集群或节点正在使用
countResp, err := this.RPC().NodeClusterRPC().CountAllEnabledNodeClustersWithGrantId(this.AdminContext(), &pb.CountAllEnabledNodeClustersWithGrantIdRequest{
GrantId: params.GrantId,
countResp, err := this.RPC().NodeClusterRPC().CountAllEnabledNodeClustersWithNodeGrantId(this.AdminContext(), &pb.CountAllEnabledNodeClustersWithNodeGrantIdRequest{
NodeGrantId: params.GrantId,
})
if err != nil {
this.ErrorPage(err)
@@ -28,7 +28,7 @@ func (this *DeleteAction) RunPost(params struct {
this.Fail("有集群正在使用此服务,请修改后再删除")
}
countResp2, err := this.RPC().NodeRPC().CountAllEnabledNodesWithGrantId(this.AdminContext(), &pb.CountAllEnabledNodesWithGrantIdRequest{GrantId: params.GrantId})
countResp2, err := this.RPC().NodeRPC().CountAllEnabledNodesWithNodeGrantId(this.AdminContext(), &pb.CountAllEnabledNodesWithNodeGrantIdRequest{NodeGrantId: params.GrantId})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -46,7 +46,7 @@ func (this *GrantAction) RunGet(params struct {
// 使用此认证的集群
clusterMaps := []maps.Map{}
clustersResp, err := this.RPC().NodeClusterRPC().FindAllEnabledNodeClustersWithGrantId(this.AdminContext(), &pb.FindAllEnabledNodeClustersWithGrantIdRequest{GrantId: params.GrantId})
clustersResp, err := this.RPC().NodeClusterRPC().FindAllEnabledNodeClustersWithNodeGrantId(this.AdminContext(), &pb.FindAllEnabledNodeClustersWithNodeGrantIdRequest{NodeGrantId: params.GrantId})
if err != nil {
this.ErrorPage(err)
return
@@ -61,7 +61,7 @@ func (this *GrantAction) RunGet(params struct {
// 使用此认证的节点
nodeMaps := []maps.Map{}
nodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesWithGrantId(this.AdminContext(), &pb.FindAllEnabledNodesWithGrantIdRequest{GrantId: params.GrantId})
nodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesWithNodeGrantId(this.AdminContext(), &pb.FindAllEnabledNodesWithNodeGrantIdRequest{NodeGrantId: params.GrantId})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -42,7 +42,7 @@ func (this *IndexAction) RunGet(params struct {
grantMaps := []maps.Map{}
for _, grant := range grantsResp.NodeGrants {
// 集群数
countClustersResp, err := this.RPC().NodeClusterRPC().CountAllEnabledNodeClustersWithGrantId(this.AdminContext(), &pb.CountAllEnabledNodeClustersWithGrantIdRequest{GrantId: grant.Id})
countClustersResp, err := this.RPC().NodeClusterRPC().CountAllEnabledNodeClustersWithNodeGrantId(this.AdminContext(), &pb.CountAllEnabledNodeClustersWithNodeGrantIdRequest{NodeGrantId: grant.Id})
if err != nil {
this.ErrorPage(err)
return
@@ -50,7 +50,7 @@ func (this *IndexAction) RunGet(params struct {
countClusters := countClustersResp.Count
// 节点数
countNodesResp, err := this.RPC().NodeRPC().CountAllEnabledNodesWithGrantId(this.AdminContext(), &pb.CountAllEnabledNodesWithGrantIdRequest{GrantId: grant.Id})
countNodesResp, err := this.RPC().NodeRPC().CountAllEnabledNodesWithNodeGrantId(this.AdminContext(), &pb.CountAllEnabledNodesWithNodeGrantIdRequest{NodeGrantId: grant.Id})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -29,13 +29,7 @@ func (this *IndexAction) RunGet(params struct {
this.Data["searchType"] = params.SearchType
this.Data["isSearching"] = isSearching
// 搜索节点
if params.SearchType == "node" && len(params.Keyword) > 0 {
this.searchNodes(params.Keyword)
return
}
// 常用的节点
// 常用的集群
latestClusterMaps := []maps.Map{}
if !isSearching {
clustersResp, err := this.RPC().NodeClusterRPC().FindLatestNodeClusters(this.AdminContext(), &pb.FindLatestNodeClustersRequest{Size: 6})
@@ -52,6 +46,12 @@ func (this *IndexAction) RunGet(params struct {
}
this.Data["latestClusters"] = latestClusterMaps
// 搜索节点
if params.SearchType == "node" && len(params.Keyword) > 0 {
this.searchNodes(params.Keyword)
return
}
// 搜索集群
countResp, err := this.RPC().NodeClusterRPC().CountAllEnabledNodeClusters(this.AdminContext(), &pb.CountAllEnabledNodeClustersRequest{
Keyword: params.Keyword,
@@ -96,7 +96,7 @@ func (this *IndexAction) RunGet(params struct {
}
// 需要升级的节点
countUpgradeNodesResp, err := this.RPC().NodeRPC().CountAllUpgradeNodesWithClusterId(this.AdminContext(), &pb.CountAllUpgradeNodesWithClusterIdRequest{NodeClusterId: cluster.Id})
countUpgradeNodesResp, err := this.RPC().NodeRPC().CountAllUpgradeNodesWithNodeClusterId(this.AdminContext(), &pb.CountAllUpgradeNodesWithNodeClusterIdRequest{NodeClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return
@@ -186,7 +186,10 @@ func (this *IndexAction) searchNodes(keyword string) {
}
// IP
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{NodeId: node.Id})
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: node.Id,
Role: nodeconfigs.NodeRoleNode,
})
if err != nil {
this.ErrorPage(err)
return
@@ -203,19 +206,19 @@ func (this *IndexAction) searchNodes(keyword string) {
// 分组
var groupMap maps.Map = nil
if node.Group != nil {
if node.NodeGroup != nil {
groupMap = maps.Map{
"id": node.Group.Id,
"name": node.Group.Name,
"id": node.NodeGroup.Id,
"name": node.NodeGroup.Name,
}
}
// 区域
var regionMap maps.Map = nil
if node.Region != nil {
if node.NodeRegion != nil {
regionMap = maps.Map{
"id": node.Region.Id,
"name": node.Region.Name,
"id": node.NodeRegion.Id,
"name": node.NodeRegion.Name,
}
}

View File

@@ -93,25 +93,71 @@ func (this *IndexAction) RunGet(params struct{}) {
}
// 版本升级
this.Data["nodeUpgradeInfo"] = maps.Map{
"count": resp.NodeUpgradeInfo.CountNodes,
"version": resp.NodeUpgradeInfo.NewVersion,
if resp.NodeUpgradeInfo != nil {
this.Data["nodeUpgradeInfo"] = maps.Map{
"count": resp.NodeUpgradeInfo.CountNodes,
"version": resp.NodeUpgradeInfo.NewVersion,
}
} else {
this.Data["nodeUpgradeInfo"] = maps.Map{
"count": 0,
"version": "",
}
}
this.Data["monitorNodeUpgradeInfo"] = maps.Map{
"count": resp.MonitorNodeUpgradeInfo.CountNodes,
"version": resp.MonitorNodeUpgradeInfo.NewVersion,
if resp.MonitorNodeUpgradeInfo != nil {
this.Data["monitorNodeUpgradeInfo"] = maps.Map{
"count": resp.MonitorNodeUpgradeInfo.CountNodes,
"version": resp.MonitorNodeUpgradeInfo.NewVersion,
}
} else {
this.Data["monitorNodeUpgradeInfo"] = maps.Map{
"count": 0,
"version": "",
}
}
this.Data["apiNodeUpgradeInfo"] = maps.Map{
"count": resp.ApiNodeUpgradeInfo.CountNodes,
"version": resp.ApiNodeUpgradeInfo.NewVersion,
if resp.ApiNodeUpgradeInfo != nil {
this.Data["apiNodeUpgradeInfo"] = maps.Map{
"count": resp.ApiNodeUpgradeInfo.CountNodes,
"version": resp.ApiNodeUpgradeInfo.NewVersion,
}
} else {
this.Data["apiNodeUpgradeInfo"] = maps.Map{
"count": 0,
"version": "",
}
}
this.Data["userNodeUpgradeInfo"] = maps.Map{
"count": resp.UserNodeUpgradeInfo.CountNodes,
"version": resp.UserNodeUpgradeInfo.NewVersion,
if resp.UserNodeUpgradeInfo != nil {
this.Data["userNodeUpgradeInfo"] = maps.Map{
"count": resp.UserNodeUpgradeInfo.CountNodes,
"version": resp.UserNodeUpgradeInfo.NewVersion,
}
} else {
this.Data["userNodeUpgradeInfo"] = maps.Map{
"count": 0,
"version": 0,
}
}
this.Data["authorityNodeUpgradeInfo"] = maps.Map{
"count": resp.AuthorityNodeUpgradeInfo.CountNodes,
"version": resp.AuthorityNodeUpgradeInfo.NewVersion,
if resp.AuthorityNodeUpgradeInfo != nil {
this.Data["authorityNodeUpgradeInfo"] = maps.Map{
"count": resp.AuthorityNodeUpgradeInfo.CountNodes,
"version": resp.AuthorityNodeUpgradeInfo.NewVersion,
}
} else {
this.Data["authorityNodeUpgradeInfo"] = maps.Map{
"count": 0,
"version": "",
}
}
if resp.NsNodeUpgradeInfo != nil {
this.Data["nsNodeUpgradeInfo"] = maps.Map{
"count": resp.NsNodeUpgradeInfo.CountNodes,
"version": resp.NsNodeUpgradeInfo.NewVersion,
}
} else {
this.Data["nsNodeUpgradeInfo"] = maps.Map{
"count": 0,
"version": "",
}
}
this.Show()

View File

@@ -1,6 +1,7 @@
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/utils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
@@ -62,7 +63,7 @@ func (this *ClusterAction) RunGet(params struct {
this.Data["dnsInfo"] = dnsMap
// 节点DNS解析记录
nodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesDNSWithClusterId(this.AdminContext(), &pb.FindAllEnabledNodesDNSWithClusterIdRequest{NodeClusterId: params.ClusterId})
nodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodesDNSWithNodeClusterIdRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
@@ -74,10 +75,14 @@ func (this *ClusterAction) RunGet(params struct {
// 检查是否已解析
isResolved := false
if cluster.DnsDomainId > 0 && len(cluster.DnsName) > 0 && len(node.IpAddr) > 0 {
recordType := "A"
if utils.IsIPv6(node.IpAddr) {
recordType = "AAAA"
}
checkResp, err := this.RPC().DNSDomainRPC().ExistDNSDomainRecord(this.AdminContext(), &pb.ExistDNSDomainRecordRequest{
DnsDomainId: cluster.DnsDomainId,
Name: cluster.DnsName,
Type: "A",
Type: recordType,
Route: route.Code,
Value: node.IpAddr,
})
@@ -117,7 +122,7 @@ func (this *ClusterAction) RunGet(params struct {
this.Data["nodes"] = nodeMaps
// 代理服务解析记录
serversResp, err := this.RPC().ServerRPC().FindAllEnabledServersDNSWithClusterId(this.AdminContext(), &pb.FindAllEnabledServersDNSWithClusterIdRequest{NodeClusterId: params.ClusterId})
serversResp, err := this.RPC().ServerRPC().FindAllEnabledServersDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledServersDNSWithNodeClusterIdRequest{NodeClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
@@ -157,5 +162,25 @@ func (this *ClusterAction) RunGet(params struct {
}
this.Data["dnsHasChanges"] = checkChangesResp.IsChanged
// 需要解决的问题
issuesResp, err := this.RPC().DNSRPC().FindAllDNSIssues(this.AdminContext(), &pb.FindAllDNSIssuesRequest{
NodeClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
issueMaps := []maps.Map{}
for _, issue := range issuesResp.Issues {
issueMaps = append(issueMaps, maps.Map{
"target": issue.Target,
"targetId": issue.TargetId,
"type": issue.Type,
"description": issue.Description,
"params": issue.Params,
})
}
this.Data["issues"] = issueMaps
this.Show()
}

View File

@@ -1,26 +1,38 @@
package domainutils
import (
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
"net"
"regexp"
"strings"
)
// 校验域名格式
// ValidateDomainFormat 校验域名格式
func ValidateDomainFormat(domain string) bool {
pieces := strings.Split(domain, ".")
for _, piece := range pieces {
if !regexp.MustCompile(`^[a-z0-9-]+$`).MatchString(piece) {
if piece == "-" ||
strings.HasPrefix(piece, "-") ||
strings.HasSuffix(piece, "-") ||
strings.Contains(piece, "--") ||
len(piece) > 63 ||
!regexp.MustCompile(`^[a-z0-9-]+$`).MatchString(piece) {
return false
}
}
// 最后一段不能是全数字
if regexp.MustCompile(`^(\d+)$`).MatchString(pieces[len(pieces)-1]) {
return false
}
return true
}
// 转换线路列表
// ConvertRoutesToMaps 转换线路列表
func ConvertRoutesToMaps(routes []*pb.DNSRoute) []maps.Map {
result := []maps.Map{}
for _, route := range routes {
@@ -32,7 +44,7 @@ func ConvertRoutesToMaps(routes []*pb.DNSRoute) []maps.Map {
return result
}
// 筛选线路
// FilterRoutes 筛选线路
func FilterRoutes(routes []*pb.DNSRoute, allRoutes []*pb.DNSRoute) []*pb.DNSRoute {
routeCodes := []string{}
for _, route := range allRoutes {
@@ -46,3 +58,84 @@ func FilterRoutes(routes []*pb.DNSRoute, allRoutes []*pb.DNSRoute) []*pb.DNSRout
}
return result
}
// ValidateRecordName 校验记录名
func ValidateRecordName(name string) bool {
if name == "*" || name == "@" || len(name) == 0 {
return true
}
pieces := strings.Split(name, ".")
for _, piece := range pieces {
if piece == "-" ||
strings.HasPrefix(piece, "-") ||
strings.HasSuffix(piece, "-") ||
strings.Contains(piece, "--") ||
len(piece) > 63 ||
!regexp.MustCompile(`^[a-z0-9-]+$`).MatchString(piece) {
return false
}
}
return true
}
// ValidateRecordValue 校验记录值
func ValidateRecordValue(recordType dnsconfigs.RecordType, value string) (message string, ok bool) {
switch recordType {
case dnsconfigs.RecordTypeA:
if !regexp.MustCompile(`^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$`).MatchString(value) {
message = "请输入正确格式的IP"
return
}
if net.ParseIP(value) == nil {
message = "请输入正确格式的IP"
return
}
case dnsconfigs.RecordTypeCNAME:
if strings.HasSuffix(value, ".") {
value = value[:len(value)-1]
}
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
message = "请输入正确的域名"
return
}
case dnsconfigs.RecordTypeAAAA:
if !strings.Contains(value, ":") {
message = "请输入正确格式的IPv6地址"
return
}
if net.ParseIP(value) == nil {
message = "请输入正确格式的IPv6地址"
return
}
case dnsconfigs.RecordTypeNS:
if strings.HasSuffix(value, ".") {
value = value[:len(value)-1]
}
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
message = "请输入正确的DNS服务器域名"
return
}
case dnsconfigs.RecordTypeMX:
if strings.HasSuffix(value, ".") {
value = value[:len(value)-1]
}
if !strings.Contains(value, ".") || !ValidateDomainFormat(value) {
message = "请输入正确的邮件服务器域名"
return
}
case dnsconfigs.RecordTypeTXT:
if len(value) > 512 {
message = "文本长度不能超出512字节"
return
}
}
if len(value) > 512 {
message = "记录值长度不能超出512字节"
return
}
ok = true
return
}

View File

@@ -0,0 +1,61 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domainutils
import (
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/iwind/TeaGo/assert"
"testing"
)
func TestValidateRecordValue(t *testing.T) {
a := assert.NewAssertion(t)
// A
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeA, "1.2")
a.IsFalse(ok)
}
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeA, "1.2.3.400")
a.IsFalse(ok)
}
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeA, "1.2.3.4")
a.IsTrue(ok)
}
// CNAME
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeCNAME, "example.com")
a.IsTrue(ok)
}
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeCNAME, "example.com.")
a.IsTrue(ok)
}
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeCNAME, "hello, world")
a.IsFalse(ok)
}
// AAAA
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeAAAA, "1.2.3.4")
a.IsFalse(ok)
}
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeAAAA, "2001:0db8:85a3:0000:0000:8a2e:0370:7334")
a.IsTrue(ok)
}
// NS
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeNS, "1.2.3.4")
a.IsFalse(ok)
}
{
_, ok := ValidateRecordValue(dnsconfigs.RecordTypeNS, "example.com")
a.IsTrue(ok)
}
}

View File

@@ -43,7 +43,7 @@ func (this *NodesPopupAction) RunGet(params struct {
for _, cluster := range clustersResp.NodeClusters {
// 节点DNS解析记录
nodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesDNSWithClusterId(this.AdminContext(), &pb.FindAllEnabledNodesDNSWithClusterIdRequest{NodeClusterId: cluster.Id})
nodesResp, err := this.RPC().NodeRPC().FindAllEnabledNodesDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledNodesDNSWithNodeClusterIdRequest{NodeClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -41,7 +41,7 @@ func (this *ServersPopupAction) RunGet(params struct {
return
}
for _, cluster := range clustersResp.NodeClusters {
serversResp, err := this.RPC().ServerRPC().FindAllEnabledServersDNSWithClusterId(this.AdminContext(), &pb.FindAllEnabledServersDNSWithClusterIdRequest{NodeClusterId: cluster.Id})
serversResp, err := this.RPC().ServerRPC().FindAllEnabledServersDNSWithNodeClusterId(this.AdminContext(), &pb.FindAllEnabledServersDNSWithNodeClusterIdRequest{NodeClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -27,8 +27,9 @@ func (this *CreatePopupAction) RunGet(params struct{}) {
typeMaps := []maps.Map{}
for _, t := range typesResp.ProviderTypes {
typeMaps = append(typeMaps, maps.Map{
"name": t.Name,
"code": t.Code,
"name": t.Name,
"code": t.Code,
"description": t.Description,
})
}
this.Data["types"] = typeMaps
@@ -36,6 +37,21 @@ func (this *CreatePopupAction) RunGet(params struct{}) {
// 自动生成CustomHTTP私钥
this.Data["paramCustomHTTPSecret"] = rands.HexString(32)
// EdgeDNS集群列表
nsClustersResp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
nsClusterMaps := []maps.Map{}
for _, nsCluster := range nsClustersResp.NsClusters {
nsClusterMaps = append(nsClusterMaps, maps.Map{
"id": nsCluster.Id,
"name": nsCluster.Name,
})
}
this.Data["nsClusters"] = nsClusterMaps
this.Show()
}
@@ -59,6 +75,9 @@ func (this *CreatePopupAction) RunPost(params struct {
CloudFlareAPIKey string
CloudFlareEmail string
// Local EdgeDNS
ParamLocalEdgeDNSClusterId int64
// CustomHTTP
ParamCustomHTTPURL string
ParamCustomHTTPSecret string
@@ -109,6 +128,11 @@ func (this *CreatePopupAction) RunPost(params struct {
Email("请输入正确格式的邮箱地址")
apiParams["apiKey"] = params.CloudFlareAPIKey
apiParams["email"] = params.CloudFlareEmail
case "localEdgeDNS":
params.Must.
Field("ParamLocalEdgeDNSClusterId", params.ParamLocalEdgeDNSClusterId).
Gt(0, "请选择域名服务集群")
apiParams["clusterId"] = params.ParamLocalEdgeDNSClusterId
case "customHTTP":
params.Must.
Field("paramCustomHTTPURL", params.ParamCustomHTTPURL).

View File

@@ -39,12 +39,31 @@ func (this *ProviderAction) RunGet(params struct {
}
}
// 本地EdgeDNS相关
var localEdgeDNSMap = maps.Map{}
if provider.Type == "localEdgeDNS" {
nsClusterId := apiParams.GetInt64("clusterId")
nsClusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: nsClusterId})
if err != nil {
this.ErrorPage(err)
return
}
nsCluster := nsClusterResp.NsCluster
if nsCluster != nil {
localEdgeDNSMap = maps.Map{
"id": nsCluster.Id,
"name": nsCluster.Name,
}
}
}
this.Data["provider"] = maps.Map{
"id": provider.Id,
"name": provider.Name,
"type": provider.Type,
"typeName": provider.TypeName,
"apiParams": apiParams,
"id": provider.Id,
"name": provider.Name,
"type": provider.Type,
"typeName": provider.TypeName,
"apiParams": apiParams,
"localEdgeDNS": localEdgeDNSMap,
}
// 域名

View File

@@ -57,12 +57,28 @@ func (this *UpdatePopupAction) RunGet(params struct {
typeMaps := []maps.Map{}
for _, t := range typesResp.ProviderTypes {
typeMaps = append(typeMaps, maps.Map{
"name": t.Name,
"code": t.Code,
"name": t.Name,
"code": t.Code,
"description": t.Description,
})
}
this.Data["types"] = typeMaps
// EdgeDNS集群列表
nsClustersResp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
nsClusterMaps := []maps.Map{}
for _, nsCluster := range nsClustersResp.NsClusters {
nsClusterMaps = append(nsClusterMaps, maps.Map{
"id": nsCluster.Id,
"name": nsCluster.Name,
})
}
this.Data["nsClusters"] = nsClusterMaps
this.Show()
}
@@ -88,6 +104,9 @@ func (this *UpdatePopupAction) RunPost(params struct {
CloudFlareAPIKey string
CloudFlareEmail string
// Local EdgeDNS
ParamLocalEdgeDNSClusterId int64
// CustomHTTP
ParamCustomHTTPURL string
ParamCustomHTTPSecret string
@@ -140,6 +159,11 @@ func (this *UpdatePopupAction) RunPost(params struct {
Email("请输入正确格式的邮箱地址")
apiParams["apiKey"] = params.CloudFlareAPIKey
apiParams["email"] = params.CloudFlareEmail
case "localEdgeDNS":
params.Must.
Field("ParamLocalEdgeDNSClusterId", params.ParamLocalEdgeDNSClusterId).
Gt(0, "请选择域名服务集群")
apiParams["clusterId"] = params.ParamLocalEdgeDNSClusterId
case "customHTTP":
params.Must.
Field("paramCustomHTTPURL", params.ParamCustomHTTPURL).

View File

@@ -1,7 +1,6 @@
package nodes
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
@@ -13,14 +12,14 @@ type DeleteAction struct {
func (this *DeleteAction) RunPost(params struct {
NodeId int64
}) {
// 创建日志
defer this.CreateLogInfo("删除节点", params.NodeId)
_, err := this.RPC().NodeRPC().DeleteNode(this.AdminContext(), &pb.DeleteNodeRequest{NodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "删除节点", params.NodeId)
this.Success()
}

View File

@@ -3,12 +3,13 @@ package ipaddressutils
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
// 保存一组IP地址
func UpdateNodeIPAddresses(parentAction *actionutils.ParentAction, nodeId int64, ipAddressesJSON []byte) error {
// UpdateNodeIPAddresses 保存一组IP地址
func UpdateNodeIPAddresses(parentAction *actionutils.ParentAction, nodeId int64, role nodeconfigs.NodeRole, ipAddressesJSON []byte) error {
addresses := []maps.Map{}
err := json.Unmarshal(ipAddressesJSON, &addresses)
if err != nil {
@@ -29,6 +30,7 @@ func UpdateNodeIPAddresses(parentAction *actionutils.ParentAction, nodeId int64,
} else {
_, err = parentAction.RPC().NodeIPAddressRPC().CreateNodeIPAddress(parentAction.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: role,
Name: addr.GetString("name"),
Ip: addr.GetString("ip"),
CanAccess: addr.GetBool("canAccess"),

View File

@@ -34,7 +34,7 @@ func SendMessageToCluster(ctx context.Context, clusterId int64, code string, msg
}
// 获取所有节点
nodesResp, err := defaultRPCClient.NodeRPC().FindAllEnabledNodesWithClusterId(ctx, &pb.FindAllEnabledNodesWithClusterIdRequest{NodeClusterId: clusterId})
nodesResp, err := defaultRPCClient.NodeRPC().FindAllEnabledNodesWithNodeClusterId(ctx, &pb.FindAllEnabledNodesWithNodeClusterIdRequest{NodeClusterId: clusterId})
if err != nil {
return results, err
}

View File

@@ -0,0 +1,170 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package logs
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/lists"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
"net"
"regexp"
"strings"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "")
}
func (this *IndexAction) RunGet(params struct {
RequestId string
Keyword string
Day string
}) {
day := strings.ReplaceAll(params.Day, "-", "")
if !regexp.MustCompile(`^\d{8}$`).MatchString(day) {
day = timeutil.Format("Ymd")
}
this.Data["keyword"] = params.Keyword
this.Data["day"] = day[:4] + "-" + day[4:6] + "-" + day[6:]
this.Data["path"] = this.Request.URL.Path
var size = int64(10)
resp, err := this.RPC().NSAccessLogRPC().ListNSAccessLogs(this.AdminContext(), &pb.ListNSAccessLogsRequest{
RequestId: params.RequestId,
NsNodeId: 0,
NsDomainId: 0,
NsRecordId: 0,
Size: size,
Day: day,
Keyword: params.Keyword,
Reverse: false,
})
if err != nil {
this.ErrorPage(err)
return
}
ipList := []string{}
nodeIds := []int64{}
domainIds := []int64{}
if len(resp.NsAccessLogs) == 0 {
this.Data["accessLogs"] = []interface{}{}
} else {
this.Data["accessLogs"] = resp.NsAccessLogs
for _, accessLog := range resp.NsAccessLogs {
// IP
if len(accessLog.RemoteAddr) > 0 {
// 去掉端口
ip, _, err := net.SplitHostPort(accessLog.RemoteAddr)
if err == nil {
accessLog.RemoteAddr = ip
if !lists.ContainsString(ipList, ip) {
ipList = append(ipList, ip)
}
}
}
// 节点
if !lists.ContainsInt64(nodeIds, accessLog.NsNodeId) {
nodeIds = append(nodeIds, accessLog.NsNodeId)
}
// 域名
if !lists.ContainsInt64(domainIds, accessLog.NsDomainId) {
domainIds = append(domainIds, accessLog.NsDomainId)
}
}
}
this.Data["hasMore"] = resp.HasMore
this.Data["nextRequestId"] = resp.RequestId
// 上一个requestId
this.Data["hasPrev"] = false
this.Data["lastRequestId"] = ""
if len(params.RequestId) > 0 {
this.Data["hasPrev"] = true
prevResp, err := this.RPC().NSAccessLogRPC().ListNSAccessLogs(this.AdminContext(), &pb.ListNSAccessLogsRequest{
RequestId: params.RequestId,
NsNodeId: 0,
NsDomainId: 0,
NsRecordId: 0,
Day: day,
Keyword: params.Keyword,
Size: size,
Reverse: true,
})
if err != nil {
this.ErrorPage(err)
return
}
if int64(len(prevResp.NsAccessLogs)) == size {
this.Data["lastRequestId"] = prevResp.RequestId
}
}
// 根据IP查询区域
regionMap := map[string]string{} // ip => region
if len(ipList) > 0 {
resp, err := this.RPC().IPLibraryRPC().LookupIPRegions(this.AdminContext(), &pb.LookupIPRegionsRequest{IpList: ipList})
if err != nil {
this.ErrorPage(err)
return
}
if resp.IpRegionMap != nil {
for ip, region := range resp.IpRegionMap {
regionMap[ip] = region.Summary
}
}
}
this.Data["regions"] = regionMap
// 节点信息
nodeMap := map[int64]interface{}{} // node id => { ... }
for _, nodeId := range nodeIds {
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: nodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node != nil {
nodeMap[node.Id] = maps.Map{
"id": node.Id,
"name": node.Name,
"cluster": maps.Map{
"id": node.NsCluster.Id,
"name": node.NsCluster.Name,
},
}
}
}
this.Data["nodes"] = nodeMap
// 域名信息
domainMap := map[int64]interface{}{} // domain id => { ... }
for _, domainId := range domainIds {
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: domainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain != nil {
domainMap[domain.Id] = maps.Map{
"id": domain.Id,
"name": domain.Name,
}
}
}
this.Data["domains"] = domainMap
this.Show()
}

View File

@@ -0,0 +1,19 @@
package logs
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Data("teaMenu", "ns").
Data("teaSubMenu", "accessLog").
Prefix("/ns/clusters/accessLogs").
Get("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,108 @@
package cluster
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
// CreateNodeAction 创建节点
type CreateNodeAction struct {
actionutils.ParentAction
}
func (this *CreateNodeAction) Init() {
this.Nav("", "node", "create")
this.SecondMenu("nodes")
}
func (this *CreateNodeAction) RunGet(params struct {
ClusterId int64
}) {
this.Show()
}
func (this *CreateNodeAction) RunPost(params struct {
Name string
IpAddressesJSON []byte
ClusterId int64
Must *actions.Must
}) {
params.Must.
Field("name", params.Name).
Require("请输入节点名称")
if len(params.IpAddressesJSON) == 0 {
this.Fail("请至少添加一个IP地址")
}
// 检查cluster
if params.ClusterId <= 0 {
this.Fail("请选择所在集群")
}
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
if clusterResp.NsCluster == nil {
this.Fail("选择的集群不存在")
}
// IP地址
ipAddresses := []maps.Map{}
if len(params.IpAddressesJSON) > 0 {
err := json.Unmarshal(params.IpAddressesJSON, &ipAddresses)
if err != nil {
this.ErrorPage(err)
return
}
}
if len(ipAddresses) == 0 {
this.Fail("请至少输入一个IP地址")
}
// 保存
createResp, err := this.RPC().NSNodeRPC().CreateNSNode(this.AdminContext(), &pb.CreateNSNodeRequest{
Name: params.Name,
NodeClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
nodeId := createResp.NsNodeId
// IP地址
for _, address := range ipAddresses {
addressId := address.GetInt64("id")
if addressId > 0 {
_, err = this.RPC().NodeIPAddressRPC().UpdateNodeIPAddressNodeId(this.AdminContext(), &pb.UpdateNodeIPAddressNodeIdRequest{
AddressId: addressId,
NodeId: nodeId,
})
} else {
_, err = this.RPC().NodeIPAddressRPC().CreateNodeIPAddress(this.AdminContext(), &pb.CreateNodeIPAddressRequest{
NodeId: nodeId,
Role: nodeconfigs.NodeRoleDNS,
Name: address.GetString("name"),
Ip: address.GetString("ip"),
CanAccess: address.GetBool("canAccess"),
})
}
if err != nil {
this.ErrorPage(err)
return
}
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "创建域名服务节点 %d", nodeId)
this.Success()
}

View File

@@ -0,0 +1,38 @@
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) Init() {
this.Nav("", "delete", "index")
this.SecondMenu("nodes")
}
func (this *DeleteAction) RunGet(params struct{}) {
this.Show()
}
func (this *DeleteAction) RunPost(params struct {
ClusterId int64
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "删除域名服务集群 %d", params.ClusterId)
// TODO 如果有用户在使用此集群,就不能删除
// 删除
_, err := this.RPC().NSClusterRPC().DeleteNSCluster(this.AdminContext(), &pb.DeleteNSCluster{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,26 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteNodeAction struct {
actionutils.ParentAction
}
func (this *DeleteNodeAction) RunPost(params struct {
NodeId int64
}) {
defer this.CreateLogInfo("删除域名服务节点 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().DeleteNSNode(this.AdminContext(), &pb.DeleteNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,139 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import (
"encoding/json"
"fmt"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
"time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "node", "index")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
InstalledState int
ActiveState int
Keyword string
}) {
this.Data["installState"] = params.InstalledState
this.Data["activeState"] = params.ActiveState
this.Data["keyword"] = params.Keyword
countAllResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countAll"] = countAllResp.Count
countResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: params.ClusterId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
page := this.NewPage(countResp.Count)
this.Data["page"] = page.AsHTML()
nodesResp, err := this.RPC().NSNodeRPC().ListEnabledNSNodesMatch(this.AdminContext(), &pb.ListEnabledNSNodesMatchRequest{
Offset: page.Offset,
Size: page.Size,
NsClusterId: params.ClusterId,
InstallState: types.Int32(params.InstalledState),
ActiveState: types.Int32(params.ActiveState),
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
nodeMaps := []maps.Map{}
for _, node := range nodesResp.NsNodes {
// 状态
status := &nodeconfigs.NodeStatus{}
if len(node.StatusJSON) > 0 {
err = json.Unmarshal(node.StatusJSON, &status)
if err != nil {
logs.Error(err)
continue
}
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
}
// IP
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: node.Id,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddresses := []maps.Map{}
for _, addr := range ipAddressesResp.Addresses {
ipAddresses = append(ipAddresses, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
})
}
nodeMaps = append(nodeMaps, maps.Map{
"id": node.Id,
"name": node.Name,
"isInstalled": node.IsInstalled,
"isOn": node.IsOn,
"isUp": node.IsUp,
"installStatus": maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"error": node.InstallStatus.Error,
},
"status": maps.Map{
"isActive": status.IsActive,
"updatedAt": status.UpdatedAt,
"hostname": status.Hostname,
"cpuUsage": status.CPUUsage,
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
"memUsage": status.MemoryUsage,
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
},
"ipAddresses": ipAddresses,
})
}
this.Data["nodes"] = nodeMaps
// 记录最近访问
_, err = this.RPC().LatestItemRPC().IncreaseLatestItem(this.AdminContext(), &pb.IncreaseLatestItemRequest{
ItemType: "nsCluster",
ItemId: params.ClusterId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Show()
}

View File

@@ -0,0 +1,36 @@
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/cluster/node"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Helper(new(clusterutils.ClusterHelper)).
Data("teaMenu", "ns").
Data("teaSubMenu", "cluster").
Prefix("/ns/clusters/cluster").
Get("", new(IndexAction)).
GetPost("/delete", new(DeleteAction)).
GetPost("/createNode", new(CreateNodeAction)).
Post("/deleteNode", new(DeleteNodeAction)).
Get("/upgradeRemote", new(UpgradeRemoteAction)).
// 节点相关
Prefix("/ns/clusters/cluster/node").
Get("", new(node.IndexAction)).
Get("/logs", new(node.LogsAction)).
GetPost("/update", new(node.UpdateAction)).
GetPost("/install", new(node.InstallAction)).
Post("/status", new(node.StatusAction)).
Post("/updateInstallStatus", new(node.UpdateInstallStatusAction)).
EndAll()
})
}

View File

@@ -0,0 +1,137 @@
package node
import (
"encoding/json"
"fmt"
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
"time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "node", "node")
this.SecondMenu("nodes")
}
func (this *IndexAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterId := node.NsCluster.Id
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
cluster := clusterResp.NsCluster
if cluster != nil {
clusterMap = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"installDir": cluster.InstallDir,
}
}
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddressMaps := []maps.Map{}
for _, addr := range ipAddressesResp.Addresses {
ipAddressMaps = append(ipAddressMaps, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
})
}
// 运行状态
status := &nodeconfigs.NodeStatus{}
if len(node.StatusJSON) > 0 {
err = json.Unmarshal(node.StatusJSON, &status)
if err != nil {
this.ErrorPage(err)
return
}
status.IsActive = status.IsActive && time.Now().Unix()-status.UpdatedAt <= 60 // N秒之内认为活跃
}
// 检查是否有新版本
if len(status.OS) > 0 {
checkVersionResp, err := this.RPC().NSNodeRPC().CheckNSNodeLatestVersion(this.AdminContext(), &pb.CheckNSNodeLatestVersionRequest{
Os: status.OS,
Arch: status.Arch,
CurrentVersion: status.BuildVersion,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["shouldUpgrade"] = checkVersionResp.HasNewVersion
this.Data["newVersion"] = checkVersionResp.NewVersion
} else {
this.Data["shouldUpgrade"] = false
this.Data["newVersion"] = ""
}
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"ipAddresses": ipAddressMaps,
"cluster": clusterMap,
"installDir": node.InstallDir,
"isInstalled": node.IsInstalled,
"uniqueId": node.UniqueId,
"secret": node.Secret,
"isOn": node.IsOn,
"status": maps.Map{
"isActive": status.IsActive,
"updatedAt": status.UpdatedAt,
"hostname": status.Hostname,
"cpuUsage": status.CPUUsage,
"cpuUsageText": fmt.Sprintf("%.2f%%", status.CPUUsage*100),
"memUsage": status.MemoryUsage,
"memUsageText": fmt.Sprintf("%.2f%%", status.MemoryUsage*100),
"connectionCount": status.ConnectionCount,
"buildVersion": status.BuildVersion,
"cpuPhysicalCount": status.CPUPhysicalCount,
"cpuLogicalCount": status.CPULogicalCount,
"load1m": fmt.Sprintf("%.2f", status.Load1m),
"load5m": fmt.Sprintf("%.2f", status.Load5m),
"load15m": fmt.Sprintf("%.2f", status.Load15m),
"cacheTotalDiskSize": numberutils.FormatBytes(status.CacheTotalDiskSize),
"cacheTotalMemorySize": numberutils.FormatBytes(status.CacheTotalMemorySize),
},
}
this.Show()
}

View File

@@ -0,0 +1,117 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"strings"
)
// InstallAction 安装节点
type InstallAction struct {
actionutils.ParentAction
}
func (this *InstallAction) Init() {
this.Nav("", "node", "install")
this.SecondMenu("nodes")
}
func (this *InstallAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
// 节点
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
// 安装信息
if node.InstallStatus != nil {
this.Data["installStatus"] = maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"updatedAt": node.InstallStatus.UpdatedAt,
"error": node.InstallStatus.Error,
}
} else {
this.Data["installStatus"] = nil
}
// 集群
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterId := node.NsCluster.Id
clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId})
if err != nil {
this.ErrorPage(err)
return
}
cluster := clusterResp.NodeCluster
if cluster != nil {
clusterMap = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"installDir": cluster.InstallDir,
}
}
}
// API节点列表
apiNodesResp, err := this.RPC().APINodeRPC().FindAllEnabledAPINodes(this.AdminContext(), &pb.FindAllEnabledAPINodesRequest{})
if err != nil {
this.ErrorPage(err)
return
}
apiNodes := apiNodesResp.Nodes
apiEndpoints := []string{}
for _, apiNode := range apiNodes {
if !apiNode.IsOn {
continue
}
apiEndpoints = append(apiEndpoints, apiNode.AccessAddrs...)
}
this.Data["apiEndpoints"] = "\"" + strings.Join(apiEndpoints, "\", \"") + "\""
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"installDir": node.InstallDir,
"isInstalled": node.IsInstalled,
"uniqueId": node.UniqueId,
"secret": node.Secret,
"cluster": clusterMap,
}
this.Show()
}
// RunPost 开始安装
func (this *InstallAction) RunPost(params struct {
NodeId int64
Must *actions.Must
}) {
// 创建日志
defer this.CreateLogInfo("安装节点 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().InstallNSNode(this.AdminContext(), &pb.InstallNSNodeRequest{
NsNodeId: params.NodeId,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,75 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type LogsAction struct {
actionutils.ParentAction
}
func (this *LogsAction) Init() {
this.Nav("", "node", "log")
this.SecondMenu("nodes")
}
func (this *LogsAction) RunGet(params struct {
NodeId int64
DayFrom string
DayTo string
Keyword string
Level string
}) {
this.Data["nodeId"] = params.NodeId
this.Data["dayFrom"] = params.DayFrom
this.Data["dayTo"] = params.DayTo
this.Data["keyword"] = params.Keyword
this.Data["level"] = params.Level
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
Role: nodeconfigs.NodeRoleDNS,
NodeId: params.NodeId,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count, 20)
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
Offset: page.Offset,
Size: page.Size,
})
logs := []maps.Map{}
for _, log := range logsResp.NodeLogs {
logs = append(logs, maps.Map{
"tag": log.Tag,
"description": log.Description,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
"level": log.Level,
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
"count": log.Count,
})
}
this.Data["logs"] = logs
this.Data["page"] = page.AsHTML()
this.Show()
}

View File

@@ -0,0 +1,46 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
// StatusAction 节点状态
type StatusAction struct {
actionutils.ParentAction
}
func (this *StatusAction) RunPost(params struct {
NodeId int64
}) {
// 节点
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
// 安装信息
if node.InstallStatus != nil {
this.Data["installStatus"] = maps.Map{
"isRunning": node.InstallStatus.IsRunning,
"isFinished": node.InstallStatus.IsFinished,
"isOk": node.InstallStatus.IsOk,
"updatedAt": node.InstallStatus.UpdatedAt,
"error": node.InstallStatus.Error,
"errorCode": node.InstallStatus.ErrorCode,
}
} else {
this.Data["installStatus"] = nil
}
this.Data["isInstalled"] = node.IsInstalled
this.Success()
}

View File

@@ -0,0 +1,172 @@
package node
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/ipAddresses/ipaddressutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdateAction struct {
actionutils.ParentAction
}
func (this *UpdateAction) Init() {
this.Nav("", "node", "update")
this.SecondMenu("nodes")
}
func (this *UpdateAction) RunGet(params struct {
NodeId int64
}) {
this.Data["nodeId"] = params.NodeId
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: params.NodeId})
if err != nil {
this.ErrorPage(err)
return
}
node := nodeResp.NsNode
if node == nil {
this.WriteString("找不到要操作的节点")
return
}
var clusterMap maps.Map = nil
if node.NsCluster != nil {
clusterMap = maps.Map{
"id": node.NsCluster.Id,
"name": node.NsCluster.Name,
}
}
// IP地址
ipAddressesResp, err := this.RPC().NodeIPAddressRPC().FindAllEnabledIPAddressesWithNodeId(this.AdminContext(), &pb.FindAllEnabledIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
ipAddressMaps := []maps.Map{}
for _, addr := range ipAddressesResp.Addresses {
ipAddressMaps = append(ipAddressMaps, maps.Map{
"id": addr.Id,
"name": addr.Name,
"ip": addr.Ip,
"canAccess": addr.CanAccess,
})
}
this.Data["node"] = maps.Map{
"id": node.Id,
"name": node.Name,
"ipAddresses": ipAddressMaps,
"cluster": clusterMap,
"isOn": node.IsOn,
}
// 所有集群
resp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
}
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps := []maps.Map{}
for _, cluster := range resp.NsClusters {
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
})
}
this.Data["clusters"] = clusterMaps
this.Show()
}
func (this *UpdateAction) RunPost(params struct {
LoginId int64
NodeId int64
Name string
IPAddressesJSON []byte `alias:"ipAddressesJSON"`
ClusterId int64
IsOn bool
Must *actions.Must
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改节点 %d", params.NodeId)
if params.NodeId <= 0 {
this.Fail("要操作的节点不存在")
}
params.Must.
Field("name", params.Name).
Require("请输入节点名称")
// 检查cluster
if params.ClusterId <= 0 {
this.Fail("请选择所在集群")
}
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
if clusterResp.NsCluster == nil {
this.Fail("选择的集群不存在")
}
// IP地址
ipAddresses := []maps.Map{}
if len(params.IPAddressesJSON) > 0 {
err := json.Unmarshal(params.IPAddressesJSON, &ipAddresses)
if err != nil {
this.ErrorPage(err)
return
}
}
if len(ipAddresses) == 0 {
this.Fail("请至少输入一个IP地址")
}
// 保存
_, err = this.RPC().NSNodeRPC().UpdateNSNode(this.AdminContext(), &pb.UpdateNSNodeRequest{
NsNodeId: params.NodeId,
Name: params.Name,
NsClusterId: params.ClusterId,
IsOn: params.IsOn,
})
if err != nil {
this.ErrorPage(err)
return
}
// 禁用老的IP地址
_, err = this.RPC().NodeIPAddressRPC().DisableAllIPAddressesWithNodeId(this.AdminContext(), &pb.DisableAllIPAddressesWithNodeIdRequest{
NodeId: params.NodeId,
Role: nodeconfigs.NodeRoleDNS,
})
if err != nil {
this.ErrorPage(err)
return
}
// 添加新的IP地址
err = ipaddressutils.UpdateNodeIPAddresses(this.Parent(), params.NodeId, nodeconfigs.NodeRoleDNS, params.IPAddressesJSON)
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,30 @@
package node
import (
"github.com/TeaOSLab/EdgeAdmin/internal/oplogs"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type UpdateInstallStatusAction struct {
actionutils.ParentAction
}
func (this *UpdateInstallStatusAction) RunPost(params struct {
NodeId int64
IsInstalled bool
}) {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改节点安装状态 %d", params.NodeId)
_, err := this.RPC().NSNodeRPC().UpdateNSNodeIsInstalled(this.AdminContext(), &pb.UpdateNSNodeIsInstalledRequest{
NsNodeId: params.NodeId,
IsInstalled: params.IsInstalled,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,73 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("accessLog")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
}) {
accessLogResp, err := this.RPC().NSClusterRPC().FindNSClusterAccessLog(this.AdminContext(), &pb.FindNSClusterAccessLogRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
accessLogRef := &dnsconfigs.AccessLogRef{}
if len(accessLogResp.AccessLogJSON) > 0 {
err = json.Unmarshal(accessLogResp.AccessLogJSON, accessLogRef)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["accessLogRef"] = accessLogRef
this.Show()
}
func (this *IndexAction) RunPost(params struct {
ClusterId int64
AccessLogJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改域名服务集群 %d 访问日志配置", params.ClusterId)
ref := &dnsconfigs.AccessLogRef{}
err := json.Unmarshal(params.AccessLogJSON, ref)
if err != nil {
this.Fail("数据格式错误:" + err.Error())
}
err = ref.Init()
if err != nil {
this.Fail("数据格式错误:" + err.Error())
}
_, err = this.RPC().NSClusterRPC().UpdateNSClusterAccessLog(this.AdminContext(), &pb.UpdateNSClusterAccessLogRequest{
NsClusterId: params.ClusterId,
AccessLogJSON: params.AccessLogJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,21 @@
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Helper(new(clusterutils.ClusterHelper)).
Data("teaMenu", "ns").
Data("teaSubMenu", "cluster").
Prefix("/ns/clusters/cluster/settings/accessLog").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,69 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "setting", "")
this.SecondMenu("basic")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
}) {
clusterResp, err := this.RPC().NSClusterRPC().FindEnabledNSCluster(this.AdminContext(), &pb.FindEnabledNSClusterRequest{NsClusterId: params.ClusterId})
if err != nil {
this.ErrorPage(err)
return
}
cluster := clusterResp.NsCluster
if cluster == nil {
this.NotFound("nsCluster", params.ClusterId)
return
}
this.Data["cluster"] = maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"isOn": cluster.IsOn,
}
this.Show()
}
func (this *IndexAction) RunPost(params struct {
ClusterId int64
Name string
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改域名服务集群基本信息 %d", params.ClusterId)
params.Must.
Field("name", params.Name).
Require("请输入集群名称")
_, err := this.RPC().NSClusterRPC().UpdateNSCluster(this.AdminContext(), &pb.UpdateNSClusterRequest{
NsClusterId: params.ClusterId,
Name: params.Name,
IsOn: params.IsOn,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,21 @@
package cluster
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/clusters/clusterutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Helper(new(clusterutils.ClusterHelper)).
Data("teaMenu", "ns").
Data("teaSubMenu", "cluster").
Prefix("/ns/clusters/cluster/settings").
GetPost("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,17 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package cluster
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
type UpgradeRemoteAction struct {
actionutils.ParentAction
}
func (this *UpgradeRemoteAction) Init() {
this.Nav("", "", "")
}
func (this *UpgradeRemoteAction) RunGet(params struct{}) {
this.Show()
}

View File

@@ -0,0 +1,92 @@
package clusterutils
import (
"github.com/TeaOSLab/EdgeAdmin/internal/rpc"
"github.com/TeaOSLab/EdgeAdmin/internal/utils/numberutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/logs"
"github.com/iwind/TeaGo/maps"
"net/http"
"strconv"
)
// ClusterHelper 单个集群的帮助
type ClusterHelper struct {
}
func NewClusterHelper() *ClusterHelper {
return &ClusterHelper{}
}
func (this *ClusterHelper) BeforeAction(actionPtr actions.ActionWrapper) (goNext bool) {
action := actionPtr.Object()
if action.Request.Method != http.MethodGet {
return true
}
action.Data["teaMenu"] = "ns"
selectedTabbar := action.Data.GetString("mainTab")
clusterId := action.ParamInt64("clusterId")
clusterIdString := strconv.FormatInt(clusterId, 10)
action.Data["clusterId"] = clusterId
if clusterId > 0 {
rpcClient, err := rpc.SharedRPC()
if err != nil {
logs.Error(err)
return
}
clusterResp, err := rpcClient.NSClusterRPC().FindEnabledNSCluster(actionPtr.(rpc.ContextInterface).AdminContext(), &pb.FindEnabledNSClusterRequest{
NsClusterId: clusterId,
})
if err != nil {
logs.Error(err)
return
}
cluster := clusterResp.NsCluster
if cluster == nil {
action.WriteString("can not find ns cluster")
return
}
tabbar := actionutils.NewTabbar()
tabbar.Add("集群列表", "", "/ns/clusters", "", false)
tabbar.Add("集群节点", "", "/ns/clusters/cluster?clusterId="+clusterIdString, "server", selectedTabbar == "node")
tabbar.Add("集群设置", "", "/ns/clusters/cluster/settings?clusterId="+clusterIdString, "setting", selectedTabbar == "setting")
tabbar.Add("删除集群", "", "/ns/clusters/cluster/delete?clusterId="+clusterIdString, "trash", selectedTabbar == "delete")
{
m := tabbar.Add("当前集群:"+cluster.Name, "", "/ns/clusters/cluster?clusterId="+clusterIdString, "", false)
m["right"] = true
}
actionutils.SetTabbar(action, tabbar)
// 左侧菜单
secondMenuItem := action.Data.GetString("secondMenuItem")
switch selectedTabbar {
case "setting":
action.Data["leftMenuItems"] = this.createSettingMenu(cluster, secondMenuItem)
}
}
return true
}
// 设置菜单
func (this *ClusterHelper) createSettingMenu(cluster *pb.NSCluster, selectedItem string) (items []maps.Map) {
clusterId := numberutils.FormatInt64(cluster.Id)
items = append(items, maps.Map{
"name": "基础设置",
"url": "/ns/clusters/cluster/settings?clusterId=" + clusterId,
"isActive": selectedItem == "basic",
})
items = append(items, maps.Map{
"name": "访问日志",
"url": "/ns/clusters/cluster/settings/accessLog?clusterId=" + clusterId,
"isActive": selectedItem == "accessLog",
})
return
}

View File

@@ -0,0 +1,68 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type CreateAction struct {
actionutils.ParentAction
}
func (this *CreateAction) Init() {
this.Nav("", "", "create")
}
func (this *CreateAction) RunGet(params struct{}) {
// 默认的访问日志设置
this.Data["accessLogRef"] = &dnsconfigs.AccessLogRef{
IsOn: true,
}
this.Show()
}
func (this *CreateAction) RunPost(params struct {
Name string
AccessLogJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var clusterId int64
defer func() {
this.CreateLogInfo("创建域名服务集群 %d", clusterId)
}()
params.Must.
Field("name", params.Name).
Require("请输入集群名称")
// 校验访问日志设置
ref := &dnsconfigs.AccessLogRef{}
err := json.Unmarshal(params.AccessLogJSON, ref)
if err != nil {
this.Fail("数据格式错误:" + err.Error())
}
err = ref.Init()
if err != nil {
this.Fail("数据格式错误:" + err.Error())
}
resp, err := this.RPC().NSClusterRPC().CreateNSCluster(this.AdminContext(), &pb.CreateNSClusterRequest{
Name: params.Name,
AccessLogJSON: params.AccessLogJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
clusterId = resp.NsClusterId
this.Success()
}

View File

@@ -0,0 +1,77 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/configutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "index")
}
func (this *IndexAction) RunGet(params struct{}) {
countResp, err := this.RPC().NSClusterRPC().CountAllEnabledNSClusters(this.AdminContext(), &pb.CountAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
clustersResp, err := this.RPC().NSClusterRPC().ListEnabledNSClusters(this.AdminContext(), &pb.ListEnabledNSClustersRequest{
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps := []maps.Map{}
for _, cluster := range clustersResp.NsClusters {
// 全部节点数量
countNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{NsClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return
}
// 在线节点
countActiveNodesResp, err := this.RPC().NSNodeRPC().CountAllEnabledNSNodesMatch(this.AdminContext(), &pb.CountAllEnabledNSNodesMatchRequest{
NsClusterId: cluster.Id,
ActiveState: types.Int32(configutils.BoolStateYes),
})
if err != nil {
this.ErrorPage(err)
return
}
// 需要升级的节点
countUpgradeNodesResp, err := this.RPC().NSNodeRPC().CountAllUpgradeNSNodesWithNSClusterId(this.AdminContext(), &pb.CountAllUpgradeNSNodesWithNSClusterIdRequest{NsClusterId: cluster.Id})
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
"isOn": cluster.IsOn,
"countAllNodes": countNodesResp.Count,
"countActiveNodes": countActiveNodesResp.Count,
"countUpgradeNodes": countUpgradeNodesResp.Count,
})
}
this.Data["clusters"] = clusterMaps
this.Show()
}

View File

@@ -0,0 +1,21 @@
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Data("teaMenu", "ns").
Data("teaSubMenu", "cluster").
Prefix("/ns/clusters").
Get("", new(IndexAction)).
GetPost("/create", new(CreateAction)).
Post("/options", new(OptionsAction)).
EndAll()
})
}

View File

@@ -0,0 +1,88 @@
package logs
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
}
func (this *IndexAction) RunGet(params struct {
DayFrom string
DayTo string
Keyword string
Level string
}) {
this.Data["dayFrom"] = params.DayFrom
this.Data["dayTo"] = params.DayTo
this.Data["keyword"] = params.Keyword
this.Data["level"] = params.Level
countResp, err := this.RPC().NodeLogRPC().CountNodeLogs(this.AdminContext(), &pb.CountNodeLogsRequest{
NodeId: 0,
Role: nodeconfigs.NodeRoleDNS,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
logsResp, err := this.RPC().NodeLogRPC().ListNodeLogs(this.AdminContext(), &pb.ListNodeLogsRequest{
NodeId: 0,
Role: nodeconfigs.NodeRoleDNS,
DayFrom: params.DayFrom,
DayTo: params.DayTo,
Keyword: params.Keyword,
Level: params.Level,
Offset: page.Offset,
Size: page.Size,
})
logs := []maps.Map{}
for _, log := range logsResp.NodeLogs {
// 节点信息
nodeResp, err := this.RPC().NSNodeRPC().FindEnabledNSNode(this.AdminContext(), &pb.FindEnabledNSNodeRequest{NsNodeId: log.NodeId})
if err != nil {
continue
}
node := nodeResp.NsNode
if node == nil || node.NsCluster == nil {
continue
}
logs = append(logs, maps.Map{
"tag": log.Tag,
"description": log.Description,
"createdTime": timeutil.FormatTime("Y-m-d H:i:s", log.CreatedAt),
"level": log.Level,
"isToday": timeutil.FormatTime("Y-m-d", log.CreatedAt) == timeutil.Format("Y-m-d"),
"count": log.Count,
"node": maps.Map{
"id": node.Id,
"cluster": maps.Map{
"id": node.NsCluster.Id,
"name": node.NsCluster.Name,
},
"name": node.Name,
},
})
}
this.Data["logs"] = logs
this.Show()
}

View File

@@ -0,0 +1,19 @@
package logs
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Data("teaMenu", "ns").
Data("teaSubMenu", "log").
Prefix("/ns/clusters/logs").
Get("", new(IndexAction)).
EndAll()
})
}

View File

@@ -0,0 +1,30 @@
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type OptionsAction struct {
actionutils.ParentAction
}
func (this *OptionsAction) RunPost(params struct{}) {
clustersResp, err := this.RPC().NSClusterRPC().FindAllEnabledNSClusters(this.AdminContext(), &pb.FindAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
clusterMaps := []maps.Map{}
for _, cluster := range clustersResp.NsClusters {
clusterMaps = append(clusterMaps, maps.Map{
"id": cluster.Id,
"name": cluster.Name,
})
}
this.Data["clusters"] = clusterMaps
this.Success()
}

View File

@@ -0,0 +1,73 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"strings"
)
type CreateAction struct {
actionutils.ParentAction
}
func (this *CreateAction) Init() {
this.Nav("", "", "create")
}
func (this *CreateAction) RunGet(params struct{}) {
// 集群数量
countClustersResp, err := this.RPC().NSClusterRPC().CountAllEnabledNSClusters(this.AdminContext(), &pb.CountAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countClusters"] = countClustersResp.Count
this.Show()
}
func (this *CreateAction) RunPost(params struct {
Name string
ClusterId int64
UserId int64
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var domainId int64
defer func() {
this.CreateLogInfo("创建域名 %d", domainId)
}()
params.Name = strings.ToLower(params.Name)
params.Must.
Field("name", params.Name).
Require("请输入域名").
Expect(func() (message string, success bool) {
success = domainutils.ValidateDomainFormat(params.Name)
if !success {
message = "请输入正确的域名"
}
return
}).
Field("clusterId", params.ClusterId).
Gt(0, "请选择所属集群")
createResp, err := this.RPC().NSDomainRPC().CreateNSDomain(this.AdminContext(), &pb.CreateNSDomainRequest{
NsClusterId: params.ClusterId,
UserId: params.UserId,
Name: params.Name,
})
if err != nil {
this.ErrorPage(err)
return
}
domainId = createResp.NsDomainId
this.Success()
}

View File

@@ -0,0 +1,26 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
DomainId int64
}) {
defer this.CreateLogInfo("删除域名 %d", params.DomainId)
_, err := this.RPC().NSDomainRPC().DeleteNSDomain(this.AdminContext(), &pb.DeleteNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,61 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type DomainAction struct {
actionutils.ParentAction
}
func (this *DomainAction) Init() {
this.Nav("", "", "index")
}
func (this *DomainAction) RunGet(params struct {
DomainId int64
}) {
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", params.DomainId)
return
}
var clusterMap maps.Map
if domain.NsCluster != nil {
clusterMap = maps.Map{
"id": domain.NsCluster.Id,
"name": domain.NsCluster.Name,
}
}
// 用户信息
var userMap maps.Map
if domain.User != nil {
userMap = maps.Map{
"id": domain.User.Id,
"username": domain.User.Username,
"fullname": domain.User.Fullname,
}
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
"isOn": domain.IsOn,
"cluster": clusterMap,
"user": userMap,
}
this.Show()
}

View File

@@ -0,0 +1,94 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package records
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *CreatePopupAction) RunGet(params struct {
DomainId int64
}) {
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", params.DomainId)
return
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
}
// 类型
this.Data["types"] = dnsconfigs.FindAllRecordTypeDefinitions()
// TTL
this.Data["ttlValues"] = dnsconfigs.FindAllRecordTTL()
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
DomainId int64
Name string
Type string
Value string
Ttl int32
Description string
RouteIds []int64
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var recordId int64
defer func() {
this.CreateLogInfo("创建域名记录 %d", recordId)
}()
// 校验记录名
if !domainutils.ValidateRecordName(params.Name) {
this.FailField("name", "请输入正确的记录名")
}
// 校验记录值
message, ok := domainutils.ValidateRecordValue(params.Type, params.Value)
if !ok {
this.FailField("value", "记录值错误:"+message)
}
createResp, err := this.RPC().NSRecordRPC().CreateNSRecord(this.AdminContext(), &pb.CreateNSRecordRequest{
NsDomainId: params.DomainId,
Description: params.Description,
Name: params.Name,
Type: params.Type,
Value: params.Value,
Ttl: params.Ttl,
NsRouteIds: params.RouteIds,
})
if err != nil {
this.ErrorPage(err)
return
}
recordId = createResp.NsRecordId
this.Success()
}

View File

@@ -0,0 +1,26 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package records
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
RecordId int64
}) {
defer this.CreateLogInfo("删除域名记录 %d", params.RecordId)
_, err := this.RPC().NSRecordRPC().DeleteNSRecord(this.AdminContext(), &pb.DeleteNSRecordRequest{NsRecordId: params.RecordId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,100 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package records
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "record")
}
func (this *IndexAction) RunGet(params struct {
DomainId int64
Type string
Keyword string
RouteId int64
}) {
this.Data["type"] = params.Type
this.Data["keyword"] = params.Keyword
this.Data["routeId"] = params.RouteId
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", params.DomainId)
return
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
}
// 记录
countResp, err := this.RPC().NSRecordRPC().CountAllEnabledNSRecords(this.AdminContext(), &pb.CountAllEnabledNSRecordsRequest{
NsDomainId: params.DomainId,
Type: params.Type,
NsRouteId: params.RouteId,
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
count := countResp.Count
page := this.NewPage(count)
this.Data["page"] = page.AsHTML()
recordsResp, err := this.RPC().NSRecordRPC().ListEnabledNSRecords(this.AdminContext(), &pb.ListEnabledNSRecordsRequest{
NsDomainId: params.DomainId,
Type: params.Type,
NsRouteId: params.RouteId,
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
var recordMaps = []maps.Map{}
for _, record := range recordsResp.NsRecords {
routeMaps := []maps.Map{}
for _, route := range record.NsRoutes {
routeMaps = append(routeMaps, maps.Map{
"id": route.Id,
"name": route.Name,
})
}
recordMaps = append(recordMaps, maps.Map{
"id": record.Id,
"name": record.Name,
"type": record.Type,
"value": record.Value,
"ttl": record.Ttl,
"weight": record.Weight,
"description": record.Description,
"routes": routeMaps,
})
}
this.Data["records"] = recordMaps
// 所有记录类型
this.Data["types"] = dnsconfigs.FindAllRecordTypeDefinitions()
this.Show()
}

View File

@@ -0,0 +1,117 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package records
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/dns/domains/domainutils"
"github.com/TeaOSLab/EdgeCommon/pkg/dnsconfigs"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
RecordId int64
}) {
recordResp, err := this.RPC().NSRecordRPC().FindEnabledNSRecord(this.AdminContext(), &pb.FindEnabledNSRecordRequest{NsRecordId: params.RecordId})
if err != nil {
this.ErrorPage(err)
return
}
record := recordResp.NsRecord
if record == nil {
this.NotFound("nsRecord", params.RecordId)
return
}
routeIds := []int64{}
for _, route := range record.NsRoutes {
routeIds = append(routeIds, route.Id)
}
this.Data["record"] = maps.Map{
"id": record.Id,
"name": record.Name,
"type": record.Type,
"value": record.Value,
"ttl": record.Ttl,
"weight": record.Weight,
"description": record.Description,
"routeIds": routeIds,
}
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: record.NsDomain.Id})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", record.NsDomain.Id)
return
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
}
// 类型
this.Data["types"] = dnsconfigs.FindAllRecordTypeDefinitions()
// TTL
this.Data["ttlValues"] = dnsconfigs.FindAllRecordTTL()
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
RecordId int64
Name string
Type string
Value string
Ttl int32
Description string
RouteIds []int64
Must *actions.Must
CSRF *actionutils.CSRF
}) {
this.CreateLogInfo("修改域名记录 %d", params.RecordId)
// 校验记录名
if !domainutils.ValidateRecordName(params.Name) {
this.FailField("name", "请输入正确的记录名")
}
// 校验记录值
message, ok := domainutils.ValidateRecordValue(params.Type, params.Value)
if !ok {
this.FailField("value", "记录值错误:"+message)
}
_, err := this.RPC().NSRecordRPC().UpdateNSRecord(this.AdminContext(), &pb.UpdateNSRecordRequest{
NsRecordId: params.RecordId,
Description: params.Description,
Name: params.Name,
Type: params.Type,
Value: params.Value,
Ttl: params.Ttl,
NsRouteIds: params.RouteIds,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,84 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package domains
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdateAction struct {
actionutils.ParentAction
}
func (this *UpdateAction) Init() {
this.Nav("", "", "update")
}
func (this *UpdateAction) RunGet(params struct {
DomainId int64
}) {
// 域名信息
domainResp, err := this.RPC().NSDomainRPC().FindEnabledNSDomain(this.AdminContext(), &pb.FindEnabledNSDomainRequest{NsDomainId: params.DomainId})
if err != nil {
this.ErrorPage(err)
return
}
domain := domainResp.NsDomain
if domain == nil {
this.NotFound("nsDomain", params.DomainId)
return
}
var clusterId = int64(0)
if domain.NsCluster != nil {
clusterId = domain.NsCluster.Id
}
// 用户信息
var userId = int64(0)
if domain.User != nil {
userId = domain.User.Id
}
this.Data["domain"] = maps.Map{
"id": domain.Id,
"name": domain.Name,
"isOn": domain.IsOn,
"clusterId": clusterId,
"userId": userId,
}
this.Show()
}
func (this *UpdateAction) RunPost(params struct {
DomainId int64
ClusterId int64
UserId int64
IsOn bool
Must *actions.Must
CSRF *actionutils.CSRF
}) {
this.CreateLogInfo("修改域名 %d", params.DomainId)
params.Must.
Field("clusterId", params.ClusterId).
Gt(0, "请选择所属集群")
_, err := this.RPC().NSDomainRPC().UpdateNSDomain(this.AdminContext(), &pb.UpdateNSDomainRequest{
NsDomainId: params.DomainId,
NsClusterId: params.ClusterId,
UserId: params.UserId,
IsOn: params.IsOn,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,90 @@
package ns
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.FirstMenu("index")
}
func (this *IndexAction) RunGet(params struct {
ClusterId int64
UserId int64
Keyword string
}) {
this.Data["clusterId"] = params.ClusterId
this.Data["userId"] = params.UserId
this.Data["keyword"] = params.Keyword
// 集群数量
countClustersResp, err := this.RPC().NSClusterRPC().CountAllEnabledNSClusters(this.AdminContext(), &pb.CountAllEnabledNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
this.Data["countClusters"] = countClustersResp.Count
// 分页
countResp, err := this.RPC().NSDomainRPC().CountAllEnabledNSDomains(this.AdminContext(), &pb.CountAllEnabledNSDomainsRequest{
UserId: params.UserId,
NsClusterId: params.ClusterId,
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
}
page := this.NewPage(countResp.Count)
// 列表
domainsResp, err := this.RPC().NSDomainRPC().ListEnabledNSDomains(this.AdminContext(), &pb.ListEnabledNSDomainsRequest{
UserId: params.UserId,
NsClusterId: params.ClusterId,
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)
return
}
domainMaps := []maps.Map{}
for _, domain := range domainsResp.NsDomains {
// 集群信息
var clusterMap maps.Map
if domain.NsCluster != nil {
clusterMap = maps.Map{
"id": domain.NsCluster.Id,
"name": domain.NsCluster.Name,
}
}
// 用户信息
var userMap maps.Map
if domain.User != nil {
userMap = maps.Map{
"id": domain.User.Id,
"username": domain.User.Username,
"fullname": domain.User.Fullname,
}
}
domainMaps = append(domainMaps, maps.Map{
"id": domain.Id,
"name": domain.Name,
"isOn": domain.IsOn,
"cluster": clusterMap,
"user": userMap,
})
}
this.Data["domains"] = domainMaps
this.Show()
}

View File

@@ -0,0 +1,35 @@
package ns
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/ns/domains/records"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Data("teaMenu", "ns").
Prefix("/ns").
Get("", new(IndexAction)).
// 域名相关
Prefix("/ns/domains").
GetPost("/create", new(domains.CreateAction)).
Post("/delete", new(domains.DeleteAction)).
Get("/domain", new(domains.DomainAction)).
GetPost("/update", new(domains.UpdateAction)).
// 记录相关
Prefix("/ns/domains/records").
Get("", new(records.IndexAction)).
GetPost("/createPopup", new(records.CreatePopupAction)).
GetPost("/updatePopup", new(records.UpdatePopupAction)).
Post("/delete", new(records.DeleteAction)).
EndAll()
})
}

View File

@@ -0,0 +1,63 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
)
type CreatePopupAction struct {
actionutils.ParentAction
}
func (this *CreatePopupAction) Init() {
}
func (this *CreatePopupAction) RunGet(params struct {
ClusterId int64
DomainId int64
UserId int64
}) {
this.Data["clusterId"] = params.ClusterId
this.Data["domainId"] = params.DomainId
this.Data["userId"] = params.UserId
this.Show()
}
func (this *CreatePopupAction) RunPost(params struct {
ClusterId int64
DomainId int64
UserId int64
Name string
RangesJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
var routeId = int64(0)
defer func() {
this.CreateLogInfo("创建域名服务线路 %d", routeId)
}()
params.Must.Field("name", params.Name).
Require("请输入线路名称")
createResp, err := this.RPC().NSRouteRPC().CreateNSRoute(this.AdminContext(), &pb.CreateNSRouteRequest{
NsClusterId: params.ClusterId,
NsDomainId: params.DomainId,
UserId: params.UserId,
Name: params.Name,
RangesJSON: params.RangesJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
routeId = createResp.NsRouteId
this.Success()
}

View File

@@ -0,0 +1,26 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type DeleteAction struct {
actionutils.ParentAction
}
func (this *DeleteAction) RunPost(params struct {
RouteId int64
}) {
defer this.CreateLogInfo("删除域名服务线路 %d", params.RouteId)
_, err := this.RPC().NSRouteRPC().DeleteNSRoute(this.AdminContext(), &pb.DeleteNSRouteRequest{NsRouteId: params.RouteId})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,41 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type IndexAction struct {
actionutils.ParentAction
}
func (this *IndexAction) Init() {
this.Nav("", "", "index")
}
func (this *IndexAction) RunGet(params struct{}) {
routesResp, err := this.RPC().NSRouteRPC().FindAllEnabledNSRoutes(this.AdminContext(), &pb.FindAllEnabledNSRoutesRequest{
NsClusterId: 0,
NsDomainId: 0,
UserId: 0,
})
if err != nil {
this.ErrorPage(err)
return
}
routeMaps := []maps.Map{}
for _, route := range routesResp.NsRoutes {
routeMaps = append(routeMaps, maps.Map{
"id": route.Id,
"name": route.Name,
"isOn": route.IsOn,
})
}
this.Data["routes"] = routeMaps
this.Show()
}

View File

@@ -0,0 +1,25 @@
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Data("teaMenu", "ns").
Data("teaSubMenu", "route").
Prefix("/ns/routes").
Get("", new(IndexAction)).
Get("/route", new(RouteAction)).
GetPost("/createPopup", new(CreatePopupAction)).
GetPost("/updatePopup", new(UpdatePopupAction)).
Post("/delete", new(DeleteAction)).
Post("/sort", new(SortAction)).
Post("/options", new(OptionsAction)).
EndAll()
})
}

View File

@@ -0,0 +1,40 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type OptionsAction struct {
actionutils.ParentAction
}
func (this *OptionsAction) RunPost(params struct {
ClusterId int64
DomainId int64
UserId int64
}) {
routesResp, err := this.RPC().NSRouteRPC().FindAllEnabledNSRoutes(this.AdminContext(), &pb.FindAllEnabledNSRoutesRequest{
NsClusterId: params.ClusterId,
NsDomainId: params.DomainId,
UserId: params.UserId,
})
if err != nil {
this.ErrorPage(err)
return
}
routeMaps := []maps.Map{}
for _, route := range routesResp.NsRoutes {
routeMaps = append(routeMaps, maps.Map{
"id": route.Id,
"name": route.Name,
})
}
this.Data["routes"] = routeMaps
this.Success()
}

View File

@@ -0,0 +1,17 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
type RouteAction struct {
actionutils.ParentAction
}
func (this *RouteAction) Init() {
this.Nav("", "", "")
}
func (this *RouteAction) RunGet(params struct{}) {
this.Show()
}

View File

@@ -0,0 +1,26 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
)
type SortAction struct {
actionutils.ParentAction
}
func (this *SortAction) RunPost(params struct {
RouteIds []int64
}) {
defer this.CreateLogInfo("对线路进行排序")
_, err := this.RPC().NSRouteRPC().UpdateNSRouteOrders(this.AdminContext(), &pb.UpdateNSRouteOrdersRequest{NsRouteIds: params.RouteIds})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,78 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
package clusters
import (
"encoding/json"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
)
type UpdatePopupAction struct {
actionutils.ParentAction
}
func (this *UpdatePopupAction) Init() {
this.Nav("", "", "")
}
func (this *UpdatePopupAction) RunGet(params struct {
RouteId int64
}) {
routeResp, err := this.RPC().NSRouteRPC().FindEnabledNSRoute(this.AdminContext(), &pb.FindEnabledNSRouteRequest{NsRouteId: params.RouteId})
if err != nil {
this.ErrorPage(err)
return
}
route := routeResp.NsRoute
if route == nil {
this.NotFound("nsRoute", params.RouteId)
return
}
rangeMaps := []maps.Map{}
if len(route.RangesJSON) > 0 {
err = json.Unmarshal([]byte(route.RangesJSON), &rangeMaps)
if err != nil {
this.ErrorPage(err)
return
}
}
this.Data["route"] = maps.Map{
"id": route.Id,
"name": route.Name,
"isOn": route.IsOn,
"ranges": rangeMaps,
}
this.Show()
}
func (this *UpdatePopupAction) RunPost(params struct {
RouteId int64
Name string
RangesJSON []byte
Must *actions.Must
CSRF *actionutils.CSRF
}) {
defer this.CreateLogInfo("修改域名线路 %d", params.RouteId)
params.Must.Field("name", params.Name).
Require("请输入线路名称")
_, err := this.RPC().NSRouteRPC().UpdateNSRoute(this.AdminContext(), &pb.UpdateNSRouteRequest{
NsRouteId: params.RouteId,
Name: params.Name,
RangesJSON: params.RangesJSON,
})
if err != nil {
this.ErrorPage(err)
return
}
this.Success()
}

View File

@@ -0,0 +1,19 @@
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/configloaders"
"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
"github.com/iwind/TeaGo"
)
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeNS)).
Data("teaMenu", "ns").
Data("teaSubMenu", "domain").
Prefix("/ns/users").
Post("/options", new(OptionsAction)).
EndAll()
})
}

View File

@@ -0,0 +1,34 @@
package users
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/iwind/TeaGo/maps"
)
type OptionsAction struct {
actionutils.ParentAction
}
func (this *OptionsAction) RunPost(params struct{}) {
usersResp, err := this.RPC().UserRPC().ListEnabledUsers(this.AdminContext(), &pb.ListEnabledUsersRequest{
Offset: 0,
Size: 10000, // TODO 改进 <ns-user-selector> 组件
})
if err != nil {
this.ErrorPage(err)
return
}
userMaps := []maps.Map{}
for _, user := range usersResp.Users {
userMaps = append(userMaps, maps.Map{
"id": user.Id,
"fullname": user.Fullname,
"username": user.Username,
})
}
this.Data["users"] = userMaps
this.Success()
}

View File

@@ -6,6 +6,7 @@ import (
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
"github.com/iwind/TeaGo/actions"
"net/url"
"regexp"
"strings"
)
@@ -36,10 +37,27 @@ func (this *AddOriginPopupAction) RunPost(params struct {
Field("addr", params.Addr).
Require("请输入源站地址")
addr := regexp.MustCompile(`\s+`).ReplaceAllString(params.Addr, "")
portIndex := strings.LastIndex(params.Addr, ":")
addr := params.Addr
// 是否是完整的地址
if (params.Protocol == "http" || params.Protocol == "https") && regexp.MustCompile(`^(http|https)://`).MatchString(addr) {
u, err := url.Parse(addr)
if err == nil {
addr = u.Host
}
}
addr = regexp.MustCompile(`\s+`).ReplaceAllString(addr, "")
portIndex := strings.LastIndex(addr, ":")
if portIndex < 0 {
this.Fail("地址中需要带有端口")
if params.Protocol == "http" {
addr += ":80"
} else if params.Protocol == "https" {
addr += ":443"
} else {
this.Fail("地址中需要带有端口")
}
portIndex = strings.LastIndex(addr, ":")
}
host := addr[:portIndex]
port := addr[portIndex+1:]
@@ -52,6 +70,7 @@ func (this *AddOriginPopupAction) RunPost(params struct {
PortRange: port,
},
Description: "",
Weight: 10,
IsOn: true,
})
if err != nil {

View File

@@ -16,8 +16,14 @@ func (this *IndexAction) Init() {
this.FirstMenu("index")
}
func (this *IndexAction) RunGet(params struct{}) {
countResp, err := this.RPC().HTTPCachePolicyRPC().CountAllEnabledHTTPCachePolicies(this.AdminContext(), &pb.CountAllEnabledHTTPCachePoliciesRequest{})
func (this *IndexAction) RunGet(params struct {
Keyword string
}) {
this.Data["keyword"] = params.Keyword
countResp, err := this.RPC().HTTPCachePolicyRPC().CountAllEnabledHTTPCachePolicies(this.AdminContext(), &pb.CountAllEnabledHTTPCachePoliciesRequest{
Keyword: params.Keyword,
})
if err != nil {
this.ErrorPage(err)
return
@@ -27,8 +33,9 @@ func (this *IndexAction) RunGet(params struct{}) {
this.Data["page"] = page.AsHTML()
listResp, err := this.RPC().HTTPCachePolicyRPC().ListEnabledHTTPCachePolicies(this.AdminContext(), &pb.ListEnabledHTTPCachePoliciesRequest{
Offset: page.Offset,
Size: page.Size,
Keyword: params.Keyword,
Offset: page.Offset,
Size: page.Size,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -37,12 +37,12 @@ func (this *CreatePopupAction) RunPost(params struct {
}
this.Data["group"] = maps.Map{
"id": createResp.GroupId,
"id": createResp.ServerGroupId,
"name": params.Name,
}
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "创建代理服务分组 %d", createResp.GroupId)
defer this.CreateLog(oplogs.LevelInfo, "创建代理服务分组 %d", createResp.ServerGroupId)
this.Success()
}

View File

@@ -17,7 +17,7 @@ func (this *DeleteAction) RunPost(params struct {
defer this.CreateLog(oplogs.LevelInfo, "删除代理服务分组 %d", params.GroupId)
// 检查是否正在使用
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithGroupId(this.AdminContext(), &pb.CountAllEnabledServersWithGroupIdRequest{GroupId: params.GroupId})
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithServerGroupId(this.AdminContext(), &pb.CountAllEnabledServersWithServerGroupIdRequest{ServerGroupId: params.GroupId})
if err != nil {
this.ErrorPage(err)
return
@@ -27,7 +27,7 @@ func (this *DeleteAction) RunPost(params struct {
this.Fail("此分组正在被使用不能删除,请修改相关服务后再删除")
}
_, err = this.RPC().ServerGroupRPC().DeleteServerGroup(this.AdminContext(), &pb.DeleteServerGroupRequest{GroupId: params.GroupId})
_, err = this.RPC().ServerGroupRPC().DeleteServerGroup(this.AdminContext(), &pb.DeleteServerGroupRequest{ServerGroupId: params.GroupId})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -23,8 +23,8 @@ func (this *IndexAction) RunGet(params struct{}) {
}
groupMaps := []maps.Map{}
for _, group := range groupsResp.Groups {
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithGroupId(this.AdminContext(), &pb.CountAllEnabledServersWithGroupIdRequest{GroupId: group.Id})
for _, group := range groupsResp.ServerGroups {
countResp, err := this.RPC().ServerRPC().CountAllEnabledServersWithServerGroupId(this.AdminContext(), &pb.CountAllEnabledServersWithServerGroupIdRequest{ServerGroupId: group.Id})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -34,7 +34,7 @@ func (this *SelectPopupAction) RunGet(params struct {
}
groupMaps := []maps.Map{}
for _, group := range groupsResp.Groups {
for _, group := range groupsResp.ServerGroups {
// 已经选过的就跳过
if lists.ContainsInt64(selectedGroupIds, group.Id) {
continue
@@ -58,12 +58,12 @@ func (this *SelectPopupAction) RunPost(params struct {
this.Fail("请选择要使用的分组")
}
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroup(this.AdminContext(), &pb.FindEnabledServerGroupRequest{GroupId: params.GroupId})
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroup(this.AdminContext(), &pb.FindEnabledServerGroupRequest{ServerGroupId: params.GroupId})
if err != nil {
this.ErrorPage(err)
return
}
group := groupResp.Group
group := groupResp.ServerGroup
if group == nil {
this.NotFound("serverGroup", params.GroupId)
return

View File

@@ -16,7 +16,7 @@ func (this *SortAction) RunPost(params struct {
// 创建日志
defer this.CreateLog(oplogs.LevelInfo, "修改代理分组排序")
_, err := this.RPC().ServerGroupRPC().UpdateServerGroupOrders(this.AdminContext(), &pb.UpdateServerGroupOrdersRequest{GroupIds: params.GroupIds})
_, err := this.RPC().ServerGroupRPC().UpdateServerGroupOrders(this.AdminContext(), &pb.UpdateServerGroupOrdersRequest{ServerGroupIds: params.GroupIds})
if err != nil {
this.ErrorPage(err)
return

View File

@@ -19,12 +19,12 @@ func (this *UpdatePopupAction) Init() {
func (this *UpdatePopupAction) RunGet(params struct {
GroupId int64
}) {
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroup(this.AdminContext(), &pb.FindEnabledServerGroupRequest{GroupId: params.GroupId})
groupResp, err := this.RPC().ServerGroupRPC().FindEnabledServerGroup(this.AdminContext(), &pb.FindEnabledServerGroupRequest{ServerGroupId: params.GroupId})
if err != nil {
this.ErrorPage(err)
return
}
group := groupResp.Group
group := groupResp.ServerGroup
if group == nil {
this.NotFound("serverGroup", params.GroupId)
return
@@ -51,8 +51,8 @@ func (this *UpdatePopupAction) RunPost(params struct {
Field("name", params.Name).
Require("请输入分组名称")
_, err := this.RPC().ServerGroupRPC().UpdateServerGroup(this.AdminContext(), &pb.UpdateServerGroupRequest{
GroupId: params.GroupId,
Name: params.Name,
ServerGroupId: params.GroupId,
Name: params.Name,
})
if err != nil {
this.ErrorPage(err)

Some files were not shown because too many files have changed in this diff Show More