mirror of
https://github.com/TeaOSLab/EdgeCommon.git
synced 2025-11-09 00:20:25 +08:00
支持单个服务更新
This commit is contained in:
@@ -2,6 +2,7 @@ package nodeconfigs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
@@ -9,6 +10,7 @@ import (
|
|||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/maps"
|
"github.com/iwind/TeaGo/maps"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -106,12 +108,40 @@ func ResetNodeConfig(nodeConfig *NodeConfig) {
|
|||||||
shared.Locker.Unlock()
|
shared.Locker.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloneNodeConfig 复制节点配置
|
||||||
|
func CloneNodeConfig(nodeConfig *NodeConfig) (*NodeConfig, error) {
|
||||||
|
if nodeConfig == nil {
|
||||||
|
return nil, errors.New("node config should not be nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
var newConfigValue = reflect.Indirect(reflect.ValueOf(&NodeConfig{}))
|
||||||
|
var oldValue = reflect.Indirect(reflect.ValueOf(nodeConfig))
|
||||||
|
var valueType = oldValue.Type()
|
||||||
|
for i := 0; i < valueType.NumField(); i++ {
|
||||||
|
var field = valueType.Field(i)
|
||||||
|
var fieldName = field.Name
|
||||||
|
if !field.IsExported() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fieldName == "Servers" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newConfigValue.FieldByName(fieldName).Set(oldValue.FieldByName(fieldName))
|
||||||
|
}
|
||||||
|
|
||||||
|
var newConfig = newConfigValue.Interface().(NodeConfig)
|
||||||
|
newConfig.Servers = append([]*serverconfigs.ServerConfig{}, nodeConfig.Servers...)
|
||||||
|
return &newConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Init 初始化
|
// Init 初始化
|
||||||
func (this *NodeConfig) Init() (err error, serverErrors []*ServerError) {
|
func (this *NodeConfig) Init() (err error, serverErrors []*ServerError) {
|
||||||
this.paddedId = fmt.Sprintf("%08d", this.Id)
|
this.paddedId = fmt.Sprintf("%08d", this.Id)
|
||||||
|
|
||||||
// servers
|
// servers
|
||||||
for _, server := range this.Servers {
|
for _, server := range this.Servers {
|
||||||
|
// 初始化
|
||||||
errs := server.Init()
|
errs := server.Init()
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
// 这里不返回错误,而是继续往下,防止单个服务错误而影响其他服务
|
// 这里不返回错误,而是继续往下,防止单个服务错误而影响其他服务
|
||||||
@@ -119,6 +149,11 @@ func (this *NodeConfig) Init() (err error, serverErrors []*ServerError) {
|
|||||||
serverErrors = append(serverErrors, NewServerError(server.Id, "server '"+strconv.FormatInt(server.Id, 10)+"' init failed: "+serverErr.Error()))
|
serverErrors = append(serverErrors, NewServerError(server.Id, "server '"+strconv.FormatInt(server.Id, 10)+"' init failed: "+serverErr.Error()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查ACME支持
|
||||||
|
if server.IsOn && server.SupportCNAME {
|
||||||
|
this.SupportCNAME = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// global config
|
// global config
|
||||||
@@ -161,6 +196,7 @@ func (this *NodeConfig) Init() (err error, serverErrors []*ServerError) {
|
|||||||
this.originMap = map[int64]*serverconfigs.OriginConfig{}
|
this.originMap = map[int64]*serverconfigs.OriginConfig{}
|
||||||
|
|
||||||
// 查找FirewallPolicy
|
// 查找FirewallPolicy
|
||||||
|
this.synFlood = nil
|
||||||
this.firewallPolicies = []*firewallconfigs.HTTPFirewallPolicy{}
|
this.firewallPolicies = []*firewallconfigs.HTTPFirewallPolicy{}
|
||||||
for _, policy := range this.HTTPFirewallPolicies {
|
for _, policy := range this.HTTPFirewallPolicies {
|
||||||
if policy.IsOn {
|
if policy.IsOn {
|
||||||
@@ -242,6 +278,35 @@ func (this *NodeConfig) Init() (err error, serverErrors []*ServerError) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddServer 添加服务
|
||||||
|
func (this *NodeConfig) AddServer(server *serverconfigs.ServerConfig) {
|
||||||
|
if server == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var found = false
|
||||||
|
for index, oldServer := range this.Servers {
|
||||||
|
if oldServer.Id == server.Id {
|
||||||
|
this.Servers[index] = server
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
this.Servers = append(this.Servers, server)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveServer 删除服务
|
||||||
|
func (this *NodeConfig) RemoveServer(serverId int64) {
|
||||||
|
for index, oldServer := range this.Servers {
|
||||||
|
if oldServer.Id == serverId {
|
||||||
|
this.Servers = append(this.Servers[:index], this.Servers[index+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// AvailableGroups 根据网络地址和协议分组
|
// AvailableGroups 根据网络地址和协议分组
|
||||||
func (this *NodeConfig) AvailableGroups() []*serverconfigs.ServerAddressGroup {
|
func (this *NodeConfig) AvailableGroups() []*serverconfigs.ServerAddressGroup {
|
||||||
groupMapping := map[string]*serverconfigs.ServerAddressGroup{} // protocol://addr => Server Group
|
groupMapping := map[string]*serverconfigs.ServerAddressGroup{} // protocol://addr => Server Group
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
_ "github.com/iwind/TeaGo/bootstrap"
|
_ "github.com/iwind/TeaGo/bootstrap"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSharedNodeConfig(t *testing.T) {
|
func TestSharedNodeConfig(t *testing.T) {
|
||||||
@@ -64,3 +65,37 @@ func TestNodeConfig_Groups(t *testing.T) {
|
|||||||
}
|
}
|
||||||
logs.PrintAsJSON(config.AvailableGroups(), t)
|
logs.PrintAsJSON(config.AvailableGroups(), t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCloneNodeConfig(t *testing.T) {
|
||||||
|
var config = &NodeConfig{Id: 1, NodeId: "1", IsOn: true}
|
||||||
|
for i := 0; i < 100_000; i++ {
|
||||||
|
config.Servers = append(config.Servers, &serverconfigs.ServerConfig{})
|
||||||
|
}
|
||||||
|
var before = time.Now()
|
||||||
|
newConfig, err := CloneNodeConfig(config)
|
||||||
|
t.Log(time.Since(before))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
newConfig.Servers = []*serverconfigs.ServerConfig{}
|
||||||
|
logs.PrintAsJSON(newConfig, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNodeConfig_AddServer(t *testing.T) {
|
||||||
|
var config = &NodeConfig{Id: 1, NodeId: "1", IsOn: true}
|
||||||
|
config.AddServer(&serverconfigs.ServerConfig{Id: 1})
|
||||||
|
config.AddServer(&serverconfigs.ServerConfig{Id: 2})
|
||||||
|
|
||||||
|
t.Log("===before===")
|
||||||
|
for _, s := range config.Servers {
|
||||||
|
t.Log(s.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("===after===")
|
||||||
|
config.AddServer(&serverconfigs.ServerConfig{Id: 3})
|
||||||
|
config.RemoveServer(2)
|
||||||
|
for _, s := range config.Servers {
|
||||||
|
t.Log(s.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ type NodeTask struct {
|
|||||||
UpdatedAt int64 `protobuf:"varint,6,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"`
|
UpdatedAt int64 `protobuf:"varint,6,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"`
|
||||||
Version int64 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty"`
|
Version int64 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
IsPrimary bool `protobuf:"varint,8,opt,name=isPrimary,proto3" json:"isPrimary,omitempty"` // 是否为主节点,非主节点稍等再同步有利于提升同步速度
|
IsPrimary bool `protobuf:"varint,8,opt,name=isPrimary,proto3" json:"isPrimary,omitempty"` // 是否为主节点,非主节点稍等再同步有利于提升同步速度
|
||||||
|
ServerId int64 `protobuf:"varint,9,opt,name=serverId,proto3" json:"serverId,omitempty"`
|
||||||
Node *Node `protobuf:"bytes,30,opt,name=node,proto3" json:"node,omitempty"`
|
Node *Node `protobuf:"bytes,30,opt,name=node,proto3" json:"node,omitempty"`
|
||||||
NodeCluster *NodeCluster `protobuf:"bytes,31,opt,name=nodeCluster,proto3" json:"nodeCluster,omitempty"`
|
NodeCluster *NodeCluster `protobuf:"bytes,31,opt,name=nodeCluster,proto3" json:"nodeCluster,omitempty"`
|
||||||
|
Server *NodeCluster `protobuf:"bytes,32,opt,name=server,proto3" json:"server,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NodeTask) Reset() {
|
func (x *NodeTask) Reset() {
|
||||||
@@ -131,6 +133,13 @@ func (x *NodeTask) GetIsPrimary() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *NodeTask) GetServerId() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.ServerId
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (x *NodeTask) GetNode() *Node {
|
func (x *NodeTask) GetNode() *Node {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Node
|
return x.Node
|
||||||
@@ -145,6 +154,13 @@ func (x *NodeTask) GetNodeCluster() *NodeCluster {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *NodeTask) GetServer() *NodeCluster {
|
||||||
|
if x != nil {
|
||||||
|
return x.Server
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var File_models_model_node_task_proto protoreflect.FileDescriptor
|
var File_models_model_node_task_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_models_model_node_task_proto_rawDesc = []byte{
|
var file_models_model_node_task_proto_rawDesc = []byte{
|
||||||
@@ -153,7 +169,7 @@ var file_models_model_node_task_proto_rawDesc = []byte{
|
|||||||
0x70, 0x62, 0x1a, 0x17, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
|
0x70, 0x62, 0x1a, 0x17, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
|
||||||
0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x6d, 0x6f, 0x64,
|
0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x6d, 0x6f, 0x64,
|
||||||
0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63,
|
0x65, 0x6c, 0x73, 0x2f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63,
|
||||||
0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x97, 0x02, 0x0a,
|
0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdc, 0x02, 0x0a,
|
||||||
0x08, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
|
0x08, 0x4e, 0x6f, 0x64, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70,
|
0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70,
|
||||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a,
|
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a,
|
||||||
@@ -166,13 +182,17 @@ var file_models_model_node_task_proto_rawDesc = []byte{
|
|||||||
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07,
|
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07,
|
||||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x50, 0x72, 0x69,
|
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x50, 0x72, 0x69,
|
||||||
0x6d, 0x61, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x50, 0x72,
|
0x6d, 0x61, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x50, 0x72,
|
||||||
0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1c, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x1e, 0x20,
|
0x69, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x08, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e,
|
0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x49,
|
||||||
0x6f, 0x64, 0x65, 0x12, 0x31, 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74,
|
0x64, 0x12, 0x1c, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x65, 0x72, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f,
|
0x08, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12,
|
||||||
0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x43,
|
0x31, 0x0a, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x1f,
|
||||||
0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x0b, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74,
|
||||||
|
0x65, 0x72, 0x12, 0x27, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x20, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x75, 0x73,
|
||||||
|
0x74, 0x65, 0x72, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42, 0x06, 0x5a, 0x04, 0x2e,
|
||||||
|
0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -196,11 +216,12 @@ var file_models_model_node_task_proto_goTypes = []interface{}{
|
|||||||
var file_models_model_node_task_proto_depIdxs = []int32{
|
var file_models_model_node_task_proto_depIdxs = []int32{
|
||||||
1, // 0: pb.NodeTask.node:type_name -> pb.Node
|
1, // 0: pb.NodeTask.node:type_name -> pb.Node
|
||||||
2, // 1: pb.NodeTask.nodeCluster:type_name -> pb.NodeCluster
|
2, // 1: pb.NodeTask.nodeCluster:type_name -> pb.NodeCluster
|
||||||
2, // [2:2] is the sub-list for method output_type
|
2, // 2: pb.NodeTask.server:type_name -> pb.NodeCluster
|
||||||
2, // [2:2] is the sub-list for method input_type
|
3, // [3:3] is the sub-list for method output_type
|
||||||
2, // [2:2] is the sub-list for extension type_name
|
3, // [3:3] is the sub-list for method input_type
|
||||||
2, // [2:2] is the sub-list for extension extendee
|
3, // [3:3] is the sub-list for extension type_name
|
||||||
0, // [0:2] is the sub-list for field type_name
|
3, // [3:3] is the sub-list for extension extendee
|
||||||
|
0, // [0:3] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_models_model_node_task_proto_init() }
|
func init() { file_models_model_node_task_proto_init() }
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,9 @@ message NodeTask {
|
|||||||
int64 updatedAt = 6;
|
int64 updatedAt = 6;
|
||||||
int64 version = 7;
|
int64 version = 7;
|
||||||
bool isPrimary = 8; // 是否为主节点,非主节点稍等再同步有利于提升同步速度
|
bool isPrimary = 8; // 是否为主节点,非主节点稍等再同步有利于提升同步速度
|
||||||
|
int64 serverId = 9;
|
||||||
|
|
||||||
Node node = 30;
|
Node node = 30;
|
||||||
NodeCluster nodeCluster = 31;
|
NodeCluster nodeCluster = 31;
|
||||||
|
NodeCluster server = 32;
|
||||||
}
|
}
|
||||||
@@ -141,6 +141,9 @@ service ServerService {
|
|||||||
|
|
||||||
// 获取服务套餐信息
|
// 获取服务套餐信息
|
||||||
rpc findServerUserPlan(FindServerUserPlanRequest) returns (FindServerUserPlanResponse);
|
rpc findServerUserPlan(FindServerUserPlanRequest) returns (FindServerUserPlanResponse);
|
||||||
|
|
||||||
|
// 获取服务配置
|
||||||
|
rpc composeServerConfig(ComposeServerConfigRequest) returns (ComposeServerConfigResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建服务
|
// 创建服务
|
||||||
@@ -557,3 +560,12 @@ message FindServerUserPlanRequest {
|
|||||||
message FindServerUserPlanResponse {
|
message FindServerUserPlanResponse {
|
||||||
UserPlan userPlan = 1;
|
UserPlan userPlan = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取服务配置
|
||||||
|
message ComposeServerConfigRequest {
|
||||||
|
int64 serverId = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComposeServerConfigResponse {
|
||||||
|
bytes serverConfigJSON = 1;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user