mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 66bb45e2c0 |
@@ -45,8 +45,8 @@ func (p *imlCluster) Check(ctx *gin.Context, input *cluster_dto.CheckCluster) ([
|
||||
// return id, nil
|
||||
//}
|
||||
//
|
||||
//func (p *imlCluster) SearchByDriver(ctx *gin.Context, keyword string) ([]*parition_dto.Item, error) {
|
||||
// return p.module.SearchByDriver(ctx, keyword)
|
||||
//func (p *imlCluster) Search(ctx *gin.Context, keyword string) ([]*parition_dto.Item, error) {
|
||||
// return p.module.Search(ctx, keyword)
|
||||
//}
|
||||
//
|
||||
//func (p *imlCluster) Simple(ctx *gin.Context) ([]*parition_dto.Simple, error) {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type ILogController interface {
|
||||
Save(ctx *gin.Context, driver string, input *log_dto.Save) error
|
||||
Get(ctx *gin.Context, driver string) (*log_dto.LogSource, error)
|
||||
}
|
||||
|
||||
func init() {
|
||||
logController := &imlLogController{}
|
||||
autowire.Auto[ILogController](func() reflect.Value {
|
||||
return reflect.ValueOf(logController)
|
||||
})
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"github.com/APIParkLab/APIPark/module/log"
|
||||
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type imlLogController struct {
|
||||
module log.ILogModule `autowired:""`
|
||||
}
|
||||
|
||||
func (c *imlLogController) Save(ctx *gin.Context, driver string, input *log_dto.Save) error {
|
||||
return c.module.Save(ctx, driver, input)
|
||||
}
|
||||
|
||||
func (c *imlLogController) Get(ctx *gin.Context, driver string) (*log_dto.LogSource, error) {
|
||||
return c.module.Get(ctx, driver)
|
||||
}
|
||||
@@ -17,70 +17,6 @@ type imlMonitorStatisticController struct {
|
||||
module monitor.IMonitorStatisticModule `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticController) Statistics(ctx *gin.Context, dataType string, input *monitor_dto.StatisticInput) (interface{}, error) {
|
||||
switch dataType {
|
||||
case monitor_dto.DataTypeApi:
|
||||
return i.module.ApiStatistics(ctx, input)
|
||||
case monitor_dto.DataTypeProvider:
|
||||
return i.module.ProviderStatistics(ctx, input)
|
||||
case monitor_dto.DataTypeSubscriber:
|
||||
return i.module.SubscriberStatistics(ctx, input)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported data type: %s", dataType)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticController) InvokeTrend(ctx *gin.Context, dataType string, id string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||
switch dataType {
|
||||
case monitor_dto.DataTypeApi:
|
||||
return i.module.APITrend(ctx, id, input)
|
||||
case monitor_dto.DataTypeProvider:
|
||||
return i.module.ProviderTrend(ctx, id, input)
|
||||
case monitor_dto.DataTypeSubscriber:
|
||||
return i.module.SubscriberTrend(ctx, id, input)
|
||||
default:
|
||||
return nil, "", fmt.Errorf("unsupported data type: %s", dataType)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticController) InvokeTrendInner(ctx *gin.Context, dataType string, typ string, api string, provider string, subscriber string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||
if dataType == monitor_dto.DataTypeApi && typ == monitor_dto.DataTypeSubscriber || dataType == monitor_dto.DataTypeSubscriber && typ == monitor_dto.DataTypeApi {
|
||||
return i.module.InvokeTrendWithSubscriberAndApi(ctx, api, subscriber, input)
|
||||
} else if dataType == monitor_dto.DataTypeApi && typ == monitor_dto.DataTypeProvider || dataType == monitor_dto.DataTypeProvider && typ == monitor_dto.DataTypeApi {
|
||||
return i.module.InvokeTrendWithProviderAndApi(ctx, provider, api, input)
|
||||
}
|
||||
return nil, "", fmt.Errorf("unsupported detail type: %s, data type is %s", typ, dataType)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticController) StatisticsInner(ctx *gin.Context, dataType string, typ string, id string, input *monitor_dto.StatisticInput) (interface{}, error) {
|
||||
switch dataType {
|
||||
case monitor_dto.DataTypeApi:
|
||||
switch typ {
|
||||
case monitor_dto.DataTypeProvider:
|
||||
return i.module.ProviderStatisticsOnApi(ctx, id, input)
|
||||
case monitor_dto.DataTypeSubscriber:
|
||||
return i.module.SubscriberStatisticsOnApi(ctx, id, input)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported detail type: %s, data type is %s", typ, dataType)
|
||||
}
|
||||
case monitor_dto.DataTypeProvider:
|
||||
switch typ {
|
||||
case monitor_dto.DataTypeApi:
|
||||
return i.module.ApiStatisticsOnProvider(ctx, id, input)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported detail type: %s, data type is %s", typ, dataType)
|
||||
}
|
||||
case monitor_dto.DataTypeSubscriber:
|
||||
switch typ {
|
||||
case monitor_dto.DataTypeApi:
|
||||
return i.module.ApiStatisticsOnSubscriber(ctx, id, input)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported detail type: %s, data type is %s", typ, dataType)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("unsupported data type: %s", dataType)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticController) OverviewMessageTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []float64, []float64, string, error) {
|
||||
trend, timeInterval, err := i.module.MessageTrend(ctx, input)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,12 +16,7 @@ type IMonitorStatisticController interface {
|
||||
OverviewInvokeTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []int64, []int64, []int64, []int64, []float64, []float64, string, error)
|
||||
OverviewMessageTrend(ctx *gin.Context, input *monitor_dto.CommonInput) ([]time.Time, []float64, []float64, string, error)
|
||||
|
||||
Statistics(ctx *gin.Context, dataType string, input *monitor_dto.StatisticInput) (interface{}, error)
|
||||
|
||||
InvokeTrend(ctx *gin.Context, dataType string, id string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||
|
||||
InvokeTrendInner(ctx *gin.Context, dataType string, typ string, api string, provider string, subscriber string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||
StatisticsInner(ctx *gin.Context, dataType string, typ string, id string, input *monitor_dto.StatisticInput) (interface{}, error)
|
||||
//Statistics(ctx *gin.Context, dataType string, input *monitor_dto.StatisticInput) (interface{}, error)
|
||||
}
|
||||
|
||||
type IMonitorConfigController interface {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
api_doc "github.com/APIParkLab/APIPark/module/api-doc"
|
||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||
"github.com/APIParkLab/APIPark/module/router"
|
||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||
"github.com/gin-gonic/gin"
|
||||
"io"
|
||||
)
|
||||
|
||||
var _ IRouterController = (*imlAPIController)(nil)
|
||||
@@ -16,10 +15,6 @@ type imlAPIController struct {
|
||||
module router.IRouterModule `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlAPIController) Simple(ctx *gin.Context, input *router_dto.InputSimpleAPI) ([]*router_dto.SimpleItem, error) {
|
||||
return i.module.SimpleAPIs(ctx, input)
|
||||
}
|
||||
|
||||
func (i *imlAPIController) Detail(ctx *gin.Context, serviceId string, apiId string) (*router_dto.Detail, error) {
|
||||
return i.module.Detail(ctx, serviceId, apiId)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||
"reflect"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
@@ -25,7 +24,6 @@ type IRouterController interface {
|
||||
Delete(ctx *gin.Context, serviceId string, apiId string) error
|
||||
// Prefix 获取API前缀
|
||||
Prefix(ctx *gin.Context, serviceId string) (string, bool, error)
|
||||
Simple(ctx *gin.Context, input *router_dto.InputSimpleAPI) ([]*router_dto.SimpleItem, error)
|
||||
}
|
||||
|
||||
type IAPIDocController interface {
|
||||
|
||||
+27
-120
@@ -7,16 +7,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/eolinker/go-common/pm3"
|
||||
|
||||
"github.com/APIParkLab/APIPark/module/system"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
|
||||
api_doc "github.com/APIParkLab/APIPark/module/api-doc"
|
||||
|
||||
upstream_dto "github.com/APIParkLab/APIPark/module/upstream/dto"
|
||||
|
||||
"github.com/eolinker/eosc/log"
|
||||
|
||||
application_authorization "github.com/APIParkLab/APIPark/module/application-authorization"
|
||||
@@ -35,6 +25,7 @@ import (
|
||||
"github.com/APIParkLab/APIPark/module/service"
|
||||
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
|
||||
"github.com/APIParkLab/APIPark/module/upstream"
|
||||
upstream_dto "github.com/APIParkLab/APIPark/module/upstream/dto"
|
||||
"github.com/eolinker/go-common/store"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
@@ -51,102 +42,29 @@ type imlServiceController struct {
|
||||
docModule service.IServiceDocModule `autowired:""`
|
||||
aiAPIModule ai_api.IAPIModule `autowired:""`
|
||||
routerModule router.IRouterModule `autowired:""`
|
||||
apiDocModule api_doc.IAPIDocModule `autowired:""`
|
||||
providerModule ai.IProviderModule `autowired:""`
|
||||
upstreamModule upstream.IUpstreamModule `autowired:""`
|
||||
settingModule system.ISettingModule `autowired:""`
|
||||
transaction store.ITransaction `autowired:""`
|
||||
}
|
||||
|
||||
var (
|
||||
loader = openapi3.NewLoader()
|
||||
)
|
||||
|
||||
func (i *imlServiceController) swagger(ctx *gin.Context, id string) (*openapi3.T, error) {
|
||||
doc, err := i.apiDocModule.GetDoc(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func newAIUpstream(id string, provider string, uri model_runtime.IProviderURI) *upstream_dto.Upstream {
|
||||
return &upstream_dto.Upstream{
|
||||
Type: "http",
|
||||
Balance: "round-robin",
|
||||
Timeout: 300000,
|
||||
Retry: 0,
|
||||
Remark: fmt.Sprintf("auto create by ai service %s,provider is %s", id, provider),
|
||||
LimitPeerSecond: 0,
|
||||
ProxyHeaders: nil,
|
||||
Scheme: uri.Scheme(),
|
||||
PassHost: "node",
|
||||
Nodes: []*upstream_dto.NodeConfig{
|
||||
{
|
||||
Address: uri.Host(),
|
||||
Weight: 100,
|
||||
},
|
||||
},
|
||||
}
|
||||
tmp, err := loader.LoadFromData([]byte(doc.Content))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg := i.settingModule.Get(ctx)
|
||||
|
||||
tmp.AddServer(&openapi3.Server{
|
||||
URL: cfg.InvokeAddress,
|
||||
})
|
||||
return tmp, nil
|
||||
}
|
||||
|
||||
func (i *imlServiceController) ExportSwagger(ctx *gin.Context) {
|
||||
id, has := ctx.Params.Get("id")
|
||||
if !has {
|
||||
ctx.JSON(200, &pm3.Response{
|
||||
Code: -1,
|
||||
Success: "fail",
|
||||
Message: fmt.Sprintf("id is required"),
|
||||
})
|
||||
return
|
||||
}
|
||||
s, err := i.module.Get(ctx, id)
|
||||
if err != nil {
|
||||
ctx.JSON(200, &pm3.Response{
|
||||
Code: -1,
|
||||
Success: "fail",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
tmp, err := i.swagger(ctx, id)
|
||||
if err != nil {
|
||||
ctx.JSON(200, &pm3.Response{
|
||||
Code: -1,
|
||||
Success: "fail",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
data, _ := tmp.MarshalJSON()
|
||||
ctx.Status(200)
|
||||
// 设置响应头
|
||||
ctx.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s.json", strings.Replace(s.Name, " ", "_", -1)))
|
||||
ctx.Header("Content-Type", "application/octet-stream")
|
||||
ctx.Header("Content-Transfer-Encoding", "binary")
|
||||
ctx.Writer.Write(data)
|
||||
return
|
||||
}
|
||||
|
||||
func (i *imlServiceController) Swagger(ctx *gin.Context) {
|
||||
id, has := ctx.Params.Get("id")
|
||||
if !has {
|
||||
ctx.JSON(200, &pm3.Response{
|
||||
Code: -1,
|
||||
Success: "fail",
|
||||
Message: fmt.Sprintf("id is required"),
|
||||
})
|
||||
return
|
||||
}
|
||||
tmp, err := i.swagger(ctx, id)
|
||||
if err != nil {
|
||||
ctx.JSON(200, &pm3.Response{
|
||||
Code: -1,
|
||||
Success: "fail",
|
||||
Message: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
ctx.JSON(200, tmp)
|
||||
return
|
||||
}
|
||||
|
||||
func (i *imlServiceController) Simple(ctx *gin.Context) ([]*service_dto.SimpleServiceItem, error) {
|
||||
return i.module.Simple(ctx)
|
||||
}
|
||||
|
||||
func (i *imlServiceController) MySimple(ctx *gin.Context) ([]*service_dto.SimpleServiceItem, error) {
|
||||
return i.module.MySimple(ctx)
|
||||
}
|
||||
|
||||
func (i *imlServiceController) editAIService(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error) {
|
||||
@@ -310,12 +228,21 @@ func (i *imlServiceController) SearchMyServices(ctx *gin.Context, teamId string,
|
||||
return i.module.SearchMyServices(ctx, teamId, keyword)
|
||||
}
|
||||
|
||||
//func (i *imlServiceController) Simple(ctx *gin.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
|
||||
// return i.module.Simple(ctx, keyword)
|
||||
//}
|
||||
//
|
||||
//func (i *imlServiceController) MySimple(ctx *gin.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
|
||||
// return i.module.MySimple(ctx, keyword)
|
||||
//}
|
||||
|
||||
func (i *imlServiceController) Get(ctx *gin.Context, id string) (*service_dto.Service, error) {
|
||||
now := time.Now()
|
||||
defer func() {
|
||||
log.Infof("get service %s cost %d ms", id, time.Since(now).Milliseconds())
|
||||
}()
|
||||
return i.module.Get(ctx, id)
|
||||
|
||||
}
|
||||
|
||||
func (i *imlServiceController) Search(ctx *gin.Context, teamID string, keyword string) ([]*service_dto.ServiceItem, error) {
|
||||
@@ -409,23 +336,3 @@ func (i *imlAppController) GetApp(ctx *gin.Context, appId string) (*service_dto.
|
||||
func (i *imlAppController) DeleteApp(ctx *gin.Context, appId string) error {
|
||||
return i.module.DeleteApp(ctx, appId)
|
||||
}
|
||||
|
||||
func newAIUpstream(id string, provider string, uri model_runtime.IProviderURI) *upstream_dto.Upstream {
|
||||
return &upstream_dto.Upstream{
|
||||
Type: "http",
|
||||
Balance: "round-robin",
|
||||
Timeout: 300000,
|
||||
Retry: 0,
|
||||
Remark: fmt.Sprintf("auto create by ai service %s,provider is %s", id, provider),
|
||||
LimitPeerSecond: 0,
|
||||
ProxyHeaders: nil,
|
||||
Scheme: uri.Scheme(),
|
||||
PassHost: "node",
|
||||
Nodes: []*upstream_dto.NodeConfig{
|
||||
{
|
||||
Address: uri.Host(),
|
||||
Weight: 100,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,12 @@ type IServiceController interface {
|
||||
Delete(ctx *gin.Context, id string) error
|
||||
ServiceDoc(ctx *gin.Context, id string) (*service_dto.ServiceDoc, error)
|
||||
SaveServiceDoc(ctx *gin.Context, id string, input *service_dto.SaveServiceDoc) error
|
||||
Simple(ctx *gin.Context) ([]*service_dto.SimpleServiceItem, error)
|
||||
MySimple(ctx *gin.Context) ([]*service_dto.SimpleServiceItem, error)
|
||||
|
||||
Swagger(ctx *gin.Context)
|
||||
ExportSwagger(ctx *gin.Context)
|
||||
//createAIService(ctx *gin.Context, teamID string, input *service_dto.CreateService) (*service_dto.Service, error)
|
||||
//editAIService(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error)
|
||||
//DeleteAIService(ctx *gin.Context, id string) error
|
||||
//SearchMyAIServices(ctx *gin.Context, teamID string, keyword string) ([]*service_dto.ServiceItem, error)
|
||||
//SearchAIServices(ctx *gin.Context, teamID string, keyword string) ([]*service_dto.ServiceItem, error)
|
||||
}
|
||||
|
||||
type IAppController interface {
|
||||
|
||||
@@ -1,263 +0,0 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
|
||||
|
||||
"github.com/APIParkLab/APIPark/module/service"
|
||||
"github.com/APIParkLab/APIPark/module/strategy"
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var _ IStrategyController = (*imlStrategyController)(nil)
|
||||
|
||||
type imlStrategyController struct {
|
||||
strategyModule strategy.IStrategyModule `autowired:""`
|
||||
serviceModule service.IServiceModule `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) Restore(ctx *gin.Context, id string) error {
|
||||
return i.strategyModule.Restore(ctx, id)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) DeleteServiceStrategy(ctx *gin.Context, serviceId string, id string) error {
|
||||
return i.strategyModule.DeleteServiceStrategy(ctx, serviceId, id)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) ToPublish(ctx *gin.Context, driver string) ([]*strategy_dto.ToPublishItem, string, string, bool, error) {
|
||||
list, err := i.strategyModule.ToPublish(ctx, driver)
|
||||
if err != nil {
|
||||
return nil, "", "", false, err
|
||||
}
|
||||
data, _ := json.Marshal(list)
|
||||
source := base64.StdEncoding.EncodeToString(data)
|
||||
return list, source, time.Now().Format("20060102150405") + "-release", len(list) > 0, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) FilterGlobalRemote(ctx *gin.Context, name string) ([]*strategy_dto.Title, []any, int64, string, string, error) {
|
||||
f, has := strategy_filter.RemoteFilter(name)
|
||||
if !has {
|
||||
return nil, nil, 0, "", "", fmt.Errorf("filter not found: %s", name)
|
||||
}
|
||||
scopeAllow := false
|
||||
for _, s := range f.Scopes() {
|
||||
if s == strategy_filter.ScopeGlobal {
|
||||
scopeAllow = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !scopeAllow {
|
||||
return nil, nil, 0, "", "", fmt.Errorf("scope not allowed: %s", name)
|
||||
}
|
||||
|
||||
list, total, err := f.RemoteList(ctx, "", nil, -1, -1)
|
||||
if err != nil {
|
||||
return nil, nil, 0, "", "", err
|
||||
}
|
||||
return utils.SliceToSlice(f.Titles(), func(l strategy_filter.OptionTitle) *strategy_dto.Title {
|
||||
return &strategy_dto.Title{
|
||||
Field: l.Field,
|
||||
Title: l.Title,
|
||||
}
|
||||
}), list, total, f.Key(), f.Key(), nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) FilterServiceRemote(ctx *gin.Context, serviceId string, name string) ([]*strategy_dto.Title, []any, int64, string, string, error) {
|
||||
f, has := strategy_filter.RemoteFilter(name)
|
||||
if !has {
|
||||
return nil, nil, 0, "", "", fmt.Errorf("filter not found: %s", name)
|
||||
}
|
||||
scopeAllow := false
|
||||
for _, s := range f.Scopes() {
|
||||
if s == strategy_filter.ScopeService {
|
||||
scopeAllow = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !scopeAllow {
|
||||
return nil, nil, 0, "", "", fmt.Errorf("scope not allowed: %s", name)
|
||||
}
|
||||
list, total, err := f.RemoteList(ctx, "", map[string]interface{}{"service": serviceId}, -1, -1)
|
||||
if err != nil {
|
||||
return nil, nil, 0, "", "", err
|
||||
}
|
||||
return utils.SliceToSlice(f.Titles(), func(l strategy_filter.OptionTitle) *strategy_dto.Title {
|
||||
return &strategy_dto.Title{
|
||||
Field: l.Field,
|
||||
Title: l.Title,
|
||||
}
|
||||
}), list, total, f.Key(), "list", nil
|
||||
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) filterOptions(ctx *gin.Context, scope string) ([]*strategy_dto.FilterOption, error) {
|
||||
m, has := strategy_filter.Options(scope)
|
||||
if !has {
|
||||
return nil, fmt.Errorf("scope not found: %s", scope)
|
||||
}
|
||||
|
||||
list := utils.MapToSlice(m, func(key string, value *strategy_filter.Option) *strategy_dto.FilterOption {
|
||||
pattern := ""
|
||||
if value.Pattern != nil {
|
||||
pattern = value.Pattern.String()
|
||||
}
|
||||
return &strategy_dto.FilterOption{
|
||||
Name: value.Name,
|
||||
Title: value.Title,
|
||||
Type: value.Type,
|
||||
Pattern: pattern,
|
||||
Options: value.Options,
|
||||
}
|
||||
})
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
return list[i].Name < list[j].Name
|
||||
})
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) FilterServiceOptions(ctx *gin.Context) ([]*strategy_dto.FilterOption, error) {
|
||||
return i.filterOptions(ctx, strategy_filter.ScopeService)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) FilterGlobalOptions(ctx *gin.Context) ([]*strategy_dto.FilterOption, error) {
|
||||
return i.filterOptions(ctx, strategy_filter.ScopeGlobal)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) GetStrategy(ctx *gin.Context, id string) (*strategy_dto.Strategy, error) {
|
||||
return i.strategyModule.Get(ctx, id)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) search(ctx *gin.Context, keyword string, scope strategy_dto.Scope, target string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error) {
|
||||
p, err := strconv.Atoi(page)
|
||||
if err != nil {
|
||||
if page != "" {
|
||||
return nil, 0, fmt.Errorf("page error: %s", err)
|
||||
}
|
||||
p = 1
|
||||
}
|
||||
ps, err := strconv.Atoi(pageSize)
|
||||
if err != nil {
|
||||
if pageSize != "" {
|
||||
return nil, 0, fmt.Errorf("page size error: %s", err)
|
||||
}
|
||||
ps = 20
|
||||
}
|
||||
ss := make([]string, 0)
|
||||
json.Unmarshal([]byte(sort), &ss)
|
||||
fs := make([]string, 0)
|
||||
json.Unmarshal([]byte(filters), &fs)
|
||||
list, total, err := i.strategyModule.Search(ctx, keyword, driver, scope, target, p, ps, fs, ss...)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) GlobalStrategyList(ctx *gin.Context, keyword string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error) {
|
||||
|
||||
return i.search(ctx, keyword, strategy_dto.ToScope(strategy_dto.ScopeGlobal), "", driver, page, pageSize, order, sort, filters)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) CreateGlobalStrategy(ctx *gin.Context, driver string, input *strategy_dto.Create) error {
|
||||
input.Driver = driver
|
||||
input.Scope = strategy_dto.ToScope(strategy_dto.ScopeGlobal)
|
||||
|
||||
return i.strategyModule.Create(ctx, input)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) PublishGlobalStrategy(ctx *gin.Context, driver string) error {
|
||||
return i.strategyModule.Publish(ctx, driver, strategy_dto.ScopeGlobal, "")
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) ServiceStrategyList(ctx *gin.Context, keyword string, serviceId string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error) {
|
||||
|
||||
return i.search(ctx, keyword, strategy_dto.ToScope(strategy_dto.ScopeService), serviceId, driver, page, pageSize, order, sort, filters)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) CreateServiceStrategy(ctx *gin.Context, serviceId string, driver string, input *strategy_dto.Create) error {
|
||||
_, err := i.serviceModule.Get(ctx, serviceId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create service strategy error: %s", err)
|
||||
}
|
||||
input.Driver = driver
|
||||
input.Scope = strategy_dto.ToScope(strategy_dto.ScopeService)
|
||||
input.Target = serviceId
|
||||
|
||||
return i.strategyModule.Create(ctx, input)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) EditStrategy(ctx *gin.Context, id string, input *strategy_dto.Edit) error {
|
||||
return i.strategyModule.Edit(ctx, id, input)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) EnableStrategy(ctx *gin.Context, id string) error {
|
||||
return i.strategyModule.Enable(ctx, id)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) DisableStrategy(ctx *gin.Context, id string) error {
|
||||
return i.strategyModule.Disable(ctx, id)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) DeleteStrategy(ctx *gin.Context, id string) error {
|
||||
return i.strategyModule.Delete(ctx, id)
|
||||
}
|
||||
|
||||
func genTime(t string, defaultValue time.Time) (time.Time, error) {
|
||||
if t == "" {
|
||||
return defaultValue, nil
|
||||
}
|
||||
|
||||
s, err := strconv.ParseInt(t, 10, 64)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return time.Unix(s, 0), nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) GetStrategyLogs(ctx *gin.Context, keyword string, strategyId string, start string, end string, limit string, offset string) ([]*strategy_dto.LogItem, int64, error) {
|
||||
now := time.Now()
|
||||
|
||||
s, err := genTime(start, now.Add(-time.Hour*24*30))
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("start time error: %s", err)
|
||||
}
|
||||
e, err := genTime(end, now)
|
||||
if err != nil {
|
||||
|
||||
return nil, 0, fmt.Errorf("end time error: %s", err)
|
||||
}
|
||||
if s.After(e) {
|
||||
return nil, 0, fmt.Errorf("start time must be less than end time")
|
||||
}
|
||||
l, err := strconv.ParseInt(limit, 10, 64)
|
||||
if err != nil && limit != "" {
|
||||
|
||||
return nil, 0, err
|
||||
}
|
||||
o, err := strconv.ParseInt(offset, 10, 64)
|
||||
if err != nil && offset != "" {
|
||||
return nil, 0, err
|
||||
}
|
||||
if l < 1 {
|
||||
l = 15
|
||||
}
|
||||
if o < 1 {
|
||||
o = 1
|
||||
}
|
||||
return i.strategyModule.GetStrategyLogs(ctx, keyword, strategyId, s, e, l, o)
|
||||
}
|
||||
|
||||
func (i *imlStrategyController) LogInfo(ctx *gin.Context, id string) (*strategy_dto.LogInfo, error) {
|
||||
|
||||
return i.strategyModule.StrategyLogInfo(ctx, id)
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type IStrategyController interface {
|
||||
GlobalStrategyList(ctx *gin.Context, keyword string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error)
|
||||
CreateGlobalStrategy(ctx *gin.Context, driver string, input *strategy_dto.Create) error
|
||||
PublishGlobalStrategy(ctx *gin.Context, driver string) error
|
||||
|
||||
ServiceStrategyList(ctx *gin.Context, keyword string, serviceId string, driver string, page string, pageSize string, order string, sort string, filters string) ([]*strategy_dto.StrategyItem, int64, error)
|
||||
CreateServiceStrategy(ctx *gin.Context, serviceId string, driver string, input *strategy_dto.Create) error
|
||||
|
||||
EditStrategy(ctx *gin.Context, id string, input *strategy_dto.Edit) error
|
||||
GetStrategy(ctx *gin.Context, id string) (*strategy_dto.Strategy, error)
|
||||
EnableStrategy(ctx *gin.Context, id string) error
|
||||
DisableStrategy(ctx *gin.Context, id string) error
|
||||
|
||||
DeleteStrategy(ctx *gin.Context, id string) error
|
||||
DeleteServiceStrategy(ctx *gin.Context, serviceId string, id string) error
|
||||
|
||||
Restore(ctx *gin.Context, id string) error
|
||||
|
||||
FilterGlobalOptions(ctx *gin.Context) ([]*strategy_dto.FilterOption, error)
|
||||
FilterServiceOptions(ctx *gin.Context) ([]*strategy_dto.FilterOption, error)
|
||||
|
||||
FilterGlobalRemote(ctx *gin.Context, name string) ([]*strategy_dto.Title, []any, int64, string, string, error)
|
||||
FilterServiceRemote(ctx *gin.Context, serviceId string, name string) ([]*strategy_dto.Title, []any, int64, string, string, error)
|
||||
|
||||
ToPublish(ctx *gin.Context, driver string) ([]*strategy_dto.ToPublishItem, string, string, bool, error)
|
||||
|
||||
GetStrategyLogs(ctx *gin.Context, keyword string, strategyId string, start string, end string, limit string, offset string) ([]*strategy_dto.LogItem, int64, error)
|
||||
LogInfo(ctx *gin.Context, id string) (*strategy_dto.LogInfo, error)
|
||||
}
|
||||
|
||||
type IStrategyCommonController interface {
|
||||
}
|
||||
|
||||
func init() {
|
||||
autowire.Auto[IStrategyController](func() reflect.Value {
|
||||
return reflect.ValueOf(&imlStrategyController{})
|
||||
})
|
||||
}
|
||||
@@ -146,20 +146,8 @@ export const PublishApprovalModalContent = forwardRef<PublishApprovalModalHandle
|
||||
...x,
|
||||
title: typeof x.title === 'string' ? $t(x.title) : x.title,
|
||||
...(x.dataIndex === 'status' ? {
|
||||
render:(_,entity)=> {
|
||||
switch(entity.change){
|
||||
case 'none':
|
||||
return '-'
|
||||
case 'new':
|
||||
return $t('新建')
|
||||
case 'update':
|
||||
return $t('更新')
|
||||
case 'delete':
|
||||
return $t('删除')
|
||||
default:
|
||||
return '-'
|
||||
}
|
||||
}
|
||||
render:(_,entity)=>(
|
||||
entity.status === 0 ? $t('正常') : $t('无效'))
|
||||
}:{})
|
||||
}
|
||||
}),[state.language])
|
||||
|
||||
@@ -37,8 +37,6 @@ const TableIconName = {
|
||||
const TableBtnWithPermission = ({ btnTitle, access, tooltip, disabled, navigateTo, onClick, className, btnType }: TableBtnWithPermissionProps) => {
|
||||
|
||||
const [btnAccess, setBtnAccess] = useState<boolean>(false)
|
||||
const [btnStatus, setBtnStatus] = useState<boolean>(false)
|
||||
const [closeToolTip, setCloseToolTip] = useState<boolean>(false)
|
||||
const { accessData, checkPermission, accessInit } = useGlobalContext()
|
||||
const navigate = useNavigate()
|
||||
const lastAccess = useMemo(() => {
|
||||
@@ -54,27 +52,16 @@ const TableBtnWithPermission = ({ btnTitle, access, tooltip, disabled, navigateT
|
||||
|
||||
const handleClick = useCallback((e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation()
|
||||
setTimeout(() => {
|
||||
setBtnStatus(false)
|
||||
setCloseToolTip(true)
|
||||
})
|
||||
|
||||
navigateTo ? navigate(navigateTo) : onClick?.()
|
||||
}, [navigateTo, navigate, onClick])
|
||||
const changeTooltipStatus = (open: boolean) => {
|
||||
setBtnStatus(open)
|
||||
if (closeToolTip) {
|
||||
setBtnStatus(false)
|
||||
setCloseToolTip(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (<>{
|
||||
!btnAccess || (disabled && tooltip) ?
|
||||
<Tooltip placement="top" title={tooltip ?? $t('暂无(0)权限,请联系管理员分配。', [$t(btnTitle).toLowerCase()])}>
|
||||
<Button type="text" disabled={true} className={`h-[22px] border-none p-0 flex items-center bg-transparent ${className}`} key={btnType} icon={<Icon icon={TableIconName[btnType as keyof typeof TableIconName]} width="18" height="18" />} >{ }</Button>
|
||||
</Tooltip>
|
||||
:
|
||||
<Tooltip placement="top" title={$t(btnTitle)} trigger='hover' open={btnStatus} onOpenChange={changeTooltipStatus}>
|
||||
<Tooltip placement="top" title={$t(btnTitle)}>
|
||||
<Button type="text" disabled={disabled} className={`h-[22px] border-none p-0 flex items-center bg-transparent ${className} `} key={btnType} icon={<Icon icon={TableIconName[btnType as keyof typeof TableIconName]} width="18" height="18" />} onClick={handleClick}>{ }</Button>
|
||||
</Tooltip>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useState } from 'react';
|
||||
import { Radio, DatePicker, GetProps, RadioChangeEvent } from 'antd';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||
@@ -12,80 +12,69 @@ export type RangeValue = [Dayjs | null, Dayjs | null] | null;
|
||||
dayjs.extend(customParseFormat);
|
||||
|
||||
export type TimeRange = {
|
||||
start: number | null
|
||||
end: number | null
|
||||
start:number|null
|
||||
end:number|null
|
||||
}
|
||||
|
||||
export type TimeRangeButton = '' | 'hour' | 'day' | 'threeDays' | 'sevenDays';
|
||||
export type TimeRangeButton = ''| 'hour' | 'day' | 'threeDays' | 'sevenDays';
|
||||
|
||||
type TimeRangeSelectorProps = {
|
||||
initialTimeButton?: TimeRangeButton,
|
||||
initialDatePickerValue?: RangeValue
|
||||
onTimeRangeChange?: (timeRange: TimeRange) => void
|
||||
hideTitle?: boolean
|
||||
onTimeButtonChange: (time: TimeRangeButton) => void
|
||||
labelSize?: 'small' | 'default'
|
||||
bindRef?: any
|
||||
hideBtns?: TimeRangeButton[]
|
||||
defaultTimeButton?: TimeRangeButton
|
||||
}
|
||||
const TimeRangeSelector = (props: TimeRangeSelectorProps) => {
|
||||
const { initialTimeButton, initialDatePickerValue, onTimeRangeChange, hideTitle, onTimeButtonChange, labelSize = 'default', bindRef, hideBtns = [], defaultTimeButton = 'hour' } = props
|
||||
initialTimeButton?:TimeRangeButton,
|
||||
initialDatePickerValue?:RangeValue
|
||||
onTimeRangeChange?:(timeRange:TimeRange) =>void
|
||||
hideTitle?:boolean
|
||||
onTimeButtonChange:(time:TimeRangeButton) =>void
|
||||
labelSize?:'small'|'default'
|
||||
}
|
||||
const TimeRangeSelector = (props:TimeRangeSelectorProps) => {
|
||||
const {initialTimeButton,initialDatePickerValue,onTimeRangeChange,hideTitle,onTimeButtonChange,labelSize='default'} = props
|
||||
const [timeButton, setTimeButton] = useState(initialTimeButton || '');
|
||||
const [datePickerValue, setDatePickerValue] = useState<RangeValue>(initialDatePickerValue || [null, null]);
|
||||
useEffect(() => {
|
||||
if (bindRef) {
|
||||
bindRef({ reset });
|
||||
}
|
||||
}, [bindRef])
|
||||
const [datePickerValue, setDatePickerValue] = useState<RangeValue>(initialDatePickerValue || [null,null]);
|
||||
|
||||
// 根据选择的时间范围计算开始和结束时间
|
||||
const calculateTimeRange = (curBtn: TimeRangeButton) => {
|
||||
const currentSecond = Math.floor(Date.now() / 1000); // 当前秒级时间戳
|
||||
let startMin = currentSecond - 60 * 60
|
||||
const calculateTimeRange = (curBtn:'hour'|'day'|'threeDays'|'sevenDays') => {
|
||||
const currentSecond = new Date().getTime() // 当前毫秒数时间戳
|
||||
const currentMin = currentSecond - (currentSecond % (60 * 1000)) // 当前分钟数时间戳
|
||||
let startMin = currentMin - 60 * 60 * 1000
|
||||
switch (curBtn) {
|
||||
case 'hour': {
|
||||
startMin = currentSecond - 60 * 60
|
||||
break
|
||||
case 'hour': {
|
||||
startMin = currentMin - 60 * 60 * 1000
|
||||
break
|
||||
}
|
||||
case 'day': {
|
||||
startMin = currentMin - 24 * 60 * 60 * 1000
|
||||
break
|
||||
}
|
||||
case 'threeDays': {
|
||||
startMin =
|
||||
new Date(new Date().setHours(0, 0, 0, 0)).getTime() -
|
||||
2 * 24 * 60 * 60 * 1000
|
||||
break
|
||||
}
|
||||
case 'sevenDays': {
|
||||
startMin =
|
||||
new Date(new Date().setHours(0, 0, 0, 0)).getTime() -
|
||||
6 * 24 * 60 * 60 * 1000
|
||||
break
|
||||
}
|
||||
}
|
||||
case 'day': {
|
||||
startMin = currentSecond - 24 * 60 * 60
|
||||
break
|
||||
}
|
||||
case 'threeDays': {
|
||||
startMin =
|
||||
Math.floor(new Date().setHours(0, 0, 0, 0) / 1000) -
|
||||
2 * 24 * 60 * 60
|
||||
break
|
||||
}
|
||||
case 'sevenDays': {
|
||||
startMin =
|
||||
Math.floor(new Date().setHours(0, 0, 0, 0) / 1000) -
|
||||
6 * 24 * 60 * 60
|
||||
break
|
||||
}
|
||||
}
|
||||
if (onTimeRangeChange) {
|
||||
onTimeRangeChange({ start: startMin, end: currentSecond });
|
||||
onTimeRangeChange({ start: startMin / 1000, end: currentMin / 1000 });
|
||||
}
|
||||
};
|
||||
|
||||
// 处理单选按钮的变化
|
||||
const handleRadioChange = (e: RadioChangeEvent) => {
|
||||
const handleRadioChange = (e:RadioChangeEvent) => {
|
||||
setTimeButton(e.target.value);
|
||||
onTimeButtonChange?.(e.target.value)
|
||||
setDatePickerValue(null)
|
||||
calculateTimeRange(e.target.value);
|
||||
};
|
||||
const reset = () => {
|
||||
setTimeButton(defaultTimeButton)
|
||||
calculateTimeRange(defaultTimeButton)
|
||||
setDatePickerValue(null)
|
||||
}
|
||||
|
||||
// 处理日期选择器的变化
|
||||
const handleDatePickerChange = (dates: RangeValue) => {
|
||||
setTimeButton(dates ? '' : defaultTimeButton)
|
||||
onTimeButtonChange?.(dates ? '' : defaultTimeButton)
|
||||
setTimeButton(dates ? '' : 'hour')
|
||||
onTimeButtonChange?.(dates ? '' : 'hour')
|
||||
setDatePickerValue(dates);
|
||||
if (dates && Array.isArray(dates) && dates.length === 2) {
|
||||
const [startDate, endDate] = dates;
|
||||
@@ -95,37 +84,34 @@ const TimeRangeSelector = (props: TimeRangeSelectorProps) => {
|
||||
onTimeRangeChange({ start, end });
|
||||
}
|
||||
}
|
||||
if (!dates) {
|
||||
calculateTimeRange(defaultTimeButton)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
|
||||
// Can not select days before today and today
|
||||
|
||||
|
||||
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
|
||||
// Can not select days before today and today
|
||||
return current && current.valueOf() > dayjs().startOf('day').valueOf();
|
||||
};
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-nowrap items-center pt-btnybase mr-btnybase">
|
||||
{!hideTitle && <label className={`whitespace-nowrap `}>{$t('时间')}:</label>}
|
||||
<Radio.Group className="whitespace-nowrap" value={timeButton} onChange={handleRadioChange} buttonStyle="solid">
|
||||
{hideBtns?.length && hideBtns.includes('hour') ? null : <Radio.Button value="hour">{$t('近1小时')}</Radio.Button>}
|
||||
{hideBtns?.length && hideBtns.includes('day') ? null : <Radio.Button value="day">{$t('近24小时')}</Radio.Button>}
|
||||
{hideBtns?.length && hideBtns.includes('threeDays') ? null : <Radio.Button value="threeDays">{$t('近3天')}</Radio.Button>}
|
||||
{hideBtns?.length && hideBtns.includes('sevenDays') ? null : <Radio.Button className="rounded-e-none" value="sevenDays">{$t('近7天')}</Radio.Button>}
|
||||
</Radio.Group>
|
||||
{!hideTitle && <label className={`whitespace-nowrap `}>{$t('时间')}:</label>}
|
||||
<Radio.Group className="whitespace-nowrap" value={timeButton} onChange={handleRadioChange} buttonStyle="solid">
|
||||
<Radio.Button value="hour">{$t('近1小时')}</Radio.Button>
|
||||
<Radio.Button value="day">{$t('近24小时')}</Radio.Button>
|
||||
<Radio.Button value="threeDays">{$t('近3天')}</Radio.Button>
|
||||
<Radio.Button className="rounded-e-none" value="sevenDays">{$t('近7天')}</Radio.Button>
|
||||
</Radio.Group>
|
||||
<DatePicker.RangePicker
|
||||
value={datePickerValue}
|
||||
className="rounded-s-none ml-[-1px]"
|
||||
className="rounded-s-none ml-[-1px]"
|
||||
disabledDate={disabledDate}
|
||||
onChange={handleDatePickerChange}
|
||||
onOpenChange={(open) => {
|
||||
if (!open && datePickerValue && datePickerValue.length > 2) {
|
||||
setTimeButton('')
|
||||
onTimeButtonChange?.('')
|
||||
}
|
||||
onOpenChange={(open)=>{
|
||||
if(!open && datePickerValue && datePickerValue.length > 2){
|
||||
setTimeButton('')
|
||||
onTimeButtonChange?.('')
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -181,10 +181,6 @@ export const TranslateWord = ()=>{
|
||||
{$t('请输入IP地址或CIDR范围,每条以换行分割')}
|
||||
{$t('待更新')}
|
||||
{$t('待删除')}
|
||||
{$t('内容')}
|
||||
{$t('调用地址')}
|
||||
{$t('消费者 IP')}
|
||||
{$t('鉴权名称')}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -13,7 +13,6 @@ export interface CodeboxApiRef {
|
||||
formatCode: () => void
|
||||
}
|
||||
|
||||
export type codeBoxLanguagesType = 'html' | 'json' | 'xml' | 'javascript' | 'css' | 'plaintext'|'yaml'
|
||||
interface CodeboxProps {
|
||||
options?: MonacoEditor.IStandaloneEditorConstructionOptions
|
||||
value?: string
|
||||
@@ -23,7 +22,7 @@ interface CodeboxProps {
|
||||
height?: string | null
|
||||
readOnly?: boolean
|
||||
apiRef?: RefObject<CodeboxApiRef>
|
||||
language?: codeBoxLanguagesType
|
||||
language?: 'html' | 'json' | 'xml' | 'javascript' | 'css' | 'plaintext'|'yaml'
|
||||
extraContent?:React.ReactNode
|
||||
sx?:Record<string,unknown>
|
||||
editorTheme?:'vs' | 'vs-dark' | 'hc-black'
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { codeBoxLanguagesType } from "@common/components/postcat/api/Codebox";
|
||||
|
||||
export const MatchRules = [
|
||||
{ value: 'inner', label: '数据格式' },
|
||||
@@ -55,34 +54,4 @@ export const StrategyStatusEnum = {
|
||||
"offline":'text-status_fail',
|
||||
"delete":'text-status_offline',
|
||||
}
|
||||
|
||||
export const contentTypeToLanguageMap: Record<string, codeBoxLanguagesType> = {
|
||||
// JSON
|
||||
"application/json": "json",
|
||||
|
||||
// XML
|
||||
"application/xml": "xml",
|
||||
"text/xml": "xml",
|
||||
|
||||
// HTML
|
||||
"text/html": "html",
|
||||
|
||||
// Plain text
|
||||
"text/plain": "plaintext",
|
||||
|
||||
// JavaScript
|
||||
"application/javascript": "javascript",
|
||||
"text/javascript": "javascript",
|
||||
|
||||
// CSS
|
||||
"text/css": "css",
|
||||
|
||||
// YAML
|
||||
"application/x-yaml": "yaml",
|
||||
"text/yaml": "yaml",
|
||||
|
||||
// Others (fallback)
|
||||
"*/*": "plaintext", // 任意类型默认处理为普通文本
|
||||
};
|
||||
|
||||
|
||||
@@ -749,19 +749,5 @@
|
||||
"K67f4e9bb": "The domain name for obtaining API market documentation information when integrating with external platforms",
|
||||
"K1da86266": "Invalid",
|
||||
"K3a34d49b": "Pending Update",
|
||||
"Kd2850420": "Pending Deletion",
|
||||
"K9ada4366": "Operation successful, the page will refresh shortly",
|
||||
"K9b332ab1": "Request prefix",
|
||||
"K3d78d483": "HTTP headers",
|
||||
"K17dc3a62": "Data logs",
|
||||
"Ke429194e": "Processing logs",
|
||||
"K84ffb1dd": "Enter the invocation address, consumer IP, and consumer condition to search",
|
||||
"Kb147fabc": "Create",
|
||||
"K40ca4f2": "Update",
|
||||
"K3e7aa0ad": "Content",
|
||||
"K2f5fdf5e": "Call Address",
|
||||
"K1bc5e0a3": "Consumer IP",
|
||||
"K6f39ea21": "Authentication Name",
|
||||
"K8c34c02f": "Before Masking",
|
||||
"K8e3d388d": "After Masking"
|
||||
"Kd2850420": "Pending Deletion"
|
||||
}
|
||||
|
||||
@@ -771,19 +771,6 @@
|
||||
"K67f4e9bb": "外部プラットフォームと統合する際に、API市場のドキュメント情報を取得するためのドメイン名",
|
||||
"K1da86266": "無効",
|
||||
"K3a34d49b": "更新待ち",
|
||||
"Kd2850420": "削除待ち",
|
||||
"K9ada4366": "操作成功、ページを更新します",
|
||||
"K9b332ab1": "リクエストプレフィックス",
|
||||
"K3d78d483": "HTTPヘッダー",
|
||||
"K17dc3a62": "データログ",
|
||||
"Ke429194e": "ログの処理",
|
||||
"K84ffb1dd": "呼び出しアドレス、コンシューマーIP、条件を入力して検索",
|
||||
"Kb147fabc": "新規作成",
|
||||
"K40ca4f2": "更新",
|
||||
"K3e7aa0ad": "内容",
|
||||
"K2f5fdf5e": "呼び出しアドレス",
|
||||
"K1bc5e0a3": "コンシューマー IP",
|
||||
"K6f39ea21": "認証名",
|
||||
"K8c34c02f": "マスキング前",
|
||||
"K8e3d388d": "マスキング後"
|
||||
"Kd2850420": "削除待ち"
|
||||
|
||||
}
|
||||
|
||||
@@ -702,19 +702,5 @@
|
||||
"K31faa2a1": "优先级",
|
||||
"Kbdec9fa": "筛选条件",
|
||||
"Kbcbb7391": "处理数",
|
||||
"Kad207008": "编辑",
|
||||
"K9ada4366": "操作成功,即将刷新页面",
|
||||
"K9b332ab1": "请求前缀",
|
||||
"K3d78d483": "HTTP 头部",
|
||||
"K17dc3a62": "数据日志",
|
||||
"Ke429194e": "处理日志",
|
||||
"K84ffb1dd": "输入调用地址、消费者IP和消费者条件查找",
|
||||
"Kb147fabc": "新建",
|
||||
"K40ca4f2": "更新",
|
||||
"K3e7aa0ad": "内容",
|
||||
"K2f5fdf5e": "调用地址",
|
||||
"K1bc5e0a3": "消费者 IP",
|
||||
"K6f39ea21": "鉴权名称",
|
||||
"K8c34c02f": "脱敏前",
|
||||
"K8e3d388d": "脱敏后"
|
||||
"Kad207008": "编辑"
|
||||
}
|
||||
@@ -771,19 +771,5 @@
|
||||
"K67f4e9bb": "與外部平台集成時,用於獲取 API 市場文檔信息的域名",
|
||||
"K1da86266": "無效",
|
||||
"K3a34d49b": "待更新",
|
||||
"Kd2850420": "待刪除",
|
||||
"K9ada4366": "操作成功,即將刷新頁面",
|
||||
"K9b332ab1": "請求前綴",
|
||||
"K3d78d483": "HTTP 標頭",
|
||||
"K17dc3a62": "數據日誌",
|
||||
"Ke429194e": "處理日誌",
|
||||
"K84ffb1dd": "輸入調用地址、消費者 IP 和消費者條件進行查找",
|
||||
"Kb147fabc": "新建",
|
||||
"K40ca4f2": "更新",
|
||||
"K3e7aa0ad": "內容",
|
||||
"K2f5fdf5e": "調用地址",
|
||||
"K1bc5e0a3": "消費者 IP",
|
||||
"K6f39ea21": "鑑權名稱",
|
||||
"K8c34c02f": "脫敏前",
|
||||
"K8e3d388d": "脫敏後"
|
||||
"Kd2850420": "待刪除"
|
||||
}
|
||||
|
||||
@@ -1,157 +1,115 @@
|
||||
|
||||
import { PageProColumns } from "@common/components/aoplatform/PageList";
|
||||
import { COLUMNS_TITLE } from "@common/const/const";
|
||||
import { EntityItem } from "@common/const/type";
|
||||
|
||||
export type PartitionConfigFieldType = {
|
||||
name?: string;
|
||||
id?: string;
|
||||
description?: string;
|
||||
prefix?: string
|
||||
url?: string
|
||||
managerAddress?: string
|
||||
canDelete?: boolean
|
||||
name?: string;
|
||||
id?: string;
|
||||
description?: string;
|
||||
prefix?:string
|
||||
url?:string
|
||||
managerAddress?:string
|
||||
canDelete?:boolean
|
||||
};
|
||||
|
||||
export type PartitionCertTableListItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
domains: string[];
|
||||
notAfter: string;
|
||||
notBefore: string;
|
||||
updater: EntityItem;
|
||||
updateTime: string;
|
||||
id:string;
|
||||
name: string;
|
||||
domains:string[];
|
||||
notAfter:string;
|
||||
notBefore:string;
|
||||
updater:EntityItem;
|
||||
updateTime:string;
|
||||
};
|
||||
|
||||
export type PartitionCertConfigFieldType = {
|
||||
id?: string
|
||||
key: string
|
||||
pem: string
|
||||
id?:string
|
||||
key:string
|
||||
pem:string
|
||||
};
|
||||
|
||||
export type PartitionCertConfigProps = {
|
||||
type: 'add' | 'edit'
|
||||
entity?: PartitionCertConfigFieldType
|
||||
type:'add'|'edit'
|
||||
entity?:PartitionCertConfigFieldType
|
||||
}
|
||||
|
||||
export type PartitionCertConfigHandle = {
|
||||
save: () => Promise<boolean | string>
|
||||
save:()=>Promise<boolean|string>
|
||||
}
|
||||
|
||||
export type PartitionClusterFieldType = {
|
||||
name?: string;
|
||||
id?: string;
|
||||
description?: string;
|
||||
address?: string;
|
||||
protocol?: 'http' | 'https'
|
||||
name?: string;
|
||||
id?: string;
|
||||
description?: string;
|
||||
address?:string;
|
||||
protocol?:'http'|'https'
|
||||
};
|
||||
|
||||
export type ClusterConfigProps = {
|
||||
mode: 'config' | 'retry' | 'result' | 'edit',
|
||||
clusterId?: string
|
||||
initFormValue?: { [k: string]: string | number }
|
||||
mode:'config' | 'retry' | 'result' | 'edit',
|
||||
clusterId?:string
|
||||
initFormValue?:{[k:string]:string|number}
|
||||
}
|
||||
|
||||
export type ClusterConfigHandle = {
|
||||
save: () => Promise<boolean | string>
|
||||
check: () => Promise<boolean>
|
||||
save:()=>Promise<boolean|string>
|
||||
check:()=>Promise<boolean>
|
||||
}
|
||||
|
||||
export type PartitionClusterTableListItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
status: 0 | 1;
|
||||
description: string;
|
||||
id:string;
|
||||
name: string;
|
||||
status:0|1;
|
||||
description:string;
|
||||
};
|
||||
|
||||
export type PartitionClusterNodeTableListItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
managerAddress: string[];
|
||||
serviceAddress: string[];
|
||||
peerAddress: string[];
|
||||
status: 0 | 1;
|
||||
id:string;
|
||||
name: string;
|
||||
managerAddress:string[];
|
||||
serviceAddress:string[];
|
||||
peerAddress:string[];
|
||||
status:0|1;
|
||||
};
|
||||
|
||||
export type PartitionClusterNodeModalTableListItem = {
|
||||
id: string,
|
||||
name: string,
|
||||
managerAddress: [],
|
||||
serviceAddress: [],
|
||||
peerAddress: string,
|
||||
status: string
|
||||
id: string,
|
||||
name: string,
|
||||
managerAddress: [],
|
||||
serviceAddress: [],
|
||||
peerAddress: string,
|
||||
status: string
|
||||
}
|
||||
|
||||
export type NodeModalFieldType = {
|
||||
address: string
|
||||
address:string
|
||||
}
|
||||
|
||||
|
||||
export type NodeModalHandle = {
|
||||
save: () => void
|
||||
save:()=>void
|
||||
}
|
||||
export type NodeModalPropsType = {
|
||||
changeStatus: (status: ClusterPageShowStatus) => void
|
||||
getClusterInfo: () => void
|
||||
status: ClusterPageShowStatus
|
||||
changeStatus:(status:ClusterPageShowStatus)=>void
|
||||
getClusterInfo:()=>void
|
||||
status:ClusterPageShowStatus
|
||||
}
|
||||
|
||||
export type ClusterPageShowStatus = 'view' | 'preview' | 'edit'
|
||||
export type ClusterPageShowStatus = 'view'|'preview'|'edit'
|
||||
export type PartitionTableListItem = {
|
||||
id: string;
|
||||
name: string;
|
||||
clusterNum: number;
|
||||
updater: EntityItem;
|
||||
updateTime: string;
|
||||
id:string;
|
||||
name: string;
|
||||
clusterNum:number;
|
||||
updater:EntityItem;
|
||||
updateTime:string;
|
||||
};
|
||||
|
||||
export type SimplePartition = EntityItem & { clusters: (EntityItem & { description: string })[] }
|
||||
export type SimplePartition = EntityItem & { clusters: (EntityItem & {description:string})[] }
|
||||
|
||||
export type PartitionDashboardConfigFieldType = {
|
||||
driver: string
|
||||
config: {
|
||||
org: string
|
||||
token: string
|
||||
addr: string
|
||||
}
|
||||
}
|
||||
export type PartitionDataLogHeaderListFieldType = {
|
||||
key: string
|
||||
value: string
|
||||
|
||||
}
|
||||
export type PartitionDataLogConfigFieldType = {
|
||||
headers: PartitionDataLogHeaderListFieldType[]
|
||||
url: string
|
||||
}
|
||||
|
||||
export const PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS: PageProColumns<PartitionDataLogConfigFieldType & { _id: string }>[] = [
|
||||
{
|
||||
title: ('标签'),
|
||||
dataIndex: 'key',
|
||||
formItemProps: {
|
||||
className: 'p-0 bg-transparent border-none',
|
||||
rootClassName: 'test',
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
whitespace: true
|
||||
},
|
||||
],
|
||||
},
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: ('内容'),
|
||||
dataIndex: 'value',
|
||||
formItemProps: {
|
||||
className: 'p-0 bg-transparent border-none'
|
||||
driver:string
|
||||
config:{
|
||||
org:string
|
||||
token:string
|
||||
addr:string
|
||||
}
|
||||
},
|
||||
{
|
||||
title: COLUMNS_TITLE.operate,
|
||||
valueType: 'option',
|
||||
btnNums: 2,
|
||||
render: () => null
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -239,7 +239,7 @@ export const AiServiceSubscriberConfig = forwardRef<AiServiceSubscriberConfigHan
|
||||
getAiServiceList()
|
||||
}, [serviceId]);
|
||||
|
||||
return (<WithPermission access="">
|
||||
return (<WithPermission access="team.service.subscription.add">
|
||||
<Form
|
||||
layout='vertical'
|
||||
labelAlign='left'
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useEffect } from "react";
|
||||
import { PartitionDashboardConfigFieldType } from "../../const/partitions/types";
|
||||
import { DASHBOARD_SETTING_DRIVER_OPTION_LIST } from "../../const/partitions/const";
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission";
|
||||
import { BasicResponse, PLACEHOLDER, STATUS_CODE } from "@common/const/const";
|
||||
import { BasicResponse, PLACEHOLDER, STATUS_CODE, VALIDATE_MESSAGE } from "@common/const/const";
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
import { $t } from "@common/locales";
|
||||
|
||||
@@ -29,10 +29,10 @@ export type DashboardSettingEditProps = {
|
||||
fetchData<BasicResponse<{info: PartitionDashboardConfigFieldType}>>('monitor/config',{method: 'POST',body:JSON.stringify(value),eoParams:{}}).then(response=>{
|
||||
const {code,msg} = response
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
message.success(msg || $t('操作成功,即将刷新页面'))
|
||||
message.success(msg || '操作成功,即将刷新页面')
|
||||
refreshData?.()
|
||||
}else{
|
||||
message.error(msg || $t('操作失败'))
|
||||
message.error(msg || '操作失败')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
import EditableTable from "@common/components/aoplatform/EditableTable"
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission"
|
||||
import { BasicResponse, PLACEHOLDER, STATUS_CODE } from "@common/const/const"
|
||||
import { useFetch } from "@common/hooks/http"
|
||||
import { $t } from "@common/locales"
|
||||
import { PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS, PartitionDataLogConfigFieldType, PartitionDataLogHeaderListFieldType } from "@core/const/partitions/types"
|
||||
import { Button, Form, Input, message } from "antd"
|
||||
import { useEffect } from "react"
|
||||
|
||||
export type DashboardPageShowStatus = 'view' | 'edit'
|
||||
export type DashboardSettingEditProps = {
|
||||
changeStatus: (status: DashboardPageShowStatus) => void
|
||||
refreshData: () => void
|
||||
data?: PartitionDataLogConfigFieldType
|
||||
}
|
||||
const DataLogSettingEdit = (props: DashboardSettingEditProps) => {
|
||||
const { changeStatus, refreshData, data } = props
|
||||
const [form] = Form.useForm();
|
||||
const { fetchData } = useFetch()
|
||||
|
||||
const onFinish = () => {
|
||||
form.validateFields().then((value) => {
|
||||
const formData = {
|
||||
config: {
|
||||
url: value.url,
|
||||
headers: value.headers.filter((item: PartitionDataLogHeaderListFieldType) => item.key).map((item: PartitionDataLogHeaderListFieldType) => ({key:item.key, value:item.value || ''}))
|
||||
}
|
||||
}
|
||||
fetchData<BasicResponse<{ info: PartitionDataLogConfigFieldType }>>('log/loki', { method: 'POST', body: JSON.stringify(formData), eoParams: {} }).then(response => {
|
||||
const { code, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
message.success(msg || $t('操作成功,即将刷新页面'))
|
||||
refreshData?.()
|
||||
} else {
|
||||
message.error(msg || $t('操作失败'))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => { form.setFieldsValue(data) }, [data])
|
||||
|
||||
useEffect(() => {
|
||||
return (form.setFieldsValue({}))
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<div className="overflow-auto h-full">
|
||||
<WithPermission access={''} >
|
||||
<Form
|
||||
form={form}
|
||||
className="mx-auto flex flex-col justify-between h-full"
|
||||
layout="vertical"
|
||||
onFinish={onFinish}
|
||||
autoComplete="off"
|
||||
>
|
||||
<Form.Item<PartitionDataLogConfigFieldType>
|
||||
label={$t("请求前缀")}
|
||||
name="url"
|
||||
rules={[{ required: true }]}
|
||||
>
|
||||
<Input className="w-INPUT_NORMAL" placeholder={$t(PLACEHOLDER.input)} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<PartitionDataLogConfigFieldType>
|
||||
label={$t("HTTP 头部")}
|
||||
name="headers"
|
||||
>
|
||||
<EditableTable<PartitionDataLogConfigFieldType & { _id: string }>
|
||||
configFields={PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS}
|
||||
/>
|
||||
</Form.Item>
|
||||
<div className="flex gap-btnbase">
|
||||
<WithPermission access='system.devops.data_source.edit'>
|
||||
<Button type="primary" htmlType="submit">
|
||||
{$t('保存')}
|
||||
</Button>
|
||||
</WithPermission>
|
||||
<Button type="default" onClick={() => changeStatus('view')}>
|
||||
{$t('取消')}
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</WithPermission>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default DataLogSettingEdit;
|
||||
@@ -57,7 +57,7 @@ const CertConfigModal = forwardRef<PartitionCertConfigHandle,PartitionCertConfig
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (<WithPermission access=''>
|
||||
return (<WithPermission access={type === 'edit' ? 'system.devops.ssl_certificate.edit':'system.devops.ssl_certificate.add'}>
|
||||
<Form
|
||||
layout='vertical'
|
||||
labelAlign='left'
|
||||
@@ -187,7 +187,7 @@ const PartitionInsideCert:FC = ()=>{
|
||||
switch (type){
|
||||
case 'add':
|
||||
title=$t('添加证书')
|
||||
content= <WithPermission access='system.devops.ssl_certificate.add'><CertConfigModal ref={addRef} type="add"/></WithPermission>
|
||||
content= <CertConfigModal ref={addRef} type="add"/>
|
||||
break;
|
||||
case 'edit':{
|
||||
title=$t('修改证书')
|
||||
@@ -195,7 +195,7 @@ const PartitionInsideCert:FC = ()=>{
|
||||
const {code,data,msg} = await fetchData<BasicResponse<{cert:{key:string, pem:string}}>>('certificate',{method:'GET',eoParams:{id:entity!.id}})
|
||||
message.destroy()
|
||||
if(code === STATUS_CODE.SUCCESS){
|
||||
content= <WithPermission access={'system.devops.ssl_certificate.edit'}><CertConfigModal ref={editRef} type="edit" entity={{...data.cert,id:entity!.id}}/></WithPermission>
|
||||
content= <CertConfigModal ref={editRef} type="edit" entity={{...data.cert,id:entity!.id}}/>
|
||||
}else{
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
return
|
||||
|
||||
@@ -1,175 +1,93 @@
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { useBreadcrumb } from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import { App, Button, Card, Col, Row, Spin, Tag } from "antd";
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const.tsx";
|
||||
import { useFetch } from "@common/hooks/http.ts";
|
||||
import { FC, useEffect, useState} from "react";
|
||||
import {useBreadcrumb} from "@common/contexts/BreadcrumbContext.tsx";
|
||||
import {App, Button, Card, Col, Row, Spin, Tag} from "antd";
|
||||
import {BasicResponse, RESPONSE_TIPS, STATUS_CODE} from "@common/const/const.tsx";
|
||||
import {useFetch} from "@common/hooks/http.ts";
|
||||
import WithPermission from "@common/components/aoplatform/WithPermission.tsx";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import InsidePage from "@common/components/aoplatform/InsidePage.tsx";
|
||||
import { $t } from "@common/locales/index.ts";
|
||||
import DashboardSettingEdit, { DashboardPageShowStatus } from "./DashboardSettingEdit.tsx";
|
||||
import { PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS, PartitionDashboardConfigFieldType, PartitionDataLogConfigFieldType } from "@core/const/partitions/types.ts";
|
||||
import PageList from "@common/components/aoplatform/PageList.tsx";
|
||||
import DataLogSettingEdit from "./DataLogSettingEdit.tsx";
|
||||
import { PartitionDashboardConfigFieldType } from "@core/const/partitions/types.ts";
|
||||
|
||||
const PartitionInsideDashboardSetting: FC = () => {
|
||||
const { setBreadcrumb } = useBreadcrumb()
|
||||
const { message } = App.useApp()
|
||||
const { fetchData } = useFetch()
|
||||
const [data, setData] = useState<PartitionDashboardConfigFieldType>()
|
||||
const [dataLogData, setDataLogData] = useState<PartitionDataLogConfigFieldType>()
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [dataLogLoading, setDataLogLoading] = useState<boolean>(false)
|
||||
const [showGraphStatus, setShowGraphStatus] = useState<DashboardPageShowStatus>('view')
|
||||
const [showDataLogStatus, setShowDataLogStatus] = useState<DashboardPageShowStatus>('view')
|
||||
const PartitionInsideDashboardSetting:FC = ()=> {
|
||||
const {setBreadcrumb} = useBreadcrumb()
|
||||
const {message} = App.useApp()
|
||||
const {fetchData} = useFetch()
|
||||
const [data, setData] = useState<PartitionDashboardConfigFieldType>()
|
||||
const [loading, setLoading] = useState<boolean>(false)
|
||||
const [showStatus, setShowStatus] = useState<DashboardPageShowStatus>('view')
|
||||
|
||||
const getDashboardSettingInfo = () => {
|
||||
setLoading(true)
|
||||
return fetchData<BasicResponse<{ nodes: PartitionDashboardConfigFieldType[] }>>('monitor/config', { method: 'GET', eoTransformKeys: [] }).then(response => {
|
||||
const { code, data, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
data?.info?.driver && setData(data.info)
|
||||
setShowGraphStatus('view')
|
||||
} else {
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
}
|
||||
}).catch(() => {
|
||||
return { data: [], success: false }
|
||||
}).finally(() => {
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
const getDataLogSettingInfo = () => {
|
||||
setDataLogLoading(true)
|
||||
return fetchData<BasicResponse<{ nodes: PartitionDataLogConfigFieldType[] }>>('log/loki', { method: 'GET', eoTransformKeys: [] }).then(response => {
|
||||
const { code, data, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
data?.info && setDataLogData({
|
||||
url: data.info?.config?.url || '',
|
||||
headers: data.info?.config?.headers || []
|
||||
const getDashboardSettingInfo = () => {
|
||||
setLoading(true)
|
||||
return fetchData<BasicResponse<{ nodes:PartitionDashboardConfigFieldType[] }>>('monitor/config', {method: 'GET',eoTransformKeys:[]}).then(response => {
|
||||
const {code, data, msg} = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
data?.info?.driver && setData(data.info)
|
||||
setShowStatus('view')
|
||||
} else {
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
}
|
||||
}).catch(() => {
|
||||
return {data: [], success: false}
|
||||
}).finally(()=>{
|
||||
setLoading(false)
|
||||
})
|
||||
setShowDataLogStatus('view')
|
||||
} else {
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
}
|
||||
}).catch(() => {
|
||||
return { data: [], success: false }
|
||||
}).finally(() => {
|
||||
setDataLogLoading(false)
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumb([
|
||||
{ title: $t('数据源') }
|
||||
])
|
||||
getDashboardSettingInfo()
|
||||
getDataLogSettingInfo()
|
||||
}, []);
|
||||
|
||||
const setDashboardSettingBtn = () => {
|
||||
return (<>
|
||||
{showGraphStatus === 'view' && <WithPermission access="system.devops.data_source.edit" key="changeClusterConfig">
|
||||
<Button type="primary" onClick={() => setShowGraphStatus('edit')}>{$t('修改配置')}</Button>
|
||||
</WithPermission>}</>
|
||||
)
|
||||
}
|
||||
const setDataLogSettingBtn = () => {
|
||||
return (<>
|
||||
{showDataLogStatus === 'view' && <WithPermission access="system.devops.data_source.edit" key="changeClusterConfig">
|
||||
<Button type="primary" onClick={() => setShowDataLogStatus('edit')}>{$t('修改配置')}</Button>
|
||||
</WithPermission>}</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<InsidePage
|
||||
pageTitle={$t('数据源')}
|
||||
description={$t("设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。")}
|
||||
showBorder={false}
|
||||
scrollPage={true}
|
||||
>
|
||||
<div className="flex flex-col overflow-auto pb-PAGE_INSIDE_B pr-PAGE_INSIDE_X">
|
||||
<Spin wrapperClassName="flex-1" indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={loading}>
|
||||
<div className="h-full overflow-auto">
|
||||
<Card
|
||||
classNames={{
|
||||
body: `overflow-auto ${(!data || !data?.driver) && showGraphStatus === 'view' ? 'hidden' : ''}`,
|
||||
}}
|
||||
className="overflow-hidden w-full max-h-full flex flex-col justify-between"
|
||||
title={<div><span className="text-MAIN_TEXT my-btnybase mr-btnbase" > {$t('统计图表')}</span>
|
||||
{!loading && !data?.driver && <Tag color='#f50'>{$t('未配置')}
|
||||
</Tag>}</div>}
|
||||
|
||||
extra={setDashboardSettingBtn()}>
|
||||
{showGraphStatus === 'view' && data && data.driver && DashboardConfigPreview(data)}
|
||||
{showGraphStatus !== 'view' && <DashboardSettingEdit data={data} changeStatus={setShowGraphStatus} refreshData={getDashboardSettingInfo} />}
|
||||
</Card>
|
||||
</div>
|
||||
</Spin>
|
||||
<Spin wrapperClassName="flex-1" indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} spinning={dataLogLoading}>
|
||||
<div className="h-full overflow-auto">
|
||||
<Card
|
||||
classNames={{
|
||||
body: `overflow-auto ${(!dataLogData) && showDataLogStatus === 'view' ? 'hidden' : ''}`,
|
||||
}}
|
||||
className="overflow-hidden mt-[30px] w-full max-h-full flex flex-col justify-between"
|
||||
title={<div><span className="text-MAIN_TEXT my-btnybase mr-btnbase" > {$t('数据日志')}</span>
|
||||
{!dataLogLoading && !dataLogData && <Tag color='#f50'>{$t('未配置')}
|
||||
</Tag>}</div>}
|
||||
|
||||
extra={setDataLogSettingBtn()}>
|
||||
{showDataLogStatus === 'view' && dataLogData && DataLogConfigPreview(dataLogData)}
|
||||
{showDataLogStatus !== 'view' && <DataLogSettingEdit data={dataLogData} changeStatus={setShowDataLogStatus} refreshData={getDataLogSettingInfo} />}
|
||||
</Card>
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</InsidePage>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function DashboardConfigPreview(x: PartitionDashboardConfigFieldType) {
|
||||
return <div className="flex flex-col gap-[4px] ">
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('数据源')}:</Col><Col>{x?.driver}</Col></Row>
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('地址(IP:端口)')}:</Col><Col>{x?.config?.addr}</Col></Row>
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('组织(Organization)')}:</Col><Col>{x?.config?.org}</Col></Row>
|
||||
</div>
|
||||
}
|
||||
export function DataLogConfigPreview(x: PartitionDataLogConfigFieldType) {
|
||||
const columns = PARTITION_DATA_LOG_CONFIG_TABLE_COLUMNS.map(x => {
|
||||
return {
|
||||
...x,
|
||||
title: (<span title={$t(x.title as string)}>{$t(x.title as string)}</span>)
|
||||
}
|
||||
})
|
||||
const getTableList = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve({
|
||||
data: x?.headers || [],
|
||||
success: true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
return <div className="flex flex-col gap-[4px] ">
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('请求前缀')}:</Col><Col>{x?.url}</Col></Row>
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('HTTP 头部')}:</Col><Col className="w-full">
|
||||
<div className="w-full h-full p-[20px]">
|
||||
<PageList
|
||||
id="global_role"
|
||||
tableClass="role_table mb-btnrbase"
|
||||
primaryKey="'key'"
|
||||
columns={[...columns]}
|
||||
request={() => getTableList()}
|
||||
showPagination={false}
|
||||
noScroll={true}
|
||||
/>
|
||||
</div>
|
||||
</Col></Row>
|
||||
</div>
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumb([
|
||||
{title: $t('数据源')}
|
||||
])
|
||||
getDashboardSettingInfo()
|
||||
}, []);
|
||||
|
||||
const setDashboardSettingBtn = ()=>{
|
||||
return (<>
|
||||
{showStatus === 'view' && <WithPermission access="system.devops.data_source.edit" key="changeClusterConfig">
|
||||
<Button type="primary" onClick={() => setShowStatus('edit')}>{$t('修改配置')}</Button>
|
||||
</WithPermission> }</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<InsidePage
|
||||
pageTitle={$t('数据源')}
|
||||
description={$t("设置监控报表的数据来源,设置完成之后即可获得详细的API调用统计图表。")}
|
||||
showBorder={false}
|
||||
scrollPage={true}
|
||||
>
|
||||
<div className="flex flex-col h-full overflow-auto pb-PAGE_INSIDE_B pr-PAGE_INSIDE_X">
|
||||
<Spin wrapperClassName=" h-full flex-1" indicator={<LoadingOutlined style={{ fontSize: 24 }} spin/>} spinning={loading}>
|
||||
<div className="h-full overflow-auto">
|
||||
<Card
|
||||
classNames={{
|
||||
body: `overflow-auto ${(!data || !data?.driver) && showStatus === 'view' ? 'hidden': ''}`,
|
||||
}}
|
||||
className="overflow-hidden w-full max-h-full flex flex-col justify-between"
|
||||
title={<div><span className="text-MAIN_TEXT my-btnybase mr-btnbase" > {$t('统计图表')}</span>
|
||||
{!loading && !data?.driver && <Tag color='#f50'>{ $t('未配置')}
|
||||
</Tag>}</div>}
|
||||
|
||||
extra={setDashboardSettingBtn()}>
|
||||
{showStatus === 'view'&& data && data.driver && DashboardConfigPreview(data) }
|
||||
{showStatus !== 'view' && <DashboardSettingEdit data={data} changeStatus={setShowStatus} refreshData={getDashboardSettingInfo} />}
|
||||
</Card>
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
</InsidePage>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function DashboardConfigPreview (x:PartitionDashboardConfigFieldType){
|
||||
return <div className="flex flex-col gap-[4px] ">
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('数据源')}:</Col><Col>{x?.driver}</Col></Row>
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('地址(IP:端口)')}:</Col><Col>{x?.config?.addr}</Col></Row>
|
||||
<Row className=""><Col className="font-bold text-right pr-[4px]">{$t('组织(Organization)')}:</Col><Col>{x?.config?.org}</Col></Row>
|
||||
</div>}
|
||||
|
||||
export default PartitionInsideDashboardSetting
|
||||
@@ -79,7 +79,7 @@ const DataMasking = (props: any) => {
|
||||
{
|
||||
title: '',
|
||||
key: 'option',
|
||||
btnNums: rowOperation.length,
|
||||
btnNums: rowOperation.length -1,
|
||||
fixed: 'right',
|
||||
valueType: 'option',
|
||||
render: (_: React.ReactNode, entity: any) => [
|
||||
@@ -233,6 +233,7 @@ const DataMasking = (props: any) => {
|
||||
* @param entity
|
||||
*/
|
||||
const openLogsModal = (entity: any) => {
|
||||
console.log('日志', entity);
|
||||
setStrategy(entity.id)
|
||||
setModalVisible(true)
|
||||
}
|
||||
@@ -378,11 +379,10 @@ const DataMasking = (props: any) => {
|
||||
<Modal
|
||||
title={$t('处理日志')}
|
||||
visible={modalVisible}
|
||||
destroyOnClose={true}
|
||||
onCancel={handleCloseModal}
|
||||
footer={null}
|
||||
wrapClassName="modal-without-footer"
|
||||
width={1100}
|
||||
width={1000}
|
||||
maskClosable={true}
|
||||
>
|
||||
<div className="pb-btnybase flex flex-nowrap flex-col h-full w-full items-center justify-between">
|
||||
|
||||
@@ -27,7 +27,7 @@ export const DATA_MASKING_TABLE_COLUMNS: PageProColumns<any>[] = [
|
||||
filters: true,
|
||||
onFilter: false ,
|
||||
ellipsis: true,
|
||||
width: 110,
|
||||
width: 140,
|
||||
valueEnum: new Map(
|
||||
Object.keys(StrategyStatusEnum).map(key=>
|
||||
[key,
|
||||
@@ -40,7 +40,6 @@ export const DATA_MASKING_TABLE_COLUMNS: PageProColumns<any>[] = [
|
||||
filters: true,
|
||||
onFilter: false ,
|
||||
ellipsis: true,
|
||||
width: 90,
|
||||
valueEnum: {
|
||||
false: { text: <span className="text-status_success">{$t('启用')}</span> },
|
||||
true: { text: <span className="text-status_fail">{$t('禁用')}</span> }
|
||||
@@ -54,8 +53,7 @@ export const DATA_MASKING_TABLE_COLUMNS: PageProColumns<any>[] = [
|
||||
{
|
||||
title: ('处理数'),
|
||||
dataIndex: 'processedTotal',
|
||||
ellipsis: true,
|
||||
width: 80,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: ('更新者'),
|
||||
@@ -85,10 +83,10 @@ export const DATA_MASKING_TABLE_LOG_COLUMNS: PageProColumns<any>[] = [
|
||||
width: 200
|
||||
},
|
||||
{
|
||||
title: ('消费者 IP'),
|
||||
title: ('消费者IP'),
|
||||
dataIndex: 'remote_ip',
|
||||
ellipsis: true,
|
||||
width: 100
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
title: ('消费者'),
|
||||
@@ -98,14 +96,14 @@ export const DATA_MASKING_TABLE_LOG_COLUMNS: PageProColumns<any>[] = [
|
||||
},
|
||||
{
|
||||
title: ('鉴权名称'),
|
||||
dataIndex: ['authorization', 'name'],
|
||||
dataIndex: 'authorization',
|
||||
ellipsis: true,
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: ('时间'),
|
||||
dataIndex: 'record_time',
|
||||
width: 110,
|
||||
width: 150,
|
||||
ellipsis: true
|
||||
},
|
||||
]
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { Codebox, codeBoxLanguagesType } from "@common/components/postcat/api/Codebox";
|
||||
import { Codebox } from "@common/components/postcat/api/Codebox";
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from "@common/const/const";
|
||||
import { RouterParams } from "@common/const/type";
|
||||
import { $t } from "@common/locales";
|
||||
import { message, Spin } from 'antd'
|
||||
import { App, Button, message, Switch, Modal, Spin } from 'antd'
|
||||
import { useFetch } from "@common/hooks/http";
|
||||
import { useEffect, useState } from "react";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
|
||||
import { useParams } from "react-router-dom";
|
||||
import { contentTypeToLanguageMap } from "@common/const/policy/consts";
|
||||
type LogItems = {
|
||||
id: string;
|
||||
origin: string;
|
||||
@@ -17,15 +18,7 @@ const DataMaskingCompare = () => {
|
||||
const { fetchData } = useFetch()
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [originValue, setOriginValue] = useState('')
|
||||
const [targetValue, setTargetValue] = useState('')
|
||||
const [language, setLanguage] = useState<codeBoxLanguagesType>('json')
|
||||
const getMonacoEditorLanguage = (contentType: string): codeBoxLanguagesType => {
|
||||
// 提取主类型,忽略参数(如 "; charset=utf-8")
|
||||
const mainType = contentType.split(";")[0].trim().toLowerCase();
|
||||
|
||||
// 根据映射表获取语言,默认返回 "plaintext"
|
||||
return contentTypeToLanguageMap[mainType] || "json";
|
||||
};
|
||||
const [targetValue, settTargetValue] = useState('')
|
||||
const getLogData = () => {
|
||||
setLoading(true)
|
||||
return fetchData<BasicResponse<{ log: LogItems }>>(`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking/log`,
|
||||
@@ -40,10 +33,8 @@ const DataMaskingCompare = () => {
|
||||
const { code, data, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
const { log } = data
|
||||
const docLanguage = getMonacoEditorLanguage(log.content_type)
|
||||
setLanguage(docLanguage)
|
||||
setOriginValue(docLanguage === 'json' ? JSON.stringify(JSON.parse(log.origin || ''), null, 2) : log.origin || '')
|
||||
setTargetValue(docLanguage === 'json' ? JSON.stringify(JSON.parse(log.target || ''), null, 2) : log.target || '')
|
||||
setOriginValue(log.origin || '')
|
||||
settTargetValue(log.target || '')
|
||||
setLoading(false)
|
||||
} else {
|
||||
message.error(msg || $t(RESPONSE_TIPS.error))
|
||||
@@ -51,6 +42,17 @@ const DataMaskingCompare = () => {
|
||||
}).catch(() => {
|
||||
return { data: [], success: false }
|
||||
}).finally(() => {
|
||||
const aa = `{
|
||||
"code": {
|
||||
"gg": "gg",
|
||||
"gg1": "gg",
|
||||
"gg2": "gg",
|
||||
"gg3": "gg",
|
||||
"gg4": "gg"
|
||||
}
|
||||
}`
|
||||
setOriginValue(JSON.stringify(JSON.parse(aa), null, 2))
|
||||
settTargetValue(JSON.stringify(JSON.parse(aa), null, 2))
|
||||
setLoading(false)
|
||||
})
|
||||
}
|
||||
@@ -62,26 +64,24 @@ const DataMaskingCompare = () => {
|
||||
<div className="flex h-full overflow-hidden">
|
||||
<div className="w-1/2 p-2 h-full">
|
||||
<div className="h-[30px] bg-gray-200 mb-2 flex items-center justify-center">
|
||||
{$t('脱敏前')}
|
||||
脱敏前
|
||||
</div>
|
||||
<div style={{ height: 'calc(100vh - 50px)' }}>
|
||||
<Codebox
|
||||
language={language}
|
||||
language='json'
|
||||
height="100%"
|
||||
width="100%"
|
||||
value={originValue}
|
||||
sx={{ whiteSpace: 'nowrap' }}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-1/2 p-2 h-full">
|
||||
<div className="h-[30px] bg-green-100 mb-2 flex items-center justify-center">
|
||||
{$t('脱敏后')}
|
||||
脱敏后
|
||||
</div>
|
||||
<div style={{ height: 'calc(100vh - 50px)' }}>
|
||||
<Codebox
|
||||
language={language}
|
||||
language='json'
|
||||
width="100%"
|
||||
height="100%"
|
||||
value={targetValue}
|
||||
|
||||
@@ -1,62 +1,46 @@
|
||||
import React, { useMemo, useRef, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { DataMaskLogItem } from "@common/const/policy/type";
|
||||
import PageList, { PageProColumns } from "@common/components/aoplatform/PageList";
|
||||
import { $t } from "@common/locales";
|
||||
import { Button, message } from 'antd'
|
||||
import { App, Button, message, DatePicker, Modal } from 'antd'
|
||||
|
||||
import { DATA_MASKING_TABLE_LOG_COLUMNS } from './DataMaskingColumn';
|
||||
import { DATA_MASKING_TABLE_LOG_COLUMNS, DATA_MASKING_TABLE_COLUMNS } from './DataMaskingColumn';
|
||||
import { useGlobalContext } from '@common/contexts/GlobalStateContext';
|
||||
import { ActionType } from '@ant-design/pro-components';
|
||||
import { BasicResponse, RESPONSE_TIPS, STATUS_CODE } from '@common/const/const';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { RouterParams } from '@common/const/type';
|
||||
import { useFetch } from '@common/hooks/http';
|
||||
import WithPermission from '@common/components/aoplatform/WithPermission';
|
||||
import TimeRangeSelector, { TimeRange } from '@common/components/aoplatform/TimeRangeSelector';
|
||||
import { SearchBody } from '@dashboard/const/type';
|
||||
import TableBtnWithPermission from '@common/components/aoplatform/TableBtnWithPermission';
|
||||
const { RangePicker } = DatePicker;
|
||||
const DataMaskingLogModal = (props: any) => {
|
||||
const { strategy } = props;
|
||||
const { state, accessData } = useGlobalContext()
|
||||
const { serviceId, teamId } = useParams<RouterParams>()
|
||||
const [datePickerValue, setDatePickerValue] = useState<any>();
|
||||
const currentSecond = Math.floor(Date.now() / 1000); // 当前秒级时间戳
|
||||
const [queryData, setQueryData] = useState<SearchBody>({
|
||||
start: currentSecond - 24 * 60 * 60,
|
||||
end: currentSecond
|
||||
})
|
||||
const [queryData, setQueryData] = useState<SearchBody>({})
|
||||
|
||||
/**
|
||||
* 请求数据
|
||||
*/
|
||||
const { fetchData } = useFetch()
|
||||
/**
|
||||
* 列表ref
|
||||
*/
|
||||
* 列表ref
|
||||
*/
|
||||
const pageListRef = useRef<ActionType>(null);
|
||||
/**
|
||||
* 搜索关键字
|
||||
*/
|
||||
const [searchWord, setSearchWord] = useState<string>('')
|
||||
/**
|
||||
* 重置时间范围
|
||||
*/
|
||||
let resetTimeRange = () => {}
|
||||
/**
|
||||
* 时间按钮
|
||||
*/
|
||||
const [timeButton, setTimeButton] = useState<'' | 'hour' | 'day' | 'threeDays' | 'sevenDays'>('day');
|
||||
/**
|
||||
* 绑定时间范围组件
|
||||
* @param instance
|
||||
*/
|
||||
const bindRef = (instance: any) => {
|
||||
resetTimeRange = instance.reset
|
||||
};
|
||||
/**
|
||||
* 操作列
|
||||
*/
|
||||
const operation: PageProColumns<any>[] = [
|
||||
{
|
||||
title: '',
|
||||
title: '操作',
|
||||
key: 'option',
|
||||
btnNums: 1,
|
||||
fixed: 'right',
|
||||
@@ -70,7 +54,7 @@ const DataMaskingLogModal = (props: any) => {
|
||||
url += `/${teamId}`
|
||||
}
|
||||
return [
|
||||
<TableBtnWithPermission access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.view`} key="view" btnType="view" onClick={() => { window.open(url, '_blank') }} btnTitle="查看" />
|
||||
<TableBtnWithPermission access={`${serviceId === undefined ? 'system.devops' : 'team.service'}.policy.view`} key="view" btnType="view" onClick={() => { window.open(url,'_blank') }} btnTitle="查看" />
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -84,11 +68,11 @@ const DataMaskingLogModal = (props: any) => {
|
||||
const columns = useMemo(() => {
|
||||
const res = DATA_MASKING_TABLE_LOG_COLUMNS.map(x => {
|
||||
if (x.dataIndex === 'url') {
|
||||
x.render = (text: any, record: any) => <><div className='w-full'><span className='text-green-500'>{record.method}</span> <span className='w-[calc(100%-25px)] text-ellipsis overflow-hidden whitespace-nowrap inline-block align-top'>{text}</span></div></>
|
||||
x.render = (text: any, record: any) => <><span className='text-green-500'>{record.method}</span> <span>{text}</span></>
|
||||
}
|
||||
return {
|
||||
...x,
|
||||
title: (<span title={$t(x.title as string)}>{$t(x.title as string)}</span>)
|
||||
title: typeof x.title === 'string' ? $t(x.title as string) : x.title
|
||||
}
|
||||
})
|
||||
return res
|
||||
@@ -104,7 +88,7 @@ const DataMaskingLogModal = (props: any) => {
|
||||
current: number;
|
||||
}) => {
|
||||
return fetchData<BasicResponse<{ logs: DataMaskLogItem[], total: number }>>(
|
||||
`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking/logs`,
|
||||
`strategy/${serviceId === undefined ? 'global' : 'service'}/data-masking/list`,
|
||||
{
|
||||
method: 'GET',
|
||||
eoParams: {
|
||||
@@ -122,9 +106,204 @@ const DataMaskingLogModal = (props: any) => {
|
||||
).then(response => {
|
||||
const { code, data, msg } = response
|
||||
if (code === STATUS_CODE.SUCCESS) {
|
||||
const mockData: any = [
|
||||
{
|
||||
id: '12334',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff1',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff2',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff3',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff4',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff5',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff6',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff7',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff8',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff9',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff11',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:12',
|
||||
},
|
||||
{
|
||||
id: 'fff22',
|
||||
service: {
|
||||
id: 'xxx',
|
||||
name: 'xxx'
|
||||
},
|
||||
url: 'url',
|
||||
remote_ip: '9234923',
|
||||
consumer: {
|
||||
id: 'yyy',
|
||||
name: 'yyy'
|
||||
},
|
||||
method: 'GET',
|
||||
authorization: 'authorization',
|
||||
record_time: '2021-09-09 12:12:11',
|
||||
}
|
||||
|
||||
]
|
||||
// 保存数据
|
||||
return {
|
||||
data: data.logs || [],
|
||||
data: mockData,
|
||||
total: data.total,
|
||||
success: true
|
||||
}
|
||||
@@ -141,13 +320,24 @@ const DataMaskingLogModal = (props: any) => {
|
||||
const handleTimeRangeChange = (timeRange: TimeRange) => {
|
||||
setQueryData(pre => ({ ...pre, ...timeRange } as SearchBody))
|
||||
manualReloadTable()
|
||||
|
||||
|
||||
};
|
||||
const handleDatePickerChange = (dates: any) => {
|
||||
if (dates && Array.isArray(dates) && dates.length === 2) {
|
||||
const [startDate, endDate] = dates;
|
||||
const start = startDate!.startOf('day').unix(); // 开始日期的00:00:00
|
||||
const end = endDate!.endOf('day').unix(); // 结束日期的23:59:59
|
||||
handleTimeRangeChange({ start, end });
|
||||
} else {
|
||||
handleTimeRangeChange({ start: null, end: null})
|
||||
}
|
||||
}
|
||||
|
||||
const resetQuery = () => {
|
||||
resetTimeRange()
|
||||
};
|
||||
setDatePickerValue(null)
|
||||
handleTimeRangeChange({ start: null, end: null})
|
||||
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<div className="w-full h-full p-[20px]">
|
||||
@@ -158,17 +348,11 @@ const DataMaskingLogModal = (props: any) => {
|
||||
columns={[...columns, ...operation]}
|
||||
afterNewBtn={
|
||||
[<div className="flex items-center flex-wrap p-[10px] px-btnbase content-before bg-MAIN_BG ">
|
||||
<TimeRangeSelector
|
||||
labelSize="small"
|
||||
bindRef={bindRef}
|
||||
hideBtns={['hour']}
|
||||
defaultTimeButton="day"
|
||||
initialTimeButton={timeButton}
|
||||
onTimeButtonChange={setTimeButton}
|
||||
initialDatePickerValue={datePickerValue}
|
||||
onTimeRangeChange={handleTimeRangeChange} />
|
||||
<div className="flex flex-nowrap items-center pt-btnybase">
|
||||
<Button onClick={resetQuery}>{$t('重置')}</Button>
|
||||
<RangePicker
|
||||
onChange={handleDatePickerChange}
|
||||
value={datePickerValue} />
|
||||
<div className="flex [&>.reset-btn]:!h-auto flex-nowrap items-center ml-[10px]">
|
||||
<Button className="reset-btn" onClick={resetQuery}>{$t('重置')}</Button>
|
||||
</div>
|
||||
</div>]
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ export const SystemSubscriberConfig = forwardRef<SystemSubscriberConfigHandle,Sy
|
||||
getSystemList()
|
||||
}, [serviceId]);
|
||||
|
||||
return (<WithPermission access="">
|
||||
return (<WithPermission access="team.service.subscription.add">
|
||||
<Form
|
||||
layout='vertical'
|
||||
labelAlign='left'
|
||||
|
||||
@@ -69,10 +69,8 @@ func (a *ApplicationClient) toApinto(app *gateway.ApplicationRelease) interface{
|
||||
Expire: info.Expire,
|
||||
Pattern: driver.ToPattern(info.Config),
|
||||
HideCredential: info.HideCredential,
|
||||
Labels: info.Label,
|
||||
},
|
||||
},
|
||||
Labels: info.Label,
|
||||
})
|
||||
}
|
||||
labels := make(map[string]string)
|
||||
|
||||
@@ -3,7 +3,7 @@ package apinto
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
admin_client "github.com/eolinker/eosc/process-admin/client"
|
||||
)
|
||||
@@ -14,10 +14,6 @@ type ClientDriver struct {
|
||||
client admin_client.Client
|
||||
}
|
||||
|
||||
func (c *ClientDriver) Strategy() gateway.IStrategyClient {
|
||||
return NewStrategyClient(c.client)
|
||||
}
|
||||
|
||||
func (c *ClientDriver) Close(ctx context.Context) error {
|
||||
if c.client != nil {
|
||||
return c.client.Close()
|
||||
@@ -78,7 +74,7 @@ func NewClientDriver(cfg *gateway.ClientConfig) (*ClientDriver, error) {
|
||||
}
|
||||
|
||||
func genWorkerID(id string, profession string) string {
|
||||
|
||||
|
||||
suffix := "@" + profession
|
||||
if strings.HasSuffix(id, suffix) {
|
||||
return id
|
||||
|
||||
@@ -20,6 +20,7 @@ func NewDynamicClient(client admin_client.Client, resource string) (*DynamicClie
|
||||
cfg, has := gateway.GetDynamicResourceDriver(resource)
|
||||
if !has {
|
||||
return nil, errors.New("resource not found")
|
||||
|
||||
}
|
||||
|
||||
return &DynamicClient{client: client, profession: cfg.Profession, driver: cfg.Driver}, nil
|
||||
|
||||
@@ -7,17 +7,15 @@ type Application struct {
|
||||
}
|
||||
|
||||
type Authorization struct {
|
||||
Type string `json:"type"`
|
||||
Position string `json:"position"`
|
||||
TokenName string `json:"token_name"`
|
||||
Config interface{} `json:"config"`
|
||||
Users []*AuthUser `json:"users"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
Type string `json:"type"`
|
||||
Position string `json:"position"`
|
||||
TokenName string `json:"token_name"`
|
||||
Config interface{} `json:"config"`
|
||||
Users []*AuthUser `json:"users"`
|
||||
}
|
||||
|
||||
type AuthUser struct {
|
||||
Expire int64 `json:"expire"`
|
||||
Pattern interface{} `json:"pattern"`
|
||||
HideCredential bool `json:"hide_credential"`
|
||||
Labels map[string]string `json:"labels"`
|
||||
Expire int64 `json:"expire"`
|
||||
Pattern interface{} `json:"pattern"`
|
||||
HideCredential bool `json:"hide_credential"`
|
||||
}
|
||||
|
||||
@@ -63,13 +63,6 @@
|
||||
rely: eolinker.com:apinto:plugin_app
|
||||
config:
|
||||
cache: redis@output
|
||||
|
||||
- id: eolinker.com:apinto:strategy-plugin-data_mask
|
||||
name: strategy_data_mask
|
||||
status: global
|
||||
rely: eolinker.com:apinto:plugin_app
|
||||
config:
|
||||
cache: redis@output
|
||||
-
|
||||
id: eolinker.com:apinto:ai_prompt
|
||||
name: ai_prompt
|
||||
|
||||
+16
-11
@@ -59,11 +59,27 @@ func (p *ProjectClient) online(ctx context.Context, project *gateway.ProjectRele
|
||||
"project": project.Id,
|
||||
}
|
||||
if project.Upstream != nil {
|
||||
//upstreams, err := matchLabels[entity.Service](ctx, p.client, gateway.ProfessionService, matches)
|
||||
//if err != nil {
|
||||
// if !errors.Is(err, proto.Nil) {
|
||||
// return err
|
||||
// }
|
||||
//}
|
||||
//upstreamMap := utils.SliceToMap(upstreams, func(t *entity.Service) string {
|
||||
// return t.ID
|
||||
//})
|
||||
|
||||
upstreamId := genWorkerID(project.Upstream.ID, gateway.ProfessionService)
|
||||
err := p.client.Set(ctx, upstreamId, entity.ToService(project.Upstream, project.Version, matches))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//for id := range upstreamMap {
|
||||
// err = p.client.Del(ctx, id)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
routers, err := matchLabels[entity.Router](ctx, p.client, gateway.ProfessionRouter, matches)
|
||||
@@ -90,17 +106,6 @@ func (p *ProjectClient) online(ctx context.Context, project *gateway.ProjectRele
|
||||
}
|
||||
delete(routerMap, id)
|
||||
}
|
||||
// 发布策略
|
||||
for _, s := range project.Strategies {
|
||||
if s.Config.IsDelete {
|
||||
p.client.Del(ctx, genWorkerID(s.Config.Name, gateway.ProfessionStrategy))
|
||||
continue
|
||||
}
|
||||
err := p.client.Set(ctx, genWorkerID(s.Config.Name, gateway.ProfessionStrategy), s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// 删除多余配置
|
||||
for _, v := range routerMap {
|
||||
err := driver.ApiDelete(ctx, p.client, v)
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package apinto
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/eolinker/eosc"
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
admin_client "github.com/eolinker/eosc/process-admin/client"
|
||||
)
|
||||
|
||||
var _ gateway.IStrategyClient = &StrategyClient{}
|
||||
|
||||
type StrategyClient struct {
|
||||
client admin_client.Client
|
||||
}
|
||||
|
||||
func (s *StrategyClient) Online(ctx context.Context, resources ...*eosc.Base[gateway.StrategyRelease]) error {
|
||||
s.client.Begin(ctx)
|
||||
for _, r := range resources {
|
||||
if r.Config.IsDelete {
|
||||
s.client.Del(ctx, genWorkerID(r.Config.Name, gateway.ProfessionStrategy))
|
||||
continue
|
||||
}
|
||||
err := s.client.Set(ctx, genWorkerID(r.Config.Name, gateway.ProfessionStrategy), r)
|
||||
if err != nil {
|
||||
s.client.Rollback(ctx)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return s.client.Commit(ctx)
|
||||
}
|
||||
|
||||
func (s *StrategyClient) Offline(ctx context.Context, resources ...*eosc.Base[gateway.StrategyRelease]) error {
|
||||
s.client.Begin(ctx)
|
||||
for _, r := range resources {
|
||||
err := s.client.Del(ctx, genWorkerID(r.Config.Name, gateway.ProfessionStrategy))
|
||||
if err != nil {
|
||||
s.client.Rollback(ctx)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return s.client.Commit(ctx)
|
||||
}
|
||||
|
||||
func NewStrategyClient(client admin_client.Client) *StrategyClient {
|
||||
return &StrategyClient{client: client}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ type IClientDriver interface {
|
||||
Application() IApplicationClient
|
||||
Service() IServiceClient
|
||||
Subscribe() ISubscribeClient
|
||||
Strategy() IStrategyClient
|
||||
Dynamic(resource string) (IDynamicClient, error)
|
||||
PluginSetting() IPluginSetting
|
||||
Commit(ctx context.Context) error
|
||||
|
||||
+36
-5
@@ -5,7 +5,6 @@ const (
|
||||
ProfessionCertificate = "certificate"
|
||||
ProfessionRouter = "router"
|
||||
ProfessionApplication = "app"
|
||||
ProfessionStrategy = "strategy"
|
||||
ProfessionService = "service"
|
||||
ProfessionAIProvider = "ai-provider"
|
||||
)
|
||||
@@ -57,10 +56,42 @@ var dynamicResourceMap = map[string]Worker{
|
||||
Profession: ProfessionCertificate,
|
||||
Driver: "server",
|
||||
},
|
||||
"loki": {
|
||||
Profession: ProfessionOutput,
|
||||
Driver: "loki",
|
||||
},
|
||||
//"openai": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "openai",
|
||||
//},
|
||||
//"google": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "google",
|
||||
//},
|
||||
//"anthropic": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "anthropic",
|
||||
//},
|
||||
//"moonshot": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "moonshot",
|
||||
//},
|
||||
//"tongyi": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "tongyi",
|
||||
//},
|
||||
//"zhipuai": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "zhipuai",
|
||||
//},
|
||||
//"fireworks": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "fireworks",
|
||||
//},
|
||||
//"novita": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "novita",
|
||||
//},
|
||||
//"mistralai": {
|
||||
// Profession: ProfessionAIProvider,
|
||||
// Driver: "mistralai",
|
||||
//},
|
||||
}
|
||||
|
||||
type Worker struct {
|
||||
|
||||
+4
-18
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/eolinker/eosc"
|
||||
|
||||
"github.com/APIParkLab/APIPark/model/plugin_model"
|
||||
)
|
||||
|
||||
@@ -17,8 +15,6 @@ type IServiceClient IResourceClient[ServiceRelease]
|
||||
|
||||
type ISubscribeClient IResourceClient[SubscribeRelease]
|
||||
|
||||
type IStrategyClient IResourceClient[eosc.Base[StrategyRelease]]
|
||||
|
||||
type IResourceClient[T any] interface {
|
||||
Online(ctx context.Context, resources ...*T) error
|
||||
Offline(ctx context.Context, resources ...*T) error
|
||||
@@ -31,11 +27,10 @@ type IDynamicClient interface {
|
||||
}
|
||||
|
||||
type ProjectRelease struct {
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Apis []*ApiRelease `json:"apis"`
|
||||
Upstream *UpstreamRelease `json:"upstreams"`
|
||||
Strategies []*eosc.Base[StrategyRelease] `json:"strategies"`
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Apis []*ApiRelease `json:"apis"`
|
||||
Upstream *UpstreamRelease `json:"upstreams"`
|
||||
}
|
||||
|
||||
type ApiRelease struct {
|
||||
@@ -78,15 +73,6 @@ type UpstreamRelease struct {
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
type StrategyRelease struct {
|
||||
Name string `json:"name"`
|
||||
Desc string `json:"description"`
|
||||
Driver string `json:"driver"`
|
||||
Priority int `json:"priority"`
|
||||
Filters map[string][]string `json:"filters"`
|
||||
IsDelete bool `json:"-"`
|
||||
}
|
||||
|
||||
type MatchRule struct {
|
||||
Position string
|
||||
MatchType string
|
||||
|
||||
@@ -6,7 +6,7 @@ go 1.21
|
||||
|
||||
require (
|
||||
github.com/eolinker/ap-account v1.0.15
|
||||
github.com/eolinker/eosc v0.18.3
|
||||
github.com/eolinker/eosc v0.17.3
|
||||
github.com/eolinker/go-common v1.1.1
|
||||
github.com/gabriel-vasile/mimetype v1.4.4
|
||||
github.com/getkin/kin-openapi v0.127.0
|
||||
@@ -75,10 +75,6 @@ require (
|
||||
gorm.io/driver/mysql v1.5.2 // indirect
|
||||
)
|
||||
|
||||
//replace (
|
||||
// github.com/eolinker/eosc => ../../eolinker/eosc
|
||||
//)
|
||||
|
||||
//replace github.com/eolinker/ap-account => ../aoaccount
|
||||
//
|
||||
//replace github.com/eolinker/go-common => ../go-common
|
||||
|
||||
@@ -30,8 +30,8 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eolinker/ap-account v1.0.15 h1:n6DJeL6RHZ8eLlZUcY2U3H4d/GPaA5oelAx3R0E6yL8=
|
||||
github.com/eolinker/ap-account v1.0.15/go.mod h1:zm/Ivs6waJ/M/nEszhpPmM6g50y/MKO+5eABFAdeD0g=
|
||||
github.com/eolinker/eosc v0.18.3 h1:3IK5HkAPnJRfLbQ0FR7kWsZr6Y/OiqqGazvN1q2BL5A=
|
||||
github.com/eolinker/eosc v0.18.3/go.mod h1:O9PQQXFCpB6fjHf+oFt/LN6EOAv779ItbMixMKCfTfk=
|
||||
github.com/eolinker/eosc v0.17.3 h1:sr2yT+v/AsqEdciRaaZZj0zL9pTufR5RvDW6+65hraQ=
|
||||
github.com/eolinker/eosc v0.17.3/go.mod h1:xgq816hpanlMXFtZw7Ztdctb1eEk9UPHchY4NfFO6Cw=
|
||||
github.com/eolinker/go-common v1.1.1 h1:3WqqecGqcHDgpa8Ljp156c1uWeZKP1CKScdU+6sOfcc=
|
||||
github.com/eolinker/go-common v1.1.1/go.mod h1:Kb/jENMN1mApnodvRgV4YwO9FJby1Jkt2EUjrBjvSX4=
|
||||
github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package log_driver
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/eolinker/eosc"
|
||||
)
|
||||
|
||||
type ILogDriver interface {
|
||||
LogInfo(clusterId string, id string) (*LogInfo, error)
|
||||
LogCount(clusterId string, conditions map[string]string, spendHour int64, group string) (map[string]int64, error)
|
||||
Logs(clusterId string, conditions map[string]string, start time.Time, end time.Time, limit int64, offset int64) ([]*Log, int64, error)
|
||||
}
|
||||
|
||||
var (
|
||||
driverManager = NewDriverManager()
|
||||
)
|
||||
|
||||
type DriverManager struct {
|
||||
drivers eosc.Untyped[string, ILogDriver]
|
||||
}
|
||||
|
||||
func NewDriverManager() *DriverManager {
|
||||
return &DriverManager{drivers: eosc.BuildUntyped[string, ILogDriver]()}
|
||||
}
|
||||
|
||||
func (m *DriverManager) Set(name string, driver ILogDriver) {
|
||||
m.drivers.Set(name, driver)
|
||||
}
|
||||
|
||||
func (m *DriverManager) Get(name string) (ILogDriver, bool) {
|
||||
return m.drivers.Get(name)
|
||||
}
|
||||
|
||||
func SetDriver(name string, driver ILogDriver) {
|
||||
driverManager.Set(name, driver)
|
||||
}
|
||||
|
||||
func GetDriver(name string) (ILogDriver, bool) {
|
||||
return driverManager.Get(name)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package log_driver
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Log struct {
|
||||
ID string
|
||||
Service string
|
||||
Method string
|
||||
Url string
|
||||
RemoteIP string
|
||||
Consumer string
|
||||
Authorization string
|
||||
RecordTime time.Time
|
||||
}
|
||||
|
||||
type LogInfo struct {
|
||||
ID string
|
||||
ContentType string
|
||||
RequestBody string
|
||||
ProxyBody string
|
||||
ProxyResponseBody string
|
||||
ResponseBody string
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package log_driver
|
||||
|
||||
import "github.com/eolinker/eosc"
|
||||
|
||||
var (
|
||||
defaultFactoryManager = NewFactoryManager()
|
||||
)
|
||||
|
||||
type IFactory interface {
|
||||
Create(config string) (ILogDriver, map[string]interface{}, error)
|
||||
}
|
||||
|
||||
type factoryManager struct {
|
||||
factories eosc.Untyped[string, IFactory]
|
||||
}
|
||||
|
||||
func NewFactoryManager() *factoryManager {
|
||||
return &factoryManager{factories: eosc.BuildUntyped[string, IFactory]()}
|
||||
}
|
||||
|
||||
func (m *factoryManager) Set(name string, factory IFactory) {
|
||||
m.factories.Set(name, factory)
|
||||
}
|
||||
|
||||
func (m *factoryManager) Get(name string) (IFactory, bool) {
|
||||
return m.factories.Get(name)
|
||||
}
|
||||
|
||||
func RegisterFactory(name string, factory IFactory) {
|
||||
defaultFactoryManager.Set(name, factory)
|
||||
}
|
||||
|
||||
func GetFactory(name string) (IFactory, bool) {
|
||||
return defaultFactoryManager.Get(name)
|
||||
}
|
||||
|
||||
func Drivers() []string {
|
||||
return defaultFactoryManager.factories.Keys()
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package loki
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type DriverConfig struct {
|
||||
URL string `json:"url"`
|
||||
Header []*Param `json:"headers"`
|
||||
}
|
||||
|
||||
type Param struct {
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func (d *DriverConfig) Check() error {
|
||||
if d.URL == "" {
|
||||
return fmt.Errorf("url is empty")
|
||||
}
|
||||
u, err := url.Parse(d.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if u.Host == "" {
|
||||
return fmt.Errorf("host is empty")
|
||||
}
|
||||
if u.Scheme == "" {
|
||||
u.Scheme = "http"
|
||||
}
|
||||
d.URL = fmt.Sprintf("%s://%s", u.Scheme, u.Host)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Response[T any] struct {
|
||||
Data *Data[T] `json:"data"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
type Data[T any] struct {
|
||||
ResultType string `json:"resultType"`
|
||||
Result []*T `json:"result"`
|
||||
}
|
||||
|
||||
type LogCount struct {
|
||||
Metric map[string]string `json:"metric"`
|
||||
Value []interface{} `json:"value"`
|
||||
}
|
||||
|
||||
type LogInfo struct {
|
||||
Stream *LogDetail `json:"stream"`
|
||||
}
|
||||
|
||||
type LogDetail struct {
|
||||
Api string `json:"api"`
|
||||
Application string `json:"application"`
|
||||
Strategy string `json:"strategy"`
|
||||
ContentType string `json:"content_type"`
|
||||
Cluster string `json:"cluster"`
|
||||
Msec string `json:"msec"`
|
||||
Node string `json:"node"`
|
||||
RequestId string `json:"request_id"`
|
||||
RequestMethod string `json:"request_method"`
|
||||
RequestScheme string `json:"request_scheme"`
|
||||
RequestTime string `json:"request_time"`
|
||||
RequestUri string `json:"request_uri"`
|
||||
RequestBody string `json:"request_body"`
|
||||
ProxyBody string `json:"proxy_body"`
|
||||
ResponseBody string `json:"response_body"`
|
||||
ProxyResponseBody string `json:"proxy_response_body"`
|
||||
Service string `json:"service"`
|
||||
Provider string `json:"provider"`
|
||||
Authorization string `json:"authorization"`
|
||||
SrcIp string `json:"src_ip"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
@@ -1,296 +0,0 @@
|
||||
package loki
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/eolinker/eosc/log"
|
||||
|
||||
log_driver "github.com/APIParkLab/APIPark/log-driver"
|
||||
)
|
||||
|
||||
func init() {
|
||||
log_driver.RegisterFactory("loki", &factory{})
|
||||
}
|
||||
|
||||
type factory struct {
|
||||
}
|
||||
|
||||
func (f *factory) Create(config string) (log_driver.ILogDriver, map[string]interface{}, error) {
|
||||
|
||||
return NewDriver(config)
|
||||
}
|
||||
|
||||
var (
|
||||
client = http.Client{}
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
url string
|
||||
headers map[string]string
|
||||
}
|
||||
|
||||
func NewDriver(config string) (*Driver, map[string]interface{}, error) {
|
||||
cfg := new(DriverConfig)
|
||||
err := json.Unmarshal([]byte(config), cfg)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
err = cfg.Check()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
headers := map[string]string{}
|
||||
for _, h := range cfg.Header {
|
||||
headers[h.Key] = h.Value
|
||||
}
|
||||
return &Driver{
|
||||
url: cfg.URL,
|
||||
headers: headers,
|
||||
}, map[string]interface{}{
|
||||
"url": cfg.URL,
|
||||
"headers": headers,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Driver) LogInfo(clusterId string, id string) (*log_driver.LogInfo, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("id is empty")
|
||||
}
|
||||
queries := url.Values{}
|
||||
queries.Set("query", fmt.Sprintf("{cluster=\"%s\"} | json | request_id = `%s`", clusterId, id))
|
||||
now := time.Now()
|
||||
start := now.Add(-time.Hour * 24 * 30)
|
||||
queries.Set("start", strconv.FormatInt(start.UnixNano(), 10))
|
||||
queries.Set("end", strconv.FormatInt(now.UnixNano(), 10))
|
||||
queries.Set("limit", "1")
|
||||
log.Debug("query is ", queries.Get("query"))
|
||||
|
||||
list, err := send[LogInfo](http.MethodGet, fmt.Sprintf("%s/loki/api/v1/query_range", d.url), d.headers, queries, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(list) < 1 || list[0].Stream == nil {
|
||||
return nil, fmt.Errorf("no log found")
|
||||
}
|
||||
stream := list[0].Stream
|
||||
return &log_driver.LogInfo{
|
||||
ID: stream.RequestId,
|
||||
ContentType: stream.ContentType,
|
||||
RequestBody: stream.RequestBody,
|
||||
ProxyBody: stream.ProxyBody,
|
||||
ProxyResponseBody: stream.ProxyResponseBody,
|
||||
ResponseBody: stream.ResponseBody,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (d *Driver) LogCount(clusterId string, conditions map[string]string, spendHour int64, group string) (map[string]int64, error) {
|
||||
|
||||
cs := make([]string, 0, len(conditions))
|
||||
for k, v := range conditions {
|
||||
if strings.HasPrefix(k, "#") {
|
||||
cs = append(cs, v)
|
||||
continue
|
||||
}
|
||||
cs = append(cs, fmt.Sprintf("%s=\"%s\"", k, v))
|
||||
}
|
||||
tmpCondition := ""
|
||||
if len(conditions) > 0 {
|
||||
tmpCondition = "|" + strings.Join(cs, "|")
|
||||
}
|
||||
queries := url.Values{}
|
||||
queries.Set("query", fmt.Sprintf("sum(count_over_time({cluster=\"%s\"} | json %s [%dh])) by (%s)", clusterId, tmpCondition, spendHour, group))
|
||||
sendRequestTime := time.Now()
|
||||
list, err := send[LogCount](http.MethodGet, fmt.Sprintf("%s/loki/api/v1/query", d.url), d.headers, queries, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.DebugF("send request spend time: %v", time.Now().Sub(sendRequestTime))
|
||||
log.Debug("query is ", queries.Get("query"))
|
||||
result := make(map[string]int64)
|
||||
for _, l := range list {
|
||||
if len(l.Value) != 2 {
|
||||
continue
|
||||
}
|
||||
value, ok := l.Value[1].(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
v, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
result[l.Metric[group]] = v
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (d *Driver) Logs(clusterId string, conditions map[string]string, start time.Time, end time.Time, limit int64, offset int64) ([]*log_driver.Log, int64, error) {
|
||||
if start.After(end) {
|
||||
return nil, 0, fmt.Errorf("start time is greater than end time")
|
||||
}
|
||||
if len(conditions) < 1 {
|
||||
return nil, 0, fmt.Errorf("conditions is empty")
|
||||
}
|
||||
if offset < 1 {
|
||||
offset = 1
|
||||
}
|
||||
if limit < 1 {
|
||||
limit = 15
|
||||
}
|
||||
count, err := d.logCount(clusterId, conditions, start, end)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if count == 0 {
|
||||
return nil, 0, nil
|
||||
}
|
||||
if count < (offset-1)*limit {
|
||||
return nil, 0, fmt.Errorf("offset is greater than count")
|
||||
}
|
||||
cs := make([]string, 0, len(conditions))
|
||||
for k, v := range conditions {
|
||||
if strings.HasPrefix(k, "#") {
|
||||
cs = append(cs, v)
|
||||
continue
|
||||
}
|
||||
cs = append(cs, fmt.Sprintf("%s=~\"%s\"", k, v))
|
||||
}
|
||||
queries := url.Values{}
|
||||
queries.Set("query", fmt.Sprintf("{cluster=\"%s\"} | json | %s", clusterId, strings.Join(cs, " | ")))
|
||||
queries.Set("limit", strconv.FormatInt(limit, 10))
|
||||
queries.Set("direction", "backward")
|
||||
queries.Set("start", strconv.FormatInt(start.UnixNano(), 10))
|
||||
log.Debug("query is ", queries.Get("query"))
|
||||
logs, err := d.recuseLogs(queries, end, offset)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return logs, count, nil
|
||||
}
|
||||
|
||||
func (d *Driver) recuseLogs(queries url.Values, end time.Time, offset int64) ([]*log_driver.Log, error) {
|
||||
queries.Set("end", strconv.FormatInt(end.UnixNano(), 10))
|
||||
list, err := send[LogInfo](http.MethodGet, fmt.Sprintf("%s/loki/api/v1/query_range", d.url), d.headers, queries, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(list) < 1 {
|
||||
return nil, nil
|
||||
}
|
||||
if offset > 1 {
|
||||
// 获取list最后一个元素的时间戳
|
||||
last := list[len(list)-1].Stream
|
||||
if last == nil {
|
||||
return nil, fmt.Errorf("last log is empty")
|
||||
}
|
||||
msec, err := strconv.ParseInt(last.Msec, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse last log time error: %v", err)
|
||||
}
|
||||
return d.recuseLogs(queries, time.UnixMilli(msec), offset-1)
|
||||
}
|
||||
logs := make([]*log_driver.Log, 0, len(list))
|
||||
for _, l := range list {
|
||||
if l.Stream == nil {
|
||||
continue
|
||||
}
|
||||
detail := l.Stream
|
||||
msec, _ := strconv.ParseInt(detail.Msec, 10, 64)
|
||||
|
||||
logs = append(logs, &log_driver.Log{
|
||||
ID: detail.RequestId,
|
||||
Service: detail.Provider,
|
||||
Method: detail.RequestMethod,
|
||||
Url: detail.RequestUri,
|
||||
RemoteIP: detail.SrcIp,
|
||||
Consumer: detail.Application,
|
||||
Authorization: detail.Authorization,
|
||||
RecordTime: time.UnixMilli(msec),
|
||||
})
|
||||
}
|
||||
sort.Slice(logs, func(i, j int) bool {
|
||||
return logs[i].RecordTime.After(logs[j].RecordTime)
|
||||
})
|
||||
return logs, nil
|
||||
}
|
||||
|
||||
func (d *Driver) logCount(clusterId string, conditions map[string]string, start time.Time, end time.Time) (int64, error) {
|
||||
// 先查在这段时间内符合条件的日志数量
|
||||
queries := url.Values{}
|
||||
queries.Add("start", strconv.FormatInt(start.UnixNano(), 10))
|
||||
queries.Add("end", strconv.FormatInt(end.UnixNano(), 10))
|
||||
cs := make([]string, 0, len(conditions))
|
||||
for k, v := range conditions {
|
||||
if strings.HasPrefix(k, "#") {
|
||||
cs = append(cs, v)
|
||||
continue
|
||||
}
|
||||
cs = append(cs, fmt.Sprintf("%s=\"%s\"", k, v))
|
||||
}
|
||||
tmpCondition := ""
|
||||
if len(conditions) > 0 {
|
||||
tmpCondition = "|" + strings.Join(cs, "|")
|
||||
}
|
||||
queries.Set("query", fmt.Sprintf("sum(count_over_time({cluster=\"%s\"} | json %s [720h]))", clusterId, tmpCondition))
|
||||
list, err := send[LogCount](http.MethodGet, fmt.Sprintf("%s/loki/api/v1/query", d.url), d.headers, queries, "")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(list) < 1 || len(list[0].Value) < 2 {
|
||||
return 0, nil
|
||||
}
|
||||
value, ok := list[0].Value[1].(string)
|
||||
if !ok {
|
||||
return 0, nil
|
||||
}
|
||||
v, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return v, nil
|
||||
}
|
||||
|
||||
func send[T any](method string, uri string, headers map[string]string, queries url.Values, body string) ([]*T, error) {
|
||||
if queries != nil && len(queries) > 0 {
|
||||
uri = fmt.Sprintf("%s?%s", uri, queries.Encode())
|
||||
}
|
||||
req, err := http.NewRequest(method, uri, strings.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create request: %w,uri is %s", err, uri)
|
||||
}
|
||||
for key, value := range headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
log.DebugF("do request: %s", uri)
|
||||
doRequestTime := time.Now()
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||
}
|
||||
log.DebugF("do request spend time: %v", time.Now().Sub(doRequestTime))
|
||||
defer resp.Body.Close()
|
||||
respData, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
if resp.StatusCode > 399 {
|
||||
return nil, fmt.Errorf("failed to send request: %s,body is %s", resp.Status, string(respData))
|
||||
}
|
||||
|
||||
result := new(Response[T])
|
||||
err = json.Unmarshal(respData, result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w,body is %s", err, string(respData))
|
||||
}
|
||||
return result.Data.Result, nil
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package loki
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLoki(t *testing.T) {
|
||||
d, err := NewDriver(`{"url":"http://localhost:3100","header":{"Content-Type":"application/json","X-Scope-OrgID":"tenant1"}}`)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create driver: %v", err)
|
||||
}
|
||||
logCountResult, err := d.LogCount("apinto", nil, 720, "strategy")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get log count: %v", err)
|
||||
}
|
||||
t.Log(logCountResult)
|
||||
logs, count, err := d.Logs("apinto", map[string]string{"strategy": "03899736-5d79-4f26-bd6a-c312a5880780"}, time.Now().Add(-time.Hour*24), time.Now(), 1, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get logs: %v", err)
|
||||
}
|
||||
t.Log(logs, count)
|
||||
info, err := d.LogInfo("apinto", "c9f6b19c-7dfe-496b-9b39-4d049232fe95")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get log info: %v", err)
|
||||
}
|
||||
t.Log(info)
|
||||
}
|
||||
|
||||
//func TestLokiLog(t *testing.T) {
|
||||
//
|
||||
// headers := make(map[string]string)
|
||||
// headers["Content-Type"] = "application/json"
|
||||
// headers["X-Scope-OrgID"] = "tenant1"
|
||||
// queries := url.Values{}
|
||||
// queries.Set("query", "{cluster=\"apinto\"} | json | request_id = `c9f6b19c-7dfe-496b-9b39-4d049232fe95`")
|
||||
// now := time.Now()
|
||||
// start := now.Add(-time.Hour * 24 * 30)
|
||||
// queries.Set("start", strconv.FormatInt(start.UnixNano(), 10))
|
||||
// queries.Set("end", strconv.FormatInt(now.UnixNano(), 10))
|
||||
// queries.Set("limit", "100")
|
||||
// a := time.Now()
|
||||
// result, err := send[LogInfo](http.MethodGet, "http://localhost:3100/loki/api/v1/query_range", headers, queries, "")
|
||||
// if err != nil {
|
||||
// t.Fatalf("failed to send request: %v", err)
|
||||
// }
|
||||
// t.Log(time.Now().Sub(a))
|
||||
// data, err := json.Marshal(result)
|
||||
// if err != nil {
|
||||
// t.Fatalf("failed to marshal data: %v", err)
|
||||
// }
|
||||
// t.Log(string(data))
|
||||
//}
|
||||
//
|
||||
//func TestLokiLogCount(t *testing.T) {
|
||||
// headers := make(map[string]string)
|
||||
// headers["Content-Type"] = "application/json"
|
||||
// headers["X-Scope-OrgID"] = "tenant1"
|
||||
// queries := url.Values{}
|
||||
// //queries.Set("query", "sum(count_over_time({cluster=\"apinto\"}[24h])) by (strategy)")
|
||||
// queries.Set("query", "sum(count_over_time({cluster=\"apinto\"}[24h]))")
|
||||
// result, err := send[LogCount](http.MethodGet, "http://localhost:3100/loki/api/v1/query", headers, queries, "")
|
||||
// if err != nil {
|
||||
// t.Fatalf("failed to send request: %v", err)
|
||||
// }
|
||||
// data, err := json.Marshal(result)
|
||||
// if err != nil {
|
||||
// t.Fatalf("failed to marshal data: %v", err)
|
||||
// }
|
||||
// t.Log(string(data))
|
||||
//}
|
||||
//
|
||||
//func TestLokiLogs(t *testing.T) {
|
||||
// headers := make(map[string]string)
|
||||
// headers["Content-Type"] = "application/json"
|
||||
// headers["X-Scope-OrgID"] = "tenant1"
|
||||
// queries := url.Values{}
|
||||
// queries.Set("query", "{cluster=\"apinto\"} | json | strategy=\"03899736-5d79-4f26-bd6a-c312a5880780\"")
|
||||
// now := time.Now()
|
||||
// start := now.Add(-time.Hour * 24 * 30)
|
||||
// queries.Set("start", strconv.FormatInt(start.UnixNano(), 10))
|
||||
// queries.Set("end", strconv.FormatInt(now.UnixNano(), 10))
|
||||
// queries.Set("limit", "1")
|
||||
// now = time.Now()
|
||||
// result, err := send[map[string]interface{}](http.MethodGet, "http://localhost:3100/loki/api/v1/query_range", headers, queries, "")
|
||||
// t.Log(time.Now().Sub(now))
|
||||
// if err != nil {
|
||||
// t.Fatalf("failed to send request: %v", err)
|
||||
// }
|
||||
// data, err := json.Marshal(result)
|
||||
// if err != nil {
|
||||
// t.Fatalf("failed to marshal data: %v", err)
|
||||
// }
|
||||
// t.Log(string(data))
|
||||
//}
|
||||
@@ -99,9 +99,6 @@ func (i *imlAuthorizationModule) getApplications(ctx context.Context, appIds []s
|
||||
Expire: a.ExpireTime,
|
||||
Config: authCfg,
|
||||
HideCredential: a.HideCredential,
|
||||
Label: map[string]string{
|
||||
"authorization": a.UUID,
|
||||
},
|
||||
}
|
||||
}),
|
||||
}
|
||||
@@ -156,9 +153,6 @@ func (i *imlAuthorizationModule) online(ctx context.Context, s *service.Service)
|
||||
Expire: a.ExpireTime,
|
||||
Config: authCfg,
|
||||
HideCredential: a.HideCredential,
|
||||
Label: map[string]string{
|
||||
"authorization": a.UUID,
|
||||
},
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ type ServiceBasic struct {
|
||||
ApprovalType string `json:"approval_type"`
|
||||
ServiceKind string `json:"service_kind"`
|
||||
InvokeAddress string `json:"invoke_address"`
|
||||
SitePrefix string `json:"site_prefix"`
|
||||
}
|
||||
|
||||
type ServiceApiBasic struct {
|
||||
|
||||
@@ -284,7 +284,6 @@ func (i *imlCatalogueModule) ServiceDetail(ctx context.Context, sid string) (*ca
|
||||
serviceDoc = commit.Data.Content
|
||||
}
|
||||
invokeAddress, _ := i.settingService.Get(ctx, setting.KeyInvokeAddress)
|
||||
sitePrefix, _ := i.settingService.Get(ctx, setting.KeySitePrefix)
|
||||
|
||||
return &catalogue_dto.ServiceDetail{
|
||||
Name: s.Name,
|
||||
@@ -302,7 +301,6 @@ func (i *imlCatalogueModule) ServiceDetail(ctx context.Context, sid string) (*ca
|
||||
ApprovalType: s.ApprovalType.String(),
|
||||
ServiceKind: s.Kind.String(),
|
||||
InvokeAddress: invokeAddress,
|
||||
SitePrefix: sitePrefix,
|
||||
},
|
||||
APIDoc: apiDoc,
|
||||
}, nil
|
||||
|
||||
@@ -145,8 +145,8 @@ func (m *imlClusterModule) ClusterNodes(ctx context.Context, clusterId string) (
|
||||
// return m.Get(ctx, create.Id)
|
||||
//}
|
||||
//
|
||||
//func (m *imlClusterModule) SearchByDriver(ctx context.Context, keyword string) ([]*paritiondto.Item, error) {
|
||||
// partitions, err := m.partitionService.SearchByDriver(ctx, keyword, nil)
|
||||
//func (m *imlClusterModule) Search(ctx context.Context, keyword string) ([]*paritiondto.Item, error) {
|
||||
// partitions, err := m.partitionService.Search(ctx, keyword, nil)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
@@ -185,7 +185,7 @@ func (m *imlClusterModule) ClusterNodes(ctx context.Context, clusterId string) (
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// //oDetails, err := m.organizationService.SearchByDriver(ctx, "")
|
||||
// //oDetails, err := m.organizationService.Search(ctx, "")
|
||||
// //if err != nil {
|
||||
// // return nil, err
|
||||
// //}
|
||||
@@ -248,7 +248,7 @@ func (m *imlClusterModule) ClusterNodes(ctx context.Context, clusterId string) (
|
||||
//}
|
||||
//
|
||||
//func (m *imlClusterModule) Simple(ctx context.Context) ([]*paritiondto.Simple, error) {
|
||||
// pm, err := m.partitionService.SearchByDriver(ctx, "", nil)
|
||||
// pm, err := m.partitionService.Search(ctx, "", nil)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
@@ -262,7 +262,7 @@ func (m *imlClusterModule) ClusterNodes(ctx context.Context, clusterId string) (
|
||||
//}
|
||||
//
|
||||
//func (m *imlClusterModule) SimpleByIds(ctx context.Context, ids []string) ([]*paritiondto.Simple, error) {
|
||||
// pm, err := m.partitionService.SearchByDriver(ctx, "", map[string]interface{}{
|
||||
// pm, err := m.partitionService.Search(ctx, "", map[string]interface{}{
|
||||
// "uuid": ids,
|
||||
// })
|
||||
// if err != nil {
|
||||
@@ -278,7 +278,7 @@ func (m *imlClusterModule) ClusterNodes(ctx context.Context, clusterId string) (
|
||||
//
|
||||
//}
|
||||
//func (m *imlClusterModule) SimpleWithCluster(ctx context.Context) ([]*paritiondto.SimpleWithCluster, error) {
|
||||
// pm, err := m.partitionService.SearchByDriver(ctx, "", nil)
|
||||
// pm, err := m.partitionService.Search(ctx, "", nil)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
package log_dto
|
||||
|
||||
type Save struct {
|
||||
ID string `json:"id"`
|
||||
Cluster string `json:"cluster"`
|
||||
Config map[string]interface{} `json:"config"`
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package log_dto
|
||||
|
||||
import (
|
||||
"github.com/eolinker/go-common/auto"
|
||||
)
|
||||
|
||||
type LogSource struct {
|
||||
ID string `json:"id"`
|
||||
Config map[string]interface{} `json:"config"`
|
||||
Creator auto.Label `json:"creator" aolabel:"user"`
|
||||
Updater auto.Label `json:"updater" aolabel:"user"`
|
||||
CreateAt auto.TimeLabel `json:"create_time"`
|
||||
UpdateAt auto.TimeLabel `json:"update_time"`
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
log_driver "github.com/APIParkLab/APIPark/log-driver"
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
|
||||
"github.com/eolinker/go-common/store"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/cluster"
|
||||
|
||||
"github.com/eolinker/go-common/auto"
|
||||
|
||||
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
||||
"github.com/APIParkLab/APIPark/service/log"
|
||||
log_print "github.com/eolinker/eosc/log"
|
||||
)
|
||||
|
||||
var _ ILogModule = (*imlLogModule)(nil)
|
||||
|
||||
type imlLogModule struct {
|
||||
service log.ILogService `autowired:""`
|
||||
clusterService cluster.IClusterService `autowired:""`
|
||||
transaction store.ITransaction `autowired:""`
|
||||
}
|
||||
|
||||
var labels = map[string]string{
|
||||
"cluster": "$cluster",
|
||||
"node": "$node",
|
||||
}
|
||||
var logFormatter = map[string]interface{}{
|
||||
"fields": []string{
|
||||
"$msec",
|
||||
"$service",
|
||||
"$provider",
|
||||
"$scheme as request_scheme",
|
||||
"$url as request_uri",
|
||||
"$host as request_host",
|
||||
"$header as request_header",
|
||||
"$remote_addr",
|
||||
"$request_body",
|
||||
"$proxy_body",
|
||||
"$proxy_method",
|
||||
"$proxy_scheme",
|
||||
"$proxy_uri",
|
||||
"$api",
|
||||
"$proxy_host",
|
||||
"$proxy_header",
|
||||
"$proxy_addr",
|
||||
"$response_headers",
|
||||
"$status",
|
||||
"$content_type",
|
||||
"$proxy_status",
|
||||
"$request_time",
|
||||
"$response_time",
|
||||
"$node",
|
||||
"$cluster",
|
||||
"$application",
|
||||
"$src_ip",
|
||||
"$block_name as strategy",
|
||||
"$request_id",
|
||||
"$request_method",
|
||||
"$authorization",
|
||||
"$response_body",
|
||||
"$proxy_response_body",
|
||||
},
|
||||
}
|
||||
|
||||
func (i *imlLogModule) Save(ctx context.Context, driver string, input *log_dto.Save) error {
|
||||
factory, has := log_driver.GetFactory(driver)
|
||||
if !has {
|
||||
return errors.New("driver not found")
|
||||
}
|
||||
input.Cluster = cluster.DefaultClusterID
|
||||
var cfg *string
|
||||
if input.Config != nil {
|
||||
data, _ := json.Marshal(input.Config)
|
||||
tmp := string(data)
|
||||
cfg = &tmp
|
||||
}
|
||||
return i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||
err := i.service.UpdateLogSource(txCtx, driver, &log.Save{
|
||||
ID: input.ID,
|
||||
Cluster: &input.Cluster,
|
||||
Config: cfg,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := i.service.GetLogSource(txCtx, driver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d, c, err := factory.Create(info.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, err := i.clusterService.GatewayClient(txCtx, input.Cluster)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close(txCtx)
|
||||
dynamicClient, err := client.Dynamic(driver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
attr := make(map[string]interface{})
|
||||
attr["driver"] = driver
|
||||
attr["formatter"] = logFormatter
|
||||
attr["labels"] = labels
|
||||
attr["method"] = "POST"
|
||||
attr["scopes"] = []string{"access_log"}
|
||||
attr["type"] = "json"
|
||||
for k, v := range c {
|
||||
attr[k] = v
|
||||
}
|
||||
err = dynamicClient.Online(txCtx, &gateway.DynamicRelease{
|
||||
BasicItem: &gateway.BasicItem{
|
||||
ID: driver,
|
||||
Description: "collect access log",
|
||||
Version: time.Now().Format("20060102150405"),
|
||||
Resource: gateway.ProfessionOutput,
|
||||
},
|
||||
Attr: attr,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log_driver.SetDriver(driver, d)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlLogModule) Get(ctx context.Context, driver string) (*log_dto.LogSource, error) {
|
||||
info, err := i.service.GetLogSource(ctx, driver)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
cfg := make(map[string]interface{})
|
||||
if info.Config != "" {
|
||||
err = json.Unmarshal([]byte(info.Config), &cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &log_dto.LogSource{
|
||||
ID: info.ID,
|
||||
Config: cfg,
|
||||
Creator: auto.UUID(info.Creator),
|
||||
Updater: auto.UUID(info.Updater),
|
||||
CreateAt: auto.TimeLabel(info.CreateAt),
|
||||
UpdateAt: auto.TimeLabel(info.UpdateAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (i *imlLogModule) OnComplete() {
|
||||
drivers := log_driver.Drivers()
|
||||
if len(drivers) < 1 {
|
||||
return
|
||||
}
|
||||
ctx := context.Background()
|
||||
for _, driver := range drivers {
|
||||
factory, has := log_driver.GetFactory(driver)
|
||||
if !has {
|
||||
log_print.Errorf("driver %s not found", driver)
|
||||
continue
|
||||
}
|
||||
info, err := i.service.GetLogSource(ctx, driver)
|
||||
if err != nil {
|
||||
log_print.Errorf("get log source %s error: %s", driver, err)
|
||||
continue
|
||||
}
|
||||
d, _, err := factory.Create(info.Config)
|
||||
if err != nil {
|
||||
log_print.Errorf("create driver %s error: %s,config: %s", driver, err, info.Config)
|
||||
continue
|
||||
}
|
||||
log_driver.SetDriver(driver, d)
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlLogModule) initGateway(ctx context.Context, clusterId string, clientDriver gateway.IClientDriver) error {
|
||||
drivers := log_driver.Drivers()
|
||||
if len(drivers) < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, driver := range drivers {
|
||||
factory, has := log_driver.GetFactory(driver)
|
||||
if !has {
|
||||
log_print.Errorf("driver %s not found", driver)
|
||||
continue
|
||||
}
|
||||
info, err := i.service.GetLogSource(ctx, driver)
|
||||
if err != nil {
|
||||
log_print.Errorf("get log source %s error: %s", driver, err)
|
||||
continue
|
||||
}
|
||||
d, c, err := factory.Create(info.Config)
|
||||
if err != nil {
|
||||
log_print.Errorf("create driver %s error: %s,config: %s", driver, err, info.Config)
|
||||
continue
|
||||
}
|
||||
log_driver.SetDriver(driver, d)
|
||||
dynamicClient, err := clientDriver.Dynamic(driver)
|
||||
if err != nil {
|
||||
log_print.Errorf("get dynamic client %s error: %s", driver, err)
|
||||
continue
|
||||
}
|
||||
attr := make(map[string]interface{})
|
||||
attr["driver"] = driver
|
||||
attr["formatter"] = logFormatter
|
||||
attr["labels"] = labels
|
||||
attr["method"] = "POST"
|
||||
for k, v := range c {
|
||||
attr[k] = v
|
||||
}
|
||||
err = dynamicClient.Online(ctx, &gateway.DynamicRelease{
|
||||
BasicItem: &gateway.BasicItem{
|
||||
ID: driver,
|
||||
Description: "collect access log",
|
||||
Version: time.Now().Format("20060102150405"),
|
||||
Resource: gateway.ProfessionOutput,
|
||||
},
|
||||
Attr: attr,
|
||||
})
|
||||
if err != nil {
|
||||
log_print.Errorf("online driver %s error: %s", driver, err)
|
||||
continue
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
||||
)
|
||||
|
||||
type ILogModule interface {
|
||||
Save(ctx context.Context, driver string, input *log_dto.Save) error
|
||||
Get(ctx context.Context, driver string) (*log_dto.LogSource, error)
|
||||
}
|
||||
|
||||
func init() {
|
||||
logModule := new(imlLogModule)
|
||||
|
||||
autowire.Auto[ILogModule](func() reflect.Value {
|
||||
|
||||
gateway.RegisterInitHandleFunc(logModule.initGateway)
|
||||
return reflect.ValueOf(logModule)
|
||||
})
|
||||
}
|
||||
@@ -24,7 +24,7 @@ type CommonInput struct {
|
||||
|
||||
type StatisticInput struct {
|
||||
Apis []string `json:"apis"`
|
||||
Services []string `json:"services"`
|
||||
Projects []string `json:"projects"`
|
||||
Path string `json:"path"`
|
||||
*CommonInput
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ type ApiStatisticBasicItem struct {
|
||||
*MonCommonData
|
||||
}
|
||||
|
||||
type ServiceStatisticItem struct {
|
||||
*ServiceStatisticBasicItem
|
||||
type ProjectStatisticItem struct {
|
||||
*ProjectStatisticBasicItem
|
||||
IsRed bool `json:"is_red"` //是否标红
|
||||
}
|
||||
|
||||
type ServiceStatisticBasicItem struct {
|
||||
type ProjectStatisticBasicItem struct {
|
||||
Id string `json:"id"` //订阅方ID
|
||||
Name string `json:"name"` //订阅方名称
|
||||
*MonCommonData
|
||||
|
||||
+11
-447
@@ -5,15 +5,14 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
"github.com/eolinker/eosc/log"
|
||||
"github.com/eolinker/go-common/auto"
|
||||
"github.com/eolinker/go-common/store"
|
||||
"github.com/eolinker/go-common/utils"
|
||||
"gorm.io/gorm"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/service"
|
||||
|
||||
@@ -43,442 +42,6 @@ type imlMonitorStatisticModule struct {
|
||||
apiService api.IAPIService `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) ApiStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wm := make(map[string]interface{})
|
||||
if len(input.Apis) > 0 {
|
||||
wm["uuid"] = input.Apis
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "api",
|
||||
Operation: "in",
|
||||
Values: input.Apis,
|
||||
})
|
||||
}
|
||||
if len(input.Services) > 0 {
|
||||
wm["service"] = input.Services
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "project",
|
||||
Operation: "in",
|
||||
Values: input.Services,
|
||||
})
|
||||
}
|
||||
// 查询符合条件的API
|
||||
apis, err := i.apiService.Search(ctx, input.Path, wm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(apis) < 1 {
|
||||
// 没有符合条件的API
|
||||
return make([]*monitor_dto.ApiStatisticBasicItem, 0), nil
|
||||
}
|
||||
apiIds := utils.SliceToSlice(apis, func(t *api.API) string {
|
||||
return t.UUID
|
||||
})
|
||||
|
||||
apiInfos, err := i.apiService.ListInfo(ctx, apiIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return i.apiStatistics(ctx, clusterId, apiInfos, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) apiStatistics(ctx context.Context, clusterId string, apiInfos []*api.Info, start time.Time, end time.Time, wheres []monitor.MonWhereItem, limit int) ([]*monitor_dto.ApiStatisticBasicItem, error) {
|
||||
statisticMap, err := i.statistics(ctx, clusterId, "api", start, end, wheres, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]*monitor_dto.ApiStatisticBasicItem, 0, len(statisticMap))
|
||||
for _, item := range apiInfos {
|
||||
|
||||
statisticItem := &monitor_dto.ApiStatisticBasicItem{
|
||||
Id: item.UUID,
|
||||
Name: item.Name,
|
||||
Path: item.Path,
|
||||
Service: auto.UUID(item.Service),
|
||||
MonCommonData: new(monitor_dto.MonCommonData),
|
||||
}
|
||||
if val, ok := statisticMap[item.UUID]; ok {
|
||||
statisticItem.MonCommonData = monitor_dto.ToMonCommonData(val)
|
||||
delete(statisticMap, item.UUID)
|
||||
}
|
||||
result = append(result, statisticItem)
|
||||
}
|
||||
for key, item := range statisticMap {
|
||||
statisticItem := &monitor_dto.ApiStatisticBasicItem{
|
||||
Id: key,
|
||||
Name: "未知API-" + key,
|
||||
MonCommonData: monitor_dto.ToMonCommonData(item),
|
||||
}
|
||||
|
||||
if key == "-" {
|
||||
statisticItem.Name = "无API"
|
||||
}
|
||||
result = append(result, statisticItem)
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].RequestTotal > result[j].RequestTotal
|
||||
})
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) SubscriberStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apps, err := i.serviceService.AppList(ctx, input.Services...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appIds := utils.SliceToSlice(apps, func(p *service.Service) string {
|
||||
return p.Id
|
||||
})
|
||||
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(appIds) > 0 {
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "app",
|
||||
Operation: "in",
|
||||
Values: appIds,
|
||||
})
|
||||
}
|
||||
|
||||
return i.serviceStatistics(ctx, clusterId, apps, "app", formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) serviceStatistics(ctx context.Context, clusterId string, services []*service.Service, groupBy string, start time.Time, end time.Time, wheres []monitor.MonWhereItem, limit int) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
|
||||
statisticMap, err := i.statistics(ctx, clusterId, groupBy, start, end, wheres, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]*monitor_dto.ServiceStatisticBasicItem, 0, len(statisticMap))
|
||||
for _, item := range services {
|
||||
statisticItem := &monitor_dto.ServiceStatisticBasicItem{
|
||||
Id: item.Id,
|
||||
Name: item.Name,
|
||||
MonCommonData: new(monitor_dto.MonCommonData),
|
||||
}
|
||||
if val, ok := statisticMap[item.Id]; ok {
|
||||
statisticItem.MonCommonData = monitor_dto.ToMonCommonData(val)
|
||||
delete(statisticMap, item.Id)
|
||||
}
|
||||
result = append(result, statisticItem)
|
||||
}
|
||||
for key, item := range statisticMap {
|
||||
statisticItem := &monitor_dto.ServiceStatisticBasicItem{
|
||||
Id: key,
|
||||
Name: "未知-" + key,
|
||||
MonCommonData: monitor_dto.ToMonCommonData(item),
|
||||
}
|
||||
|
||||
if key == "-" {
|
||||
statisticItem.Name = "-"
|
||||
}
|
||||
result = append(result, statisticItem)
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].RequestTotal > result[j].RequestTotal
|
||||
})
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) ProviderStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
services, err := i.serviceService.ServiceList(ctx, input.Services...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(input.Services) > 0 {
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "provider",
|
||||
Operation: "in",
|
||||
Values: input.Services,
|
||||
})
|
||||
}
|
||||
|
||||
return i.serviceStatistics(ctx, clusterId, services, "provider", formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) APITrend(ctx context.Context, apiId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "api",
|
||||
Operation: "=",
|
||||
Values: []string{apiId},
|
||||
})
|
||||
executor, err := i.getExecutor(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) ProviderTrend(ctx context.Context, providerId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "provider",
|
||||
Operation: "=",
|
||||
Values: []string{providerId},
|
||||
})
|
||||
executor, err := i.getExecutor(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) SubscriberTrend(ctx context.Context, subscriberId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "app",
|
||||
Operation: "=",
|
||||
Values: []string{subscriberId},
|
||||
})
|
||||
executor, err := i.getExecutor(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) InvokeTrendWithSubscriberAndApi(ctx context.Context, apiId string, subscriberId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "api",
|
||||
Operation: "=",
|
||||
Values: []string{apiId},
|
||||
}, monitor.MonWhereItem{
|
||||
Key: "app",
|
||||
Operation: "=",
|
||||
Values: []string{subscriberId},
|
||||
})
|
||||
executor, err := i.getExecutor(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) InvokeTrendWithProviderAndApi(ctx context.Context, providerId string, apiId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "api",
|
||||
Operation: "=",
|
||||
Values: []string{apiId},
|
||||
}, monitor.MonWhereItem{
|
||||
Key: "provider",
|
||||
Operation: "=",
|
||||
Values: []string{providerId},
|
||||
})
|
||||
executor, err := i.getExecutor(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
result, timeInterval, err := executor.InvokeTrend(ctx, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return monitor_dto.ToMonInvokeCountTrend(result), timeInterval, nil
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) statisticOnApi(ctx context.Context, clusterId string, apiId string, groupBy string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var service []*service.Service
|
||||
switch groupBy {
|
||||
case "app":
|
||||
service, err = i.serviceService.AppList(ctx)
|
||||
case "provider":
|
||||
service, err = i.serviceService.ServiceList(ctx)
|
||||
default:
|
||||
return nil, errors.New("invalid group by")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "api",
|
||||
Operation: "=",
|
||||
Values: []string{apiId},
|
||||
})
|
||||
|
||||
statisticMap, err := i.statistics(ctx, clusterId, groupBy, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]*monitor_dto.ServiceStatisticBasicItem, 0, len(statisticMap))
|
||||
for _, item := range service {
|
||||
|
||||
statisticItem := &monitor_dto.ServiceStatisticBasicItem{
|
||||
Id: item.Id,
|
||||
Name: item.Name,
|
||||
MonCommonData: new(monitor_dto.MonCommonData),
|
||||
}
|
||||
if val, ok := statisticMap[item.Id]; ok {
|
||||
statisticItem.MonCommonData = monitor_dto.ToMonCommonData(val)
|
||||
delete(statisticMap, item.Id)
|
||||
}
|
||||
result = append(result, statisticItem)
|
||||
}
|
||||
for key, item := range statisticMap {
|
||||
statisticItem := &monitor_dto.ServiceStatisticBasicItem{
|
||||
Id: key,
|
||||
Name: "未知-" + key,
|
||||
MonCommonData: monitor_dto.ToMonCommonData(item),
|
||||
}
|
||||
|
||||
if key == "-" {
|
||||
statisticItem.Name = "-"
|
||||
}
|
||||
result = append(result, statisticItem)
|
||||
}
|
||||
sort.Slice(result, func(i, j int) bool {
|
||||
return result[i].RequestTotal > result[j].RequestTotal
|
||||
})
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) ProviderStatisticsOnApi(ctx context.Context, apiId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
return i.statisticOnApi(ctx, clusterId, apiId, "provider", input)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) ApiStatisticsOnProvider(ctx context.Context, providerId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
apiInfos, err := i.apiService.ListInfoForService(ctx, providerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "provider",
|
||||
Operation: "=",
|
||||
Values: []string{providerId},
|
||||
})
|
||||
|
||||
return i.apiStatistics(ctx, clusterId, apiInfos, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) ApiStatisticsOnSubscriber(ctx context.Context, subscriberId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 根据订阅ID查询订阅的服务列表
|
||||
subscriptions, err := i.subscribeService.MySubscribeServices(ctx, subscriberId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serviceIds := utils.SliceToSlice(subscriptions, func(t *subscribe.Subscribe) string {
|
||||
return t.Service
|
||||
})
|
||||
if len(serviceIds) < 1 {
|
||||
return nil, nil
|
||||
}
|
||||
apiInfos, err := i.apiService.ListInfoForServices(ctx, serviceIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
wheres = append(wheres, monitor.MonWhereItem{
|
||||
Key: "app",
|
||||
Operation: "=",
|
||||
Values: []string{subscriberId},
|
||||
})
|
||||
|
||||
return i.apiStatistics(ctx, clusterId, apiInfos, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, 0)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) SubscriberStatisticsOnApi(ctx context.Context, apiId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
return i.statisticOnApi(ctx, clusterId, apiId, "app", input)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) MessageTrend(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonMessageTrend, string, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
@@ -610,7 +173,7 @@ func (i *imlMonitorStatisticModule) TopAPIStatistics(ctx context.Context, limit
|
||||
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error) {
|
||||
func (i *imlMonitorStatisticModule) TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
@@ -619,7 +182,7 @@ func (i *imlMonitorStatisticModule) TopSubscriberStatistics(ctx context.Context,
|
||||
return i.topProjectStatistics(ctx, clusterId, "app", input, limit)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error) {
|
||||
func (i *imlMonitorStatisticModule) TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
@@ -628,12 +191,12 @@ func (i *imlMonitorStatisticModule) TopProviderStatistics(ctx context.Context, l
|
||||
return i.topProjectStatistics(ctx, clusterId, "provider", input, limit)
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) topProjectStatistics(ctx context.Context, clusterId string, groupBy string, input *monitor_dto.CommonInput, limit int) ([]*monitor_dto.ServiceStatisticItem, error) {
|
||||
wheres, err := i.genCommonWheres(ctx, clusterId)
|
||||
func (i *imlMonitorStatisticModule) topProjectStatistics(ctx context.Context, partitionId string, groupBy string, input *monitor_dto.CommonInput, limit int) ([]*monitor_dto.ProjectStatisticItem, error) {
|
||||
wheres, err := i.genCommonWheres(ctx, partitionId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
statisticMap, err := i.statistics(ctx, clusterId, groupBy, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, limit)
|
||||
statisticMap, err := i.statistics(ctx, partitionId, groupBy, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -653,10 +216,10 @@ func (i *imlMonitorStatisticModule) topProjectStatistics(ctx context.Context, cl
|
||||
return t.Id
|
||||
})
|
||||
|
||||
result := make([]*monitor_dto.ServiceStatisticItem, 0, len(statisticMap))
|
||||
result := make([]*monitor_dto.ProjectStatisticItem, 0, len(statisticMap))
|
||||
for key, item := range statisticMap {
|
||||
statisticItem := &monitor_dto.ServiceStatisticItem{
|
||||
ServiceStatisticBasicItem: &monitor_dto.ServiceStatisticBasicItem{
|
||||
statisticItem := &monitor_dto.ProjectStatisticItem{
|
||||
ProjectStatisticBasicItem: &monitor_dto.ProjectStatisticBasicItem{
|
||||
Id: key,
|
||||
MonCommonData: monitor_dto.ToMonCommonData(item),
|
||||
},
|
||||
@@ -844,6 +407,7 @@ func (m *imlMonitorConfig) GetMonitorConfig(ctx context.Context) (*monitor_dto.M
|
||||
Driver: info.Driver,
|
||||
Config: cfg,
|
||||
}, nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *imlMonitorConfig) GetMonitorCluster(ctx context.Context) ([]*monitor_dto.MonitorCluster, error) {
|
||||
|
||||
@@ -13,36 +13,18 @@ import (
|
||||
|
||||
type IMonitorStatisticModule interface {
|
||||
TopAPIStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ApiStatisticItem, error)
|
||||
TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error)
|
||||
TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error)
|
||||
TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error)
|
||||
TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error)
|
||||
// RequestSummary 请求概况
|
||||
RequestSummary(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonSummaryOutput, error)
|
||||
// ProxySummary 转发概况
|
||||
ProxySummary(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonSummaryOutput, error)
|
||||
|
||||
// InvokeTrend 调用次数趋势
|
||||
InvokeTrend(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||
|
||||
// MessageTrend 消息趋势
|
||||
MessageTrend(ctx context.Context, input *monitor_dto.CommonInput) (*monitor_dto.MonMessageTrend, string, error)
|
||||
|
||||
ApiStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error)
|
||||
|
||||
SubscriberStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error)
|
||||
|
||||
ProviderStatistics(ctx context.Context, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error)
|
||||
|
||||
APITrend(ctx context.Context, apiId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||
|
||||
ProviderTrend(ctx context.Context, providerId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||
|
||||
SubscriberTrend(ctx context.Context, subscriberId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||
|
||||
InvokeTrendWithSubscriberAndApi(ctx context.Context, apiId string, subscriberId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||
InvokeTrendWithProviderAndApi(ctx context.Context, providerId string, apiId string, input *monitor_dto.CommonInput) (*monitor_dto.MonInvokeCountTrend, string, error)
|
||||
|
||||
ProviderStatisticsOnApi(ctx context.Context, apiId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error)
|
||||
ApiStatisticsOnProvider(ctx context.Context, providerId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error)
|
||||
ApiStatisticsOnSubscriber(ctx context.Context, subscriberId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ApiStatisticBasicItem, error)
|
||||
SubscriberStatisticsOnApi(ctx context.Context, apiId string, input *monitor_dto.StatisticInput) ([]*monitor_dto.ServiceStatisticBasicItem, error)
|
||||
}
|
||||
|
||||
type IMonitorConfigModule interface {
|
||||
|
||||
+128
-93
@@ -2,18 +2,10 @@ package publish
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
strategy_driver "github.com/APIParkLab/APIPark/module/strategy/driver"
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
|
||||
"github.com/eolinker/eosc"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/strategy"
|
||||
|
||||
"github.com/eolinker/go-common/store"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/service"
|
||||
@@ -51,7 +43,6 @@ type imlPublishModule struct {
|
||||
publishService publish.IPublishService `autowired:""`
|
||||
apiService api.IAPIService `autowired:""`
|
||||
upstreamService upstream.IUpstreamService `autowired:""`
|
||||
strategyService strategy.IStrategyService `autowired:""`
|
||||
releaseService release.IReleaseService `autowired:""`
|
||||
clusterService cluster.IClusterService `autowired:""`
|
||||
serviceService service.IServiceService `autowired:""`
|
||||
@@ -68,7 +59,7 @@ func (m *imlPublishModule) initGateway(ctx context.Context, partitionId string,
|
||||
return p.Id
|
||||
})
|
||||
for _, projectId := range projectIds {
|
||||
releaseInfo, err := m.GetProjectRelease(ctx, projectId, partitionId)
|
||||
releaseInfo, err := m.getProjectRelease(ctx, projectId, partitionId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -84,15 +75,22 @@ func (m *imlPublishModule) initGateway(ctx context.Context, partitionId string,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *imlPublishModule) getProjectRelease(ctx context.Context, projectID string, commitId string) (*gateway.ProjectRelease, error) {
|
||||
commits, err := m.releaseService.GetCommits(ctx, commitId)
|
||||
func (m *imlPublishModule) getProjectRelease(ctx context.Context, projectID string, partitionId string) (*gateway.ProjectRelease, error) {
|
||||
|
||||
releaseInfo, err := m.releaseService.GetRunning(ctx, projectID)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
commits, err := m.releaseService.GetCommits(ctx, releaseInfo.UUID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiIds := make([]string, 0, len(commits))
|
||||
apiProxyCommitIds := make([]string, 0, len(commits))
|
||||
upstreamCommitIds := make([]string, 0, len(commits))
|
||||
strategyCommitIds := make([]string, 0, len(commits))
|
||||
for _, c := range commits {
|
||||
switch c.Type {
|
||||
case release.CommitApiProxy:
|
||||
@@ -100,8 +98,6 @@ func (m *imlPublishModule) getProjectRelease(ctx context.Context, projectID stri
|
||||
apiProxyCommitIds = append(apiProxyCommitIds, c.Commit)
|
||||
case release.CommitUpstream:
|
||||
upstreamCommitIds = append(upstreamCommitIds, c.Commit)
|
||||
case release.CommitStrategy:
|
||||
strategyCommitIds = append(strategyCommitIds, c.Commit)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,11 +114,99 @@ func (m *imlPublishModule) getProjectRelease(ctx context.Context, projectID stri
|
||||
return c.Target, c.Data
|
||||
})
|
||||
|
||||
version := commitId
|
||||
r := &gateway.ProjectRelease{
|
||||
Id: projectID,
|
||||
Version: version,
|
||||
upstreamCommits, err := m.upstreamService.ListCommit(ctx, upstreamCommitIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
version := releaseInfo.UUID
|
||||
apis := make([]*gateway.ApiRelease, 0, len(apiInfos))
|
||||
for _, a := range apiInfos {
|
||||
apiInfo := &gateway.ApiRelease{
|
||||
BasicItem: &gateway.BasicItem{
|
||||
ID: a.UUID,
|
||||
Description: a.Description,
|
||||
Version: version,
|
||||
},
|
||||
Path: a.Path,
|
||||
Methods: a.Methods,
|
||||
Service: a.Service,
|
||||
}
|
||||
proxy, ok := proxyCommitMap[a.UUID]
|
||||
if ok {
|
||||
apiInfo.ProxyPath = proxy.Path
|
||||
apiInfo.ProxyHeaders = utils.SliceToSlice(proxy.Headers, func(h *api.Header) *gateway.ProxyHeader {
|
||||
return &gateway.ProxyHeader{
|
||||
Key: h.Key,
|
||||
Value: h.Value,
|
||||
}
|
||||
})
|
||||
apiInfo.Retry = proxy.Retry
|
||||
apiInfo.Timeout = proxy.Timeout
|
||||
}
|
||||
apis = append(apis, apiInfo)
|
||||
}
|
||||
var upstreamRelease *gateway.UpstreamRelease
|
||||
for _, c := range upstreamCommits {
|
||||
if c.Key != partitionId {
|
||||
continue
|
||||
}
|
||||
upstreamRelease = &gateway.UpstreamRelease{
|
||||
BasicItem: &gateway.BasicItem{
|
||||
ID: c.Target,
|
||||
Version: version,
|
||||
MatchLabels: map[string]string{
|
||||
"serviceId": projectID,
|
||||
},
|
||||
},
|
||||
PassHost: c.Data.PassHost,
|
||||
Scheme: c.Data.Scheme,
|
||||
Balance: c.Data.Balance,
|
||||
Timeout: c.Data.Timeout,
|
||||
Nodes: utils.SliceToSlice(c.Data.Nodes, func(n *upstream.NodeConfig) string {
|
||||
return fmt.Sprintf("%s weight=%d", n.Address, n.Weight)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
return &gateway.ProjectRelease{
|
||||
Id: projectID,
|
||||
Version: version,
|
||||
Apis: apis,
|
||||
Upstream: upstreamRelease,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *imlPublishModule) getReleaseInfo(ctx context.Context, projectID, releaseId, version string, clusterIds []string) (map[string]*gateway.ProjectRelease, error) {
|
||||
commits, err := m.releaseService.GetCommits(ctx, releaseId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiIds := make([]string, 0, len(commits))
|
||||
apiProxyCommitIds := make([]string, 0, len(commits))
|
||||
upstreamCommitIds := make([]string, 0, len(commits))
|
||||
for _, c := range commits {
|
||||
switch c.Type {
|
||||
case release.CommitApiProxy:
|
||||
apiIds = append(apiIds, c.Target)
|
||||
apiProxyCommitIds = append(apiProxyCommitIds, c.Commit)
|
||||
case release.CommitUpstream:
|
||||
upstreamCommitIds = append(upstreamCommitIds, c.Commit)
|
||||
}
|
||||
}
|
||||
|
||||
apiInfos, err := m.apiService.ListInfo(ctx, apiIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
proxyCommits, err := m.apiService.ListProxyCommit(ctx, apiProxyCommitIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proxyCommitMap := utils.SliceToMapO(proxyCommits, func(c *commit.Commit[api.Proxy]) (string, *api.Proxy) {
|
||||
return c.Target, c.Data
|
||||
})
|
||||
|
||||
apis := make([]*gateway.ApiRelease, 0, len(apiInfos))
|
||||
for _, a := range apiInfos {
|
||||
apiInfo := &gateway.ApiRelease{
|
||||
@@ -156,93 +240,44 @@ func (m *imlPublishModule) getProjectRelease(ctx context.Context, projectID stri
|
||||
}
|
||||
apis = append(apis, apiInfo)
|
||||
}
|
||||
r.Apis = apis
|
||||
var upstreamRelease *gateway.UpstreamRelease
|
||||
projectReleaseMap := make(map[string]*gateway.ProjectRelease)
|
||||
upstreamReleaseMap := make(map[string]*gateway.UpstreamRelease)
|
||||
if len(upstreamCommitIds) > 0 {
|
||||
upstreamCommits, err := m.upstreamService.ListCommit(ctx, upstreamCommitIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range upstreamCommits {
|
||||
upstreamRelease = &gateway.UpstreamRelease{
|
||||
BasicItem: &gateway.BasicItem{
|
||||
ID: c.Target,
|
||||
Version: version,
|
||||
MatchLabels: map[string]string{
|
||||
"serviceId": projectID,
|
||||
for _, partitionId := range clusterIds {
|
||||
upstreamRelease := &gateway.UpstreamRelease{
|
||||
BasicItem: &gateway.BasicItem{
|
||||
ID: c.Target,
|
||||
Version: version,
|
||||
MatchLabels: map[string]string{
|
||||
"serviceId": projectID,
|
||||
},
|
||||
},
|
||||
},
|
||||
PassHost: c.Data.PassHost,
|
||||
Scheme: c.Data.Scheme,
|
||||
Balance: c.Data.Balance,
|
||||
Timeout: c.Data.Timeout,
|
||||
Nodes: utils.SliceToSlice(c.Data.Nodes, func(n *upstream.NodeConfig) string {
|
||||
return fmt.Sprintf("%s weight=%d", n.Address, n.Weight)
|
||||
}),
|
||||
PassHost: c.Data.PassHost,
|
||||
Scheme: c.Data.Scheme,
|
||||
Balance: c.Data.Balance,
|
||||
Timeout: c.Data.Timeout,
|
||||
Nodes: utils.SliceToSlice(c.Data.Nodes, func(n *upstream.NodeConfig) string {
|
||||
return fmt.Sprintf("%s weight=%d", n.Address, n.Weight)
|
||||
}),
|
||||
}
|
||||
|
||||
upstreamReleaseMap[partitionId] = upstreamRelease
|
||||
}
|
||||
}
|
||||
r.Upstream = upstreamRelease
|
||||
}
|
||||
if len(strategyCommitIds) > 0 {
|
||||
strategyCommits, err := m.strategyService.ListStrategyCommit(ctx, strategyCommitIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
strategyReleases := make([]*eosc.Base[gateway.StrategyRelease], 0, len(strategyCommits))
|
||||
for _, c := range strategyCommits {
|
||||
s := c.Data
|
||||
driver, has := strategy_driver.GetDriver(c.Data.Driver)
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
filters := make([]*strategy_dto.Filter, 0)
|
||||
json.Unmarshal([]byte(s.Filters), &filters)
|
||||
var cfg interface{}
|
||||
json.Unmarshal([]byte(s.Config), &cfg)
|
||||
strategyReleases = append(strategyReleases, driver.ToRelease(&strategy_dto.Strategy{
|
||||
Id: fmt.Sprintf("%s", s.Id),
|
||||
Name: s.Name,
|
||||
Priority: s.Priority,
|
||||
Filters: filters,
|
||||
Config: cfg,
|
||||
IsDelete: s.IsDelete || s.IsStop,
|
||||
}, map[string][]string{
|
||||
"provider": {projectID},
|
||||
}, 0))
|
||||
}
|
||||
r.Strategies = strategyReleases
|
||||
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (m *imlPublishModule) GetProjectRelease(ctx context.Context, projectID string, partitionId string) (*gateway.ProjectRelease, error) {
|
||||
|
||||
releaseInfo, err := m.releaseService.GetRunning(ctx, projectID)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return m.getProjectRelease(ctx, projectID, releaseInfo.UUID)
|
||||
}
|
||||
|
||||
func (m *imlPublishModule) getReleaseInfo(ctx context.Context, projectID, releaseId, version string, clusterIds []string) (map[string]*gateway.ProjectRelease, error) {
|
||||
projectRelease, err := m.getProjectRelease(ctx, projectID, releaseId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
projectReleaseMap := make(map[string]*gateway.ProjectRelease)
|
||||
for _, clusterId := range clusterIds {
|
||||
projectReleaseMap[clusterId] = &gateway.ProjectRelease{
|
||||
Id: projectID,
|
||||
Version: version,
|
||||
Apis: projectRelease.Apis,
|
||||
Upstream: projectRelease.Upstream,
|
||||
Strategies: projectRelease.Strategies,
|
||||
Id: projectID,
|
||||
Version: version,
|
||||
Apis: apis,
|
||||
Upstream: upstreamReleaseMap[clusterId],
|
||||
}
|
||||
}
|
||||
return projectReleaseMap, nil
|
||||
|
||||
+2
-33
@@ -5,10 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/strategy"
|
||||
|
||||
api_doc "github.com/APIParkLab/APIPark/service/api-doc"
|
||||
service_doc "github.com/APIParkLab/APIPark/service/service-doc"
|
||||
|
||||
@@ -44,26 +40,11 @@ type imlReleaseModule struct {
|
||||
serviceDocService service_doc.IDocService `autowired:""`
|
||||
upstreamService upstream.IUpstreamService `autowired:""`
|
||||
publishService publish.IPublishService `autowired:""`
|
||||
strategyService strategy.IStrategyService `autowired:""`
|
||||
transaction store.ITransaction `autowired:""`
|
||||
projectService service.IServiceService `autowired:""`
|
||||
clusterService cluster.IClusterService `autowired:""`
|
||||
}
|
||||
|
||||
func (m *imlReleaseModule) latestStrategyCommits(ctx context.Context, serviceId string) ([]*commit.Commit[strategy.Commit], error) {
|
||||
list, err := m.strategyService.All(ctx, 2, serviceId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get latest strategy failed:%w", err)
|
||||
}
|
||||
for _, s := range list {
|
||||
err = m.strategyService.CommitStrategy(ctx, strategy_dto.ScopeService, serviceId, s.Id, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return m.strategyService.ListLatestStrategyCommit(ctx, strategy_dto.ScopeService, serviceId)
|
||||
}
|
||||
|
||||
func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input *dto.CreateInput) (string, error) {
|
||||
|
||||
proInfo, err := m.projectService.Check(ctx, serviceId, projectRuleMustServer)
|
||||
@@ -102,7 +83,7 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input *
|
||||
return "", errors.New("api or document not found")
|
||||
}
|
||||
|
||||
upstreams, err := m.upstreamService.ListLatestCommit(ctx, cluster.DefaultClusterID, serviceId)
|
||||
upstreams, err := m.upstreamService.ListLatestCommit(ctx, serviceId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return "", errors.New("api config or document not found")
|
||||
@@ -145,9 +126,6 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input *
|
||||
|
||||
doc, err := m.apiDocService.GetDoc(ctx, serviceId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fmt.Errorf("api doc not found")
|
||||
}
|
||||
return err
|
||||
}
|
||||
err = m.apiDocService.CommitDoc(ctx, serviceId, doc)
|
||||
@@ -173,17 +151,8 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input *
|
||||
}
|
||||
serviceDocCommit, err := m.serviceDocService.LatestDocCommit(ctx, serviceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
strategies, err := m.latestStrategyCommits(ctx, serviceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
strategyCommits := utils.SliceToMapO(strategies, func(c *commit.Commit[strategy.Commit]) (string, string) {
|
||||
return c.Target, c.UUID
|
||||
})
|
||||
|
||||
if !m.releaseService.Completeness(utils.SliceToSlice(clusters, func(s *cluster.Cluster) string {
|
||||
return s.Uuid
|
||||
}), apiUUIDS, requestCommits, apiProxy, upstreams) {
|
||||
@@ -192,7 +161,7 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input *
|
||||
requestCommitMap := utils.SliceToMapO(requestCommits, func(c *commit.Commit[api.Request]) (string, string) {
|
||||
return c.Target, c.UUID
|
||||
})
|
||||
newRelease, err = m.releaseService.CreateRelease(ctx, serviceId, input.Version, input.Remark, requestCommitMap, apiProxyCommits, docCommit.UUID, serviceDocCommit.UUID, upstreamCommitsForUKC, strategyCommits)
|
||||
newRelease, err = m.releaseService.CreateRelease(ctx, serviceId, input.Version, input.Remark, requestCommitMap, apiProxyCommits, docCommit.UUID, serviceDocCommit.UUID, upstreamCommitsForUKC)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -102,7 +102,3 @@ type ListInput struct {
|
||||
type UpdateDoc struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type InputSimpleAPI struct {
|
||||
Services []string `json:"services"`
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ type Item struct {
|
||||
type SimpleItem struct {
|
||||
Id string `json:"id"`
|
||||
Methods []string `json:"methods"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"request_path"`
|
||||
}
|
||||
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
"github.com/eolinker/eosc/log"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/api"
|
||||
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
|
||||
)
|
||||
|
||||
var _ strategy_filter.IRemoteFilter = (*imlRouterFilter)(nil)
|
||||
|
||||
type imlRouterFilter struct {
|
||||
service api.IAPIService `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Name() string {
|
||||
return "api"
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Title() string {
|
||||
return "API"
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Labels(values ...string) []string {
|
||||
list, err := i.service.ListInfo(context.Background(), values...)
|
||||
if err != nil {
|
||||
log.Errorf("get api labels error: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return utils.SliceToSlice(list, func(a *api.Info) string {
|
||||
return a.Name
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Type() string {
|
||||
return strategy_filter.TypeRemote
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Scopes() []string {
|
||||
return []string{
|
||||
//strategy_filter.ScopeGlobal,
|
||||
strategy_filter.ScopeService,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Option() *strategy_filter.Option {
|
||||
return &strategy_filter.Option{
|
||||
Name: i.Name(),
|
||||
Title: i.Title(),
|
||||
Type: i.Type(),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Titles() []strategy_filter.OptionTitle {
|
||||
return []strategy_filter.OptionTitle{
|
||||
{
|
||||
Field: "name",
|
||||
Title: "api name",
|
||||
},
|
||||
{
|
||||
Field: "methods",
|
||||
Title: "methods",
|
||||
},
|
||||
{
|
||||
Field: "request_path",
|
||||
Title: "request path",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Key() string {
|
||||
return "id"
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) Target() string {
|
||||
return "list"
|
||||
}
|
||||
|
||||
func (i *imlRouterFilter) RemoteList(ctx context.Context, keyword string, condition map[string]interface{}, page int, pageSize int) ([]any, int64, error) {
|
||||
if pageSize == -1 {
|
||||
// 获取全部
|
||||
list, err := i.service.Search(ctx, keyword, condition)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return utils.SliceToSlice(list, func(s *api.API) any {
|
||||
return &router_dto.SimpleItem{
|
||||
Id: s.UUID,
|
||||
Path: s.Path,
|
||||
Methods: s.Method,
|
||||
}
|
||||
}), int64(len(list)), nil
|
||||
}
|
||||
list, total, err := i.service.SearchByPage(ctx, keyword, condition, page, pageSize, "update_at")
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return utils.SliceToSlice(list, func(s *api.API) any {
|
||||
return &router_dto.SimpleItem{
|
||||
Id: s.UUID,
|
||||
Path: s.Path,
|
||||
Methods: s.Method,
|
||||
}
|
||||
}), total, nil
|
||||
}
|
||||
@@ -46,28 +46,6 @@ type imlRouterModule struct {
|
||||
transaction store.ITransaction `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlRouterModule) SimpleAPIs(ctx context.Context, input *router_dto.InputSimpleAPI) ([]*router_dto.SimpleItem, error) {
|
||||
list, err := i.apiService.ListForServices(ctx, input.Services...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiInfos, err := i.apiService.ListInfo(ctx, utils.SliceToSlice(list, func(s *api.API) string {
|
||||
return s.UUID
|
||||
})...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return utils.SliceToSlice(apiInfos, func(item *api.Info) *router_dto.SimpleItem {
|
||||
return &router_dto.SimpleItem{
|
||||
Id: item.UUID,
|
||||
Name: item.Name,
|
||||
Methods: item.Methods,
|
||||
Path: item.Path,
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (i *imlRouterModule) ExportAll(ctx context.Context) ([]*router_dto.Export, error) {
|
||||
|
||||
apiList, err := i.apiService.ListInfo(ctx)
|
||||
|
||||
@@ -2,10 +2,8 @@ package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/APIParkLab/APIPark/module/system"
|
||||
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
|
||||
"reflect"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
|
||||
@@ -31,7 +29,6 @@ type IRouterModule interface {
|
||||
// Prefix 获取API前缀
|
||||
Prefix(ctx context.Context, serviceId string) (string, error)
|
||||
|
||||
SimpleAPIs(ctx context.Context, input *router_dto.InputSimpleAPI) ([]*router_dto.SimpleItem, error)
|
||||
//ExportAll(ctx context.Context) ([]*router_dto.Export, error)
|
||||
}
|
||||
|
||||
@@ -48,8 +45,4 @@ func init() {
|
||||
autowire.Auto[IExportRouterModule](func() reflect.Value {
|
||||
return reflect.ValueOf(apiModule)
|
||||
})
|
||||
|
||||
filter := new(imlRouterFilter)
|
||||
autowire.Autowired(filter)
|
||||
strategy_filter.RegisterRemoteFilter(filter)
|
||||
}
|
||||
|
||||
+21
-119
@@ -5,8 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/strategy"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/service"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/api"
|
||||
@@ -25,7 +23,6 @@ type imlServiceDiff struct {
|
||||
apiDocService api_doc.IAPIDocService `autowired:""`
|
||||
upstreamService upstream.IUpstreamService `autowired:""`
|
||||
releaseService release.IReleaseService `autowired:""`
|
||||
strategyService strategy.IStrategyService `autowired:""`
|
||||
clusterService cluster.IClusterService `autowired:""`
|
||||
}
|
||||
|
||||
@@ -82,34 +79,6 @@ func (m *imlServiceDiff) getBaseInfo(ctx context.Context, serviceId, baseRelease
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
func (m *imlServiceDiff) latestStrategyCommits(ctx context.Context, serviceId string) ([]*commit.Commit[strategy.Commit], error) {
|
||||
list, err := m.strategyService.All(ctx, 2, serviceId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get latest strategy failed:%w", err)
|
||||
}
|
||||
|
||||
return utils.SliceToSlice(list, func(s *strategy.Strategy) *commit.Commit[strategy.Commit] {
|
||||
key := fmt.Sprintf("service-%s", s.Id)
|
||||
return &commit.Commit[strategy.Commit]{
|
||||
Target: s.Id,
|
||||
Key: key,
|
||||
Data: &strategy.Commit{
|
||||
Id: s.Id,
|
||||
Name: s.Name,
|
||||
Priority: s.Priority,
|
||||
Filters: s.Filters,
|
||||
Config: s.Config,
|
||||
Driver: s.Driver,
|
||||
IsStop: s.IsStop,
|
||||
Version: s.UpdateAt.Format("20060102150405"),
|
||||
},
|
||||
}
|
||||
}, func(s *strategy.Strategy) bool {
|
||||
return !s.IsDelete
|
||||
}), nil
|
||||
}
|
||||
|
||||
func (m *imlServiceDiff) DiffForLatest(ctx context.Context, serviceId string, baseRelease string) (*service_diff.Diff, bool, error) {
|
||||
serviceInfo, err := m.serviceService.Get(ctx, serviceId)
|
||||
if err != nil {
|
||||
@@ -119,9 +88,6 @@ func (m *imlServiceDiff) DiffForLatest(ctx context.Context, serviceId string, ba
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if len(apis) < 1 {
|
||||
return nil, false, fmt.Errorf("api not found")
|
||||
}
|
||||
|
||||
apiIds := utils.SliceToSlice(apis, func(i *api.API) string {
|
||||
return i.UUID
|
||||
@@ -156,7 +122,7 @@ func (m *imlServiceDiff) DiffForLatest(ctx context.Context, serviceId string, ba
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
upstreamCommits, err := m.upstreamService.ListLatestCommit(ctx, cluster.DefaultClusterID, serviceId)
|
||||
upstreamCommits, err := m.upstreamService.ListLatestCommit(ctx, serviceId)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@@ -164,11 +130,6 @@ func (m *imlServiceDiff) DiffForLatest(ctx context.Context, serviceId string, ba
|
||||
return nil, false, fmt.Errorf("upstream not found")
|
||||
}
|
||||
|
||||
strategyCommits, err := m.latestStrategyCommits(ctx, serviceId)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
base, err := m.getBaseInfo(ctx, serviceId, baseRelease)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
@@ -179,7 +140,6 @@ func (m *imlServiceDiff) DiffForLatest(ctx context.Context, serviceId string, ba
|
||||
apiProxyCommits: proxy,
|
||||
apiDocCommits: apiDocCommits,
|
||||
upstreamCommits: upstreamCommits,
|
||||
strategyCommits: strategyCommits,
|
||||
}
|
||||
clusters, err := m.clusterService.List(ctx)
|
||||
if err != nil {
|
||||
@@ -195,26 +155,26 @@ func (m *imlServiceDiff) getReleaseInfo(ctx context.Context, releaseId string) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiRequestCommitIds := make([]string, 0)
|
||||
apiProxyCommitIds := make([]string, 0)
|
||||
apiDocumentCommitIds := make([]string, 0)
|
||||
upstreamCommitIds := make([]string, 0)
|
||||
strategyCommitIds := make([]string, 0)
|
||||
for _, c := range commits {
|
||||
switch c.Type {
|
||||
case release.CommitApiRequest:
|
||||
apiRequestCommitIds = append(apiRequestCommitIds, c.Commit)
|
||||
case release.CommitApiProxy:
|
||||
apiProxyCommitIds = append(apiProxyCommitIds, c.Commit)
|
||||
case release.CommitApiDocument:
|
||||
apiDocumentCommitIds = append(apiDocumentCommitIds, c.Commit)
|
||||
case release.CommitUpstream:
|
||||
upstreamCommitIds = append(upstreamCommitIds, c.Commit)
|
||||
case release.CommitStrategy:
|
||||
strategyCommitIds = append(strategyCommitIds, c.Commit)
|
||||
}
|
||||
}
|
||||
|
||||
apiRequestCommitIds := utils.SliceToSlice(commits, func(i *release.ProjectCommits) string {
|
||||
return i.Target
|
||||
}, func(c *release.ProjectCommits) bool {
|
||||
return c.Type == release.CommitApiRequest
|
||||
})
|
||||
apiProxyCommitIds := utils.SliceToSlice(commits, func(i *release.ProjectCommits) string {
|
||||
return i.Commit
|
||||
}, func(c *release.ProjectCommits) bool {
|
||||
return c.Type == release.CommitApiProxy
|
||||
})
|
||||
apiDocumentCommitIds := utils.SliceToSlice(commits, func(i *release.ProjectCommits) string {
|
||||
return i.Commit
|
||||
}, func(c *release.ProjectCommits) bool {
|
||||
return c.Type == release.CommitApiDocument
|
||||
})
|
||||
upstreamCommitIds := utils.SliceToSlice(commits, func(i *release.ProjectCommits) string {
|
||||
return i.Commit
|
||||
}, func(c *release.ProjectCommits) bool {
|
||||
return c.Type == release.CommitUpstream
|
||||
})
|
||||
var requestCommits []*commit.Commit[api.Request]
|
||||
var proxyCommits []*commit.Commit[api.Proxy]
|
||||
var documentCommits []*commit.Commit[api_doc.DocCommit]
|
||||
@@ -243,63 +203,14 @@ func (m *imlServiceDiff) getReleaseInfo(ctx context.Context, releaseId string) (
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var strategyCommits []*commit.Commit[strategy.Commit]
|
||||
if len(strategyCommitIds) > 0 {
|
||||
strategyCommits, err = m.strategyService.ListStrategyCommit(ctx, strategyCommitIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &projectInfo{
|
||||
apiRequestCommits: requestCommits,
|
||||
apiProxyCommits: proxyCommits,
|
||||
apiDocCommits: documentCommits,
|
||||
upstreamCommits: upstreamCommits,
|
||||
strategyCommits: strategyCommits,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *imlServiceDiff) diffStrategies(base, target []*commit.Commit[strategy.Commit]) []*service_diff.StrategyDiff {
|
||||
baseStrategy := utils.SliceToMap(base, func(i *commit.Commit[strategy.Commit]) string {
|
||||
return i.Target
|
||||
})
|
||||
targetStrategy := utils.SliceToMap(target, func(i *commit.Commit[strategy.Commit]) string {
|
||||
return i.Target
|
||||
})
|
||||
out := make([]*service_diff.StrategyDiff, 0, len(target))
|
||||
for _, tc := range targetStrategy {
|
||||
|
||||
//t := tc.Data
|
||||
key := tc.Target
|
||||
o := &service_diff.StrategyDiff{
|
||||
Strategy: key,
|
||||
Name: tc.Data.Name,
|
||||
Priority: tc.Data.Priority,
|
||||
Change: service_diff.ChangeTypeNone,
|
||||
Status: 0,
|
||||
}
|
||||
b, hasB := baseStrategy[key]
|
||||
if !hasB {
|
||||
o.Change = service_diff.ChangeTypeNew
|
||||
} else if tc.Data.Version != b.Data.Version {
|
||||
o.Change = service_diff.ChangeTypeUpdate
|
||||
}
|
||||
delete(baseStrategy, key)
|
||||
out = append(out, o)
|
||||
}
|
||||
for _, b := range baseStrategy {
|
||||
o := &service_diff.StrategyDiff{
|
||||
Strategy: b.Target,
|
||||
Name: b.Data.Name,
|
||||
Priority: b.Data.Priority,
|
||||
Change: service_diff.ChangeTypeDelete,
|
||||
Status: 0,
|
||||
}
|
||||
out = append(out, o)
|
||||
}
|
||||
return out
|
||||
}
|
||||
func (m *imlServiceDiff) diff(partitions []string, base, target *projectInfo) *service_diff.Diff {
|
||||
out := &service_diff.Diff{
|
||||
Apis: nil,
|
||||
@@ -417,7 +328,6 @@ func (m *imlServiceDiff) diff(partitions []string, base, target *projectInfo) *s
|
||||
}
|
||||
}
|
||||
}
|
||||
out.Strategies = m.diffStrategies(base.strategyCommits, target.strategyCommits)
|
||||
|
||||
return out
|
||||
}
|
||||
@@ -463,13 +373,5 @@ func (m *imlServiceDiff) Out(ctx context.Context, diff *service_diff.Diff) (*Dif
|
||||
}),
|
||||
})
|
||||
}
|
||||
out.Strategies = utils.SliceToSlice(diff.Strategies, func(i *service_diff.StrategyDiff) *StrategyDiffOut {
|
||||
return &StrategyDiffOut{
|
||||
Name: i.Name,
|
||||
Priority: i.Priority,
|
||||
Change: i.Change,
|
||||
Status: i.Status,
|
||||
}
|
||||
})
|
||||
return out, nil
|
||||
}
|
||||
|
||||
@@ -4,15 +4,13 @@ import (
|
||||
"github.com/APIParkLab/APIPark/service/api"
|
||||
api_doc "github.com/APIParkLab/APIPark/service/api-doc"
|
||||
"github.com/APIParkLab/APIPark/service/service_diff"
|
||||
"github.com/APIParkLab/APIPark/service/strategy"
|
||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||
"github.com/APIParkLab/APIPark/service/upstream"
|
||||
)
|
||||
|
||||
type DiffOut struct {
|
||||
Routers []*RouterDiffOut `json:"routers"`
|
||||
Upstreams []*UpstreamDiffOut `json:"upstreams"`
|
||||
Strategies []*StrategyDiffOut `json:"strategies"`
|
||||
Routers []*RouterDiffOut `json:"routers"`
|
||||
Upstreams []*UpstreamDiffOut `json:"upstreams"`
|
||||
}
|
||||
|
||||
type RouterDiffOut struct {
|
||||
@@ -32,13 +30,6 @@ type UpstreamDiffOut struct {
|
||||
Addr []string `json:"addr,omitempty"`
|
||||
}
|
||||
|
||||
type StrategyDiffOut struct {
|
||||
Name string `json:"name"`
|
||||
Priority int `json:"priority"`
|
||||
Change service_diff.ChangeType `json:"change,omitempty"`
|
||||
Status service_diff.StatusType `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
type projectInfo struct {
|
||||
id string
|
||||
//apis []*api.Info
|
||||
@@ -46,5 +37,4 @@ type projectInfo struct {
|
||||
apiProxyCommits []*commit.Commit[api.Proxy]
|
||||
apiDocCommits []*commit.Commit[api_doc.DocCommit]
|
||||
upstreamCommits []*commit.Commit[upstream.Config]
|
||||
strategyCommits []*commit.Commit[strategy.Commit]
|
||||
}
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/subscribe"
|
||||
|
||||
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
|
||||
"github.com/eolinker/go-common/auto"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/service"
|
||||
"github.com/eolinker/eosc/log"
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
|
||||
)
|
||||
|
||||
var _ strategy_filter.IRemoteFilter = (*imlAppFilter)(nil)
|
||||
|
||||
type imlAppFilter struct {
|
||||
service service.IServiceService `autowired:""`
|
||||
subscriberService subscribe.ISubscribeService `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Name() string {
|
||||
return "application"
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Title() string {
|
||||
return "consumer"
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Labels(values ...string) []string {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
if values[0] == strategy_filter.ValuesALL {
|
||||
return []string{
|
||||
"all consumer",
|
||||
}
|
||||
}
|
||||
apps, err := i.service.AppList(context.Background(), values...)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil
|
||||
}
|
||||
return utils.SliceToSlice(apps, func(a *service.Service) string {
|
||||
return a.Name
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Type() string {
|
||||
return strategy_filter.TypeRemote
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Scopes() []string {
|
||||
return []string{
|
||||
strategy_filter.ScopeGlobal,
|
||||
strategy_filter.ScopeService,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Option() *strategy_filter.Option {
|
||||
return &strategy_filter.Option{
|
||||
Name: i.Name(),
|
||||
Title: i.Title(),
|
||||
Type: i.Type(),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Titles() []strategy_filter.OptionTitle {
|
||||
return []strategy_filter.OptionTitle{
|
||||
{
|
||||
Field: "name",
|
||||
Title: "consumer",
|
||||
},
|
||||
{
|
||||
Field: "id",
|
||||
Title: "consumer id",
|
||||
},
|
||||
{
|
||||
Field: "description",
|
||||
Title: "description",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Key() string {
|
||||
return "id"
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) Target() string {
|
||||
return "list"
|
||||
}
|
||||
|
||||
func (i *imlAppFilter) RemoteList(ctx context.Context, keyword string, condition map[string]interface{}, page int, pageSize int) ([]any, int64, error) {
|
||||
if condition == nil {
|
||||
condition = make(map[string]interface{})
|
||||
}
|
||||
if serviceId, ok := condition["service"]; ok {
|
||||
// 查询订阅了该服务的消费者
|
||||
v, ok := serviceId.(string)
|
||||
if ok {
|
||||
subscribers, err := i.subscriberService.Subscribers(ctx, v, subscribe.ApplyStatusSubscribe)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if len(subscribers) > 0 {
|
||||
appIds := utils.SliceToSlice(subscribers, func(s *subscribe.Subscribe) string {
|
||||
return s.Application
|
||||
})
|
||||
condition["uuid"] = appIds
|
||||
}
|
||||
|
||||
}
|
||||
delete(condition, "service")
|
||||
}
|
||||
condition["as_app"] = true
|
||||
if pageSize == -1 {
|
||||
// 获取全部
|
||||
list, err := i.service.Search(ctx, keyword, condition, "update_at")
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return utils.SliceToSlice(list, func(s *service.Service) any {
|
||||
return &service_dto.SimpleAppItem{
|
||||
Id: s.Id,
|
||||
Name: s.Name,
|
||||
Team: auto.UUID(s.Team),
|
||||
Description: s.Description,
|
||||
}
|
||||
}), int64(len(list)), nil
|
||||
}
|
||||
list, total, err := i.service.SearchByPage(ctx, keyword, condition, page, pageSize, "update_at")
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return utils.SliceToSlice(list, func(s *service.Service) any {
|
||||
return &service_dto.SimpleAppItem{
|
||||
Id: s.Id,
|
||||
Name: s.Name,
|
||||
Team: auto.UUID(s.Team),
|
||||
Description: s.Description,
|
||||
}
|
||||
}), total, nil
|
||||
}
|
||||
+45
-43
@@ -109,7 +109,9 @@ func (i *imlServiceModule) ExportAll(ctx context.Context) ([]*service_dto.Export
|
||||
Catalogue: s.Catalogue,
|
||||
Logo: s.Logo,
|
||||
}
|
||||
|
||||
//if v, ok := docMap[s.Id]; ok {
|
||||
// info.Doc = v.Doc
|
||||
//}
|
||||
if tags, ok := serviceTagMap[s.Id]; ok {
|
||||
info.Tags = tags
|
||||
}
|
||||
@@ -174,7 +176,7 @@ func (i *imlServiceModule) SearchMyServices(ctx context.Context, teamId string,
|
||||
//func (i *imlServiceModule) SimpleAPPS(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
|
||||
// w := make(map[string]interface{})
|
||||
// w["as_app"] = true
|
||||
// services, err := i.serviceService.SearchByDriver(ctx, keyword, w)
|
||||
// services, err := i.serviceService.Search(ctx, keyword, w)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
@@ -189,47 +191,47 @@ func (i *imlServiceModule) SearchMyServices(ctx context.Context, teamId string,
|
||||
// }), nil
|
||||
//}
|
||||
|
||||
func (i *imlServiceModule) Simple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error) {
|
||||
w := make(map[string]interface{})
|
||||
w["as_server"] = true
|
||||
|
||||
services, err := i.serviceService.Search(ctx, "", w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
items := make([]*service_dto.SimpleServiceItem, 0, len(services))
|
||||
for _, p := range services {
|
||||
|
||||
items = append(items, &service_dto.SimpleServiceItem{
|
||||
Id: p.Id,
|
||||
Name: p.Name,
|
||||
Description: p.Description,
|
||||
Team: auto.UUID(p.Team),
|
||||
})
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (i *imlServiceModule) MySimple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error) {
|
||||
services, err := i.searchMyServices(ctx, "", "")
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
items := make([]*service_dto.SimpleServiceItem, 0, len(services))
|
||||
for _, p := range services {
|
||||
|
||||
items = append(items, &service_dto.SimpleServiceItem{
|
||||
Id: p.Id,
|
||||
Name: p.Name,
|
||||
Description: p.Description,
|
||||
Team: auto.UUID(p.Team),
|
||||
})
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
//func (i *imlServiceModule) Simple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
|
||||
// w := make(map[string]interface{})
|
||||
// w["as_server"] = true
|
||||
//
|
||||
// services, err := i.serviceService.Search(ctx, keyword, w)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// items := make([]*service_dto.SimpleServiceItem, 0, len(services))
|
||||
// for _, p := range services {
|
||||
//
|
||||
// items = append(items, &service_dto.SimpleServiceItem{
|
||||
// Id: p.Id,
|
||||
// Name: p.Name,
|
||||
// Description: p.Description,
|
||||
// Team: auto.UUID(p.Team),
|
||||
// })
|
||||
// }
|
||||
// return items, nil
|
||||
//}
|
||||
//
|
||||
//func (i *imlServiceModule) MySimple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error) {
|
||||
// services, err := i.searchMyServices(ctx, "", keyword)
|
||||
//
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// items := make([]*service_dto.SimpleServiceItem, 0, len(services))
|
||||
// for _, p := range services {
|
||||
//
|
||||
// items = append(items, &service_dto.SimpleServiceItem{
|
||||
// Id: p.Id,
|
||||
// Name: p.Name,
|
||||
// Description: p.Description,
|
||||
// Team: auto.UUID(p.Team),
|
||||
// })
|
||||
// }
|
||||
// return items, nil
|
||||
//}
|
||||
|
||||
func (i *imlServiceModule) Get(ctx context.Context, id string) (*service_dto.Service, error) {
|
||||
now := time.Now()
|
||||
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
|
||||
|
||||
"github.com/APIParkLab/APIPark/module/system"
|
||||
|
||||
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
|
||||
@@ -27,11 +25,11 @@ type IServiceModule interface {
|
||||
// Delete 删除项目
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
//Simple 获取简易项目列表
|
||||
Simple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error)
|
||||
// Simple 获取简易项目列表
|
||||
//Simple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error)
|
||||
|
||||
//MySimple 获取我的简易项目列表
|
||||
MySimple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error)
|
||||
// MySimple 获取我的简易项目列表
|
||||
//MySimple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error)
|
||||
}
|
||||
|
||||
type IServiceDocModule interface {
|
||||
@@ -85,8 +83,4 @@ func init() {
|
||||
return reflect.ValueOf(serviceDocModule)
|
||||
})
|
||||
|
||||
filter := new(imlAppFilter)
|
||||
autowire.Autowired(filter)
|
||||
strategy_filter.RegisterRemoteFilter(filter)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package data_masking
|
||||
|
||||
type Config struct {
|
||||
Rules []*Rule `json:"rules"`
|
||||
}
|
||||
|
||||
type Rule struct {
|
||||
Match *BasicItem `json:"match"`
|
||||
Mask *Mask `json:"mask"`
|
||||
}
|
||||
|
||||
type BasicItem struct {
|
||||
Type string `json:"type"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type Mask struct {
|
||||
Type string `json:"type"`
|
||||
Begin int `json:"begin"`
|
||||
Length int `json:"length"`
|
||||
Replace *BasicItem `json:"replace"`
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package data_masking
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
"github.com/eolinker/eosc"
|
||||
|
||||
strategy_driver "github.com/APIParkLab/APIPark/module/strategy/driver"
|
||||
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
)
|
||||
|
||||
func init() {
|
||||
strategy_driver.Register(&strategyDriver{confName: "data_mask"})
|
||||
}
|
||||
|
||||
type strategyDriver struct {
|
||||
confName string
|
||||
}
|
||||
|
||||
func (d *strategyDriver) Driver() string {
|
||||
return "data-masking"
|
||||
}
|
||||
|
||||
func (d *strategyDriver) ToRelease(s *strategy_dto.Strategy, labels map[string][]string, initStep int) *eosc.Base[gateway.StrategyRelease] {
|
||||
filters := make(map[string][]string)
|
||||
|
||||
for _, f := range s.Filters {
|
||||
filters[f.Name] = f.Values
|
||||
}
|
||||
for key, value := range labels {
|
||||
filters[key] = value
|
||||
}
|
||||
|
||||
base := eosc.NewBase[gateway.StrategyRelease]()
|
||||
base.Config = &gateway.StrategyRelease{
|
||||
Name: s.Id,
|
||||
Desc: s.Name,
|
||||
Driver: "data_mask",
|
||||
Priority: initStep + s.Priority,
|
||||
Filters: filters,
|
||||
IsDelete: s.IsDelete,
|
||||
}
|
||||
cfg := make(map[string]interface{})
|
||||
cfg[d.confName] = s.Config
|
||||
base.Append = cfg
|
||||
return base
|
||||
|
||||
}
|
||||
|
||||
func (d *strategyDriver) Check(config interface{}) error {
|
||||
if config == nil {
|
||||
return nil
|
||||
}
|
||||
data, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var cfg Config
|
||||
err = json.Unmarshal(data, &cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, r := range cfg.Rules {
|
||||
if r.Match == nil {
|
||||
return errors.New("match can't be null. ")
|
||||
}
|
||||
if r.Mask == nil {
|
||||
return errors.New("mask can't be null. ")
|
||||
}
|
||||
|
||||
if _, ok := validMatchTypes[r.Match.Type]; !ok {
|
||||
return fmt.Errorf("match type %s is illegal. ", r.Match.Type)
|
||||
}
|
||||
|
||||
if r.Match.Type == "inner" {
|
||||
if _, ok := validMatchInnerValues[r.Match.Value]; !ok {
|
||||
return fmt.Errorf("match value %s is illegal. ", r.Match.Value)
|
||||
}
|
||||
}
|
||||
if _, ok := validMaskTypes[r.Mask.Type]; !ok {
|
||||
return fmt.Errorf("mask type %s is illegal. ", r.Mask.Type)
|
||||
}
|
||||
if r.Mask.Replace != nil {
|
||||
if _, ok := validReplaceTypes[r.Mask.Replace.Type]; !ok {
|
||||
return fmt.Errorf("replace type %s is illegal. ", r.Mask.Replace.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package data_masking
|
||||
|
||||
var validMatchInnerValues = map[string]struct{}{
|
||||
"name": {},
|
||||
"phone": {},
|
||||
"email": {},
|
||||
"id-card": {},
|
||||
"bank-card": {},
|
||||
"date": {},
|
||||
"amount": {},
|
||||
}
|
||||
var validMatchTypes = map[string]struct{}{
|
||||
"inner": {},
|
||||
"keyword": {},
|
||||
"regex": {},
|
||||
"json_path": {},
|
||||
}
|
||||
|
||||
var validMaskTypes = map[string]struct{}{
|
||||
"partial-display": {},
|
||||
"partial-masking": {},
|
||||
"truncation": {},
|
||||
"replacement": {},
|
||||
"shuffling": {},
|
||||
}
|
||||
|
||||
var validReplaceTypes = map[string]struct{}{
|
||||
"random": {},
|
||||
"custom": {},
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package strategy_driver
|
||||
|
||||
import (
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
"github.com/eolinker/eosc"
|
||||
)
|
||||
|
||||
type IStrategyDriver interface {
|
||||
Driver() string
|
||||
ToRelease(s *strategy_dto.Strategy, labels map[string][]string, initStep int) *eosc.Base[gateway.StrategyRelease]
|
||||
Check(config interface{}) error
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package strategy_driver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/eolinker/eosc"
|
||||
)
|
||||
|
||||
var manager = newManager()
|
||||
|
||||
func newManager() *Manager {
|
||||
return &Manager{
|
||||
drivers: eosc.BuildUntyped[string, IStrategyDriver](),
|
||||
}
|
||||
}
|
||||
|
||||
type Manager struct {
|
||||
drivers eosc.Untyped[string, IStrategyDriver]
|
||||
}
|
||||
|
||||
func (m *Manager) AddDriver(driver IStrategyDriver) {
|
||||
m.drivers.Set(driver.Driver(), driver)
|
||||
}
|
||||
|
||||
func (m *Manager) GetDriver(driver string) (IStrategyDriver, bool) {
|
||||
return m.drivers.Get(driver)
|
||||
}
|
||||
|
||||
func (m *Manager) GetDrivers() []string {
|
||||
return m.drivers.Keys()
|
||||
}
|
||||
|
||||
func (m *Manager) Delete(name string) {
|
||||
m.drivers.Del(name)
|
||||
}
|
||||
|
||||
func GetDriver(name string) (IStrategyDriver, bool) {
|
||||
return manager.GetDriver(name)
|
||||
}
|
||||
|
||||
func Register(driver IStrategyDriver) {
|
||||
manager.AddDriver(driver)
|
||||
}
|
||||
|
||||
func CheckConfig(name string, config interface{}) error {
|
||||
driver, has := manager.GetDriver(name)
|
||||
if !has {
|
||||
return fmt.Errorf("driver %s not found", name)
|
||||
}
|
||||
|
||||
return driver.Check(config)
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package strategy_dto
|
||||
|
||||
const (
|
||||
ScopeGlobal = "global"
|
||||
ScopeTeam = "team"
|
||||
ScopeService = "service"
|
||||
|
||||
PublishStatusOnline = "online"
|
||||
PublishStatusOffline = "offline"
|
||||
PublishStatusUpdate = "update"
|
||||
PublishStatusDelete = "delete"
|
||||
)
|
||||
|
||||
type Scope int
|
||||
|
||||
func (s Scope) String() string {
|
||||
switch s {
|
||||
case 0:
|
||||
return ScopeGlobal
|
||||
case 1:
|
||||
return ScopeTeam
|
||||
case 2:
|
||||
return ScopeService
|
||||
default:
|
||||
return ScopeGlobal
|
||||
}
|
||||
}
|
||||
|
||||
func (s Scope) Int() int {
|
||||
return int(s)
|
||||
}
|
||||
|
||||
func ToScope(s string) Scope {
|
||||
switch s {
|
||||
case ScopeGlobal:
|
||||
return 0
|
||||
case ScopeTeam:
|
||||
return 1
|
||||
case ScopeService:
|
||||
return 2
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package strategy_dto
|
||||
|
||||
type Create struct {
|
||||
Scope Scope `json:"-"`
|
||||
Target string `json:"-"`
|
||||
Driver string `json:"-"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Priority int `json:"priority"`
|
||||
Desc string `json:"desc"`
|
||||
Filters []*Filter `json:"filters"`
|
||||
Config interface{} `json:"config"`
|
||||
}
|
||||
|
||||
type Edit struct {
|
||||
Name *string `json:"name"`
|
||||
Priority *int `json:"priority"`
|
||||
Desc *string `json:"desc"`
|
||||
Filters *[]*Filter `json:"filters"`
|
||||
Config *interface{} `json:"config"`
|
||||
}
|
||||
|
||||
type Filter struct {
|
||||
Name string `json:"name"`
|
||||
Values []string `json:"values"`
|
||||
Type string `json:"type"`
|
||||
Label string `json:"label"`
|
||||
Title string `json:"title"`
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
package strategy_dto
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/strategy"
|
||||
"github.com/eolinker/go-common/auto"
|
||||
)
|
||||
|
||||
func StrategyStatus(s *strategy.Strategy, publishVersion string) string {
|
||||
publishStatus := PublishStatusOffline
|
||||
if publishVersion != "" {
|
||||
if s.IsDelete {
|
||||
publishStatus = PublishStatusDelete
|
||||
} else {
|
||||
version := s.UpdateAt.Format("20060102150405")
|
||||
if version != publishVersion {
|
||||
publishStatus = PublishStatusUpdate
|
||||
} else {
|
||||
publishStatus = PublishStatusOnline
|
||||
}
|
||||
}
|
||||
}
|
||||
return publishStatus
|
||||
}
|
||||
|
||||
func ToStrategyItem(s *strategy.Strategy, publishVersion string, filters string, processedTotal int64) *StrategyItem {
|
||||
publishStatus := PublishStatusOffline
|
||||
if publishVersion != "" {
|
||||
if s.IsDelete {
|
||||
publishStatus = PublishStatusDelete
|
||||
} else {
|
||||
version := s.UpdateAt.Format("20060102150405")
|
||||
if version != publishVersion {
|
||||
publishStatus = PublishStatusUpdate
|
||||
} else {
|
||||
publishStatus = PublishStatusOnline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &StrategyItem{
|
||||
Id: s.Id,
|
||||
Name: s.Name,
|
||||
Priority: s.Priority,
|
||||
Desc: s.Desc,
|
||||
Filters: filters,
|
||||
Updater: auto.UUID(s.Updater),
|
||||
UpdateTime: auto.TimeLabel(s.UpdateAt),
|
||||
ProcessedTotal: processedTotal,
|
||||
PublishStatus: publishStatus,
|
||||
IsStop: s.IsStop,
|
||||
IsDelete: s.IsDelete,
|
||||
}
|
||||
}
|
||||
|
||||
func ToStrategy(s *strategy.Strategy) *Strategy {
|
||||
filters := make([]*Filter, 0)
|
||||
json.Unmarshal([]byte(s.Filters), &filters)
|
||||
var cfg interface{}
|
||||
json.Unmarshal([]byte(s.Config), &cfg)
|
||||
return &Strategy{
|
||||
Id: s.Id,
|
||||
Name: s.Name,
|
||||
Priority: s.Priority,
|
||||
Desc: s.Desc,
|
||||
Filters: filters,
|
||||
Config: cfg,
|
||||
IsDelete: s.IsDelete || s.IsStop,
|
||||
}
|
||||
}
|
||||
|
||||
type Strategy struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Priority int `json:"priority"`
|
||||
Desc string `json:"desc"`
|
||||
Filters []*Filter `json:"filters"`
|
||||
Config interface{} `json:"config"`
|
||||
IsDelete bool `json:"is_delete"`
|
||||
}
|
||||
|
||||
type StrategyItem struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Priority int `json:"priority"`
|
||||
Desc string `json:"desc"`
|
||||
Filters string `json:"filters"`
|
||||
Updater auto.Label `json:"updater" aolabel:"user"`
|
||||
UpdateTime auto.TimeLabel `json:"update_time"`
|
||||
ProcessedTotal int64 `json:"processed_total"`
|
||||
PublishStatus string `json:"publish_status"`
|
||||
IsStop bool `json:"is_stop"`
|
||||
IsDelete bool `json:"is_delete"`
|
||||
}
|
||||
|
||||
type FilterOption struct {
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title"`
|
||||
Type string `json:"type"`
|
||||
Pattern string `json:"pattern"`
|
||||
Options []string `json:"options"`
|
||||
}
|
||||
|
||||
type Title struct {
|
||||
Field string `json:"field"`
|
||||
Title string `json:"title" aoi18n:""`
|
||||
}
|
||||
|
||||
type ToPublishItem struct {
|
||||
Name string `json:"name"`
|
||||
Priority int `json:"priority"`
|
||||
Status string `json:"status"`
|
||||
OptTime time.Time `json:"opt_time"`
|
||||
}
|
||||
|
||||
type LogItem struct {
|
||||
ID string `json:"id"`
|
||||
Service auto.Label `json:"service" aolabel:"service"`
|
||||
Method string `json:"method"`
|
||||
Url string `json:"url"`
|
||||
RemoteIP string `json:"remote_ip"`
|
||||
Consumer auto.Label `json:"consumer" aolabel:"service"`
|
||||
Authorization auto.Label `json:"authorization" aolabel:"service_authorization"`
|
||||
RecordTime auto.TimeLabel `json:"record_time"`
|
||||
}
|
||||
|
||||
type LogInfo struct {
|
||||
ID string `json:"id"`
|
||||
ContentType string `json:"content_type"`
|
||||
ProxyResponseBody string `json:"origin"`
|
||||
ResponseBody string `json:"target"`
|
||||
}
|
||||
@@ -1,394 +0,0 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/service"
|
||||
|
||||
"github.com/eolinker/go-common/auto"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/cluster"
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
"github.com/eolinker/eosc"
|
||||
|
||||
log2 "github.com/APIParkLab/APIPark/service/log"
|
||||
"github.com/eolinker/eosc/log"
|
||||
"gorm.io/gorm"
|
||||
|
||||
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
|
||||
|
||||
"github.com/eolinker/go-common/store"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
strategy_driver "github.com/APIParkLab/APIPark/module/strategy/driver"
|
||||
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/strategy"
|
||||
)
|
||||
|
||||
var _ IStrategyModule = (*imlStrategyModule)(nil)
|
||||
|
||||
type imlStrategyModule struct {
|
||||
strategyService strategy.IStrategyService `autowired:""`
|
||||
appService service.IServiceService `autowired:""`
|
||||
logService log2.ILogService `autowired:""`
|
||||
clusterService cluster.IClusterService `autowired:""`
|
||||
transaction store.ITransaction `autowired:""`
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) StrategyLogInfo(ctx context.Context, id string) (*strategy_dto.LogInfo, error) {
|
||||
c, err := i.clusterService.Get(ctx, cluster.DefaultClusterID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cluster %s not found", cluster.DefaultClusterID)
|
||||
}
|
||||
|
||||
info, err := i.logService.LogInfo(ctx, "loki", c.Cluster, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &strategy_dto.LogInfo{
|
||||
ID: info.ID,
|
||||
ContentType: info.ContentType,
|
||||
ProxyResponseBody: info.ProxyResponseBody,
|
||||
ResponseBody: info.ResponseBody,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) GetStrategyLogs(ctx context.Context, keyword string, strategyID string, start time.Time, end time.Time, limit int64, offset int64) ([]*strategy_dto.LogItem, int64, error) {
|
||||
if strategyID == "" {
|
||||
return nil, 0, errors.New("strategy id required")
|
||||
}
|
||||
conditions := map[string]string{
|
||||
"strategy": strategyID,
|
||||
}
|
||||
if keyword != "" {
|
||||
// 查询符合条件的应用ID
|
||||
apps, err := i.appService.Search(ctx, keyword, map[string]interface{}{
|
||||
"as_app": true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
orCondition := fmt.Sprintf("request_uri =~ \".*%s.*\"", keyword)
|
||||
if len(apps) > 0 {
|
||||
appIds := utils.SliceToSlice(apps, func(a *service.Service) string { return a.Id })
|
||||
orCondition = fmt.Sprintf("%s or application =~ \"%s\"", orCondition, strings.Join(appIds, "|"))
|
||||
}
|
||||
conditions["#1"] = orCondition
|
||||
}
|
||||
|
||||
c, err := i.clusterService.Get(ctx, cluster.DefaultClusterID)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("cluster %s not found", cluster.DefaultClusterID)
|
||||
}
|
||||
items, total, err := i.logService.Logs(ctx, "loki", c.Cluster, conditions, start, end, limit, offset)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
result := make([]*strategy_dto.LogItem, 0, len(items))
|
||||
for _, item := range items {
|
||||
result = append(result, &strategy_dto.LogItem{
|
||||
ID: item.ID,
|
||||
Service: auto.UUID(item.Service),
|
||||
Method: item.Method,
|
||||
Url: item.Url,
|
||||
RemoteIP: item.RemoteIP,
|
||||
Consumer: auto.UUID(item.Consumer),
|
||||
Authorization: auto.UUID(item.Authorization),
|
||||
RecordTime: auto.TimeLabel(item.RecordTime),
|
||||
})
|
||||
}
|
||||
return result, total, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Restore(ctx context.Context, id string) error {
|
||||
return i.strategyService.Restore(ctx, id)
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) DeleteServiceStrategy(ctx context.Context, serviceId string, id string) error {
|
||||
_, err := i.strategyService.LatestStrategyCommit(ctx, strategy_dto.ScopeService, serviceId, id)
|
||||
if err != nil {
|
||||
// 判断是否已经发布,如果未发布则直接删除
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return err
|
||||
}
|
||||
return i.strategyService.Delete(ctx, id)
|
||||
}
|
||||
return i.strategyService.SortDelete(ctx, id)
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) ToPublish(ctx context.Context, driver string) ([]*strategy_dto.ToPublishItem, error) {
|
||||
scope := strategy_dto.ToScope(strategy_dto.ScopeGlobal)
|
||||
list, err := i.strategyService.SearchAllByDriver(ctx, "", driver, scope.Int(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
strategyIds := utils.SliceToSlice(list, func(l *strategy.Strategy) string { return l.Id })
|
||||
commits, err := i.strategyService.ListLatestStrategyCommit(ctx, scope.String(), "", strategyIds...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
commitMap := utils.SliceToMapO(commits, func(c *commit.Commit[strategy.Commit]) (string, string) { return c.Data.Id, c.Data.Version })
|
||||
items := make([]*strategy_dto.ToPublishItem, 0, len(list))
|
||||
for _, l := range list {
|
||||
status := strategy_dto.StrategyStatus(l, commitMap[l.Id])
|
||||
if status == strategy_dto.PublishStatusOnline {
|
||||
continue
|
||||
}
|
||||
items = append(items, &strategy_dto.ToPublishItem{
|
||||
Name: l.Name,
|
||||
Priority: l.Priority,
|
||||
Status: status,
|
||||
OptTime: l.UpdateAt,
|
||||
})
|
||||
}
|
||||
sort.Slice(items, func(i, j int) bool {
|
||||
return items[i].Priority < items[j].Priority
|
||||
})
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Search(ctx context.Context, keyword string, driver string, scope strategy_dto.Scope, target string, page int, pageSize int, filters []string, order ...string) ([]*strategy_dto.StrategyItem, int64, error) {
|
||||
list, total, err := i.strategyService.SearchByDriver(ctx, keyword, driver, scope.Int(), target, page, pageSize, filters, order...)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if len(list) < 1 {
|
||||
return nil, 0, nil
|
||||
}
|
||||
strategyIds := utils.SliceToSlice(list, func(l *strategy.Strategy) string { return l.Id })
|
||||
commits, err := i.strategyService.ListLatestStrategyCommit(ctx, scope.String(), target, strategyIds...)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
commitMap := utils.SliceToMapO(commits, func(c *commit.Commit[strategy.Commit]) (string, string) { return c.Data.Id, c.Data.Version })
|
||||
items := make([]*strategy_dto.StrategyItem, 0, len(list))
|
||||
countMap := make(map[string]int64)
|
||||
c, err := i.clusterService.Get(ctx, cluster.DefaultClusterID)
|
||||
if err == nil {
|
||||
countMap, err = i.logService.LogCount(ctx, "loki", c.Cluster, map[string]string{
|
||||
"#1": fmt.Sprintf("strategy =~ \"%s\"", strings.Join(strategyIds, "|")),
|
||||
}, 720,
|
||||
"strategy")
|
||||
if err != nil {
|
||||
log.Errorf("get log count error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, l := range list {
|
||||
fs := make([]*strategy_dto.Filter, 0)
|
||||
|
||||
json.Unmarshal([]byte(l.Filters), &fs)
|
||||
filterList := make([]string, 0, len(fs))
|
||||
for _, f := range fs {
|
||||
info, err := strategy_filter.FilterLabel(f.Name, f.Values)
|
||||
if err != nil {
|
||||
log.Errorf("get filter label error: %v", err)
|
||||
continue
|
||||
}
|
||||
filterList = append(filterList, fmt.Sprintf("[%s:%s]", info.Title, info.Label))
|
||||
}
|
||||
item := strategy_dto.ToStrategyItem(l, commitMap[l.Id], strings.Join(filterList, ";"), countMap[l.Id])
|
||||
items = append(items, item)
|
||||
}
|
||||
sort.Slice(items, func(i, j int) bool {
|
||||
return items[i].Priority < items[j].Priority
|
||||
})
|
||||
return items, total, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Get(ctx context.Context, id string) (*strategy_dto.Strategy, error) {
|
||||
info, err := i.strategyService.Get(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := strategy_dto.ToStrategy(info)
|
||||
for _, f := range s.Filters {
|
||||
ff, has := strategy_filter.FilterGet(f.Name)
|
||||
if !has {
|
||||
return nil, fmt.Errorf("filter not found: %s", f.Name)
|
||||
}
|
||||
f.Title = ff.Title()
|
||||
f.Type = ff.Type()
|
||||
f.Label = strings.Join(ff.Labels(f.Values...), ",")
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Create(ctx context.Context, input *strategy_dto.Create) error {
|
||||
if input.Name == "" {
|
||||
return fmt.Errorf("name required")
|
||||
}
|
||||
if input.ID == "" {
|
||||
input.ID = uuid.NewString()
|
||||
}
|
||||
|
||||
if input.Priority < 1 {
|
||||
input.Priority = 1000
|
||||
}
|
||||
err := strategy_filter.CheckFilters(input.Driver, input.Scope, input.Filters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = strategy_driver.CheckConfig(input.Driver, input.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
filters, _ := json.Marshal(input.Filters)
|
||||
cfg, _ := json.Marshal(input.Config)
|
||||
return i.strategyService.Create(ctx, &strategy.Create{
|
||||
Id: input.ID,
|
||||
Name: input.Name,
|
||||
Priority: input.Priority,
|
||||
Desc: input.Desc,
|
||||
Filters: string(filters),
|
||||
Config: string(cfg),
|
||||
Scope: input.Scope.Int(),
|
||||
Target: input.Target,
|
||||
Driver: input.Driver,
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Edit(ctx context.Context, id string, input *strategy_dto.Edit) error {
|
||||
if input.Name != nil && *input.Name == "" {
|
||||
return fmt.Errorf("name required")
|
||||
}
|
||||
info, err := i.strategyService.Get(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if input.Priority != nil && *input.Priority < 1 {
|
||||
*input.Priority = 1000
|
||||
}
|
||||
filters := info.Filters
|
||||
if input.Filters != nil {
|
||||
err = strategy_filter.CheckFilters(info.Driver, strategy_dto.Scope(info.Scope), *input.Filters)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, _ := json.Marshal(input.Filters)
|
||||
filters = string(data)
|
||||
}
|
||||
cfg := info.Config
|
||||
if input.Config != nil {
|
||||
err = strategy_driver.CheckConfig(info.Driver, input.Config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, _ := json.Marshal(input.Config)
|
||||
cfg = string(data)
|
||||
}
|
||||
|
||||
return i.strategyService.Save(ctx, id, &strategy.Edit{
|
||||
Name: input.Name,
|
||||
Priority: input.Priority,
|
||||
Desc: input.Desc,
|
||||
Filters: &filters,
|
||||
Config: &cfg,
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Enable(ctx context.Context, id string) error {
|
||||
stop := false
|
||||
return i.strategyService.Save(ctx, id, &strategy.Edit{IsStop: &stop})
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Disable(ctx context.Context, id string) error {
|
||||
stop := true
|
||||
return i.strategyService.Save(ctx, id, &strategy.Edit{IsStop: &stop})
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Publish(ctx context.Context, driver string, scope string, target string) error {
|
||||
d, has := strategy_driver.GetDriver(driver)
|
||||
if !has {
|
||||
return fmt.Errorf("driver not found: %s", driver)
|
||||
}
|
||||
list, err := i.strategyService.AllByDriver(ctx, driver, strategy_dto.ToScope(scope).Int(), target)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||
publishStrategies := make([]*eosc.Base[gateway.StrategyRelease], 0, len(list))
|
||||
for _, l := range list {
|
||||
if l.IsDelete {
|
||||
err = i.strategyService.Delete(ctx, l.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
publishStrategies = append(publishStrategies, d.ToRelease(strategy_dto.ToStrategy(l), nil, 5000))
|
||||
|
||||
err = i.strategyService.CommitStrategy(txCtx, scope, target, l.Id, l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
client, err := i.clusterService.GatewayClient(ctx, cluster.DefaultClusterID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = client.Close(ctx)
|
||||
}()
|
||||
return client.Strategy().Online(ctx, publishStrategies...)
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) Delete(ctx context.Context, id string) error {
|
||||
_, err := i.strategyService.LatestStrategyCommit(ctx, strategy_dto.ScopeGlobal, "", id)
|
||||
if err != nil {
|
||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return i.strategyService.Delete(ctx, id)
|
||||
}
|
||||
return i.strategyService.SortDelete(ctx, id)
|
||||
}
|
||||
|
||||
func (i *imlStrategyModule) initGateway(ctx context.Context, clusterId string, clientDriver gateway.IClientDriver) error {
|
||||
commits, err := i.strategyService.ListLatestStrategyCommit(ctx, strategy_dto.ScopeGlobal, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
publishStrategies := make([]*eosc.Base[gateway.StrategyRelease], 0, len(commits))
|
||||
for _, c := range commits {
|
||||
l := c.Data
|
||||
if l.IsDelete {
|
||||
err = i.strategyService.Delete(ctx, l.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
d, has := strategy_driver.GetDriver(l.Driver)
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
publishStrategies = append(publishStrategies, d.ToRelease(strategy_dto.ToStrategy(&strategy.Strategy{
|
||||
Id: l.Id,
|
||||
Name: l.Name,
|
||||
Priority: l.Priority,
|
||||
Filters: l.Filters,
|
||||
Config: l.Config,
|
||||
Driver: l.Driver,
|
||||
IsStop: l.IsStop,
|
||||
IsDelete: l.IsDelete,
|
||||
}), nil, 5000))
|
||||
}
|
||||
|
||||
return clientDriver.Strategy().Online(ctx, publishStrategies...)
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/gateway"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
|
||||
_ "github.com/APIParkLab/APIPark/module/strategy/driver/data-masking"
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
)
|
||||
|
||||
type IStrategyModule interface {
|
||||
Search(ctx context.Context, keyword string, driver string, scope strategy_dto.Scope, target string, page int, pageSize int, filters []string, order ...string) ([]*strategy_dto.StrategyItem, int64, error)
|
||||
Get(ctx context.Context, id string) (*strategy_dto.Strategy, error)
|
||||
Create(ctx context.Context, i *strategy_dto.Create) error
|
||||
Edit(ctx context.Context, id string, i *strategy_dto.Edit) error
|
||||
Enable(ctx context.Context, id string) error
|
||||
Disable(ctx context.Context, id string) error
|
||||
Publish(ctx context.Context, driver string, scope string, target string) error
|
||||
Delete(ctx context.Context, id string) error
|
||||
ToPublish(ctx context.Context, driver string) ([]*strategy_dto.ToPublishItem, error)
|
||||
Restore(ctx context.Context, id string) error
|
||||
|
||||
DeleteServiceStrategy(ctx context.Context, serviceId string, id string) error
|
||||
|
||||
StrategyLogInfo(ctx context.Context, id string) (*strategy_dto.LogInfo, error)
|
||||
GetStrategyLogs(ctx context.Context, keyword string, strategyID string, start time.Time, end time.Time, limit int64, offset int64) ([]*strategy_dto.LogItem, int64, error)
|
||||
}
|
||||
|
||||
func init() {
|
||||
strategyModule := new(imlStrategyModule)
|
||||
autowire.Auto[IStrategyModule](func() reflect.Value {
|
||||
gateway.RegisterInitHandleFunc(strategyModule.initGateway)
|
||||
return reflect.ValueOf(strategyModule)
|
||||
})
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
type InputSetting struct {
|
||||
InvokeAddress string `json:"invoke_address" key:"system.node.invoke_address"`
|
||||
SitePrefix string `json:"site_prefix" key:"system.setting.site_prefix"`
|
||||
}
|
||||
|
||||
func (i *InputSetting) Validate() error {
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
|
||||
type Setting struct {
|
||||
InvokeAddress string `json:"invoke_address" key:"system.node.invoke_address"`
|
||||
SitePrefix string `json:"site_prefix" key:"system.setting.site_prefix"`
|
||||
}
|
||||
|
||||
func MapStringToStruct[T any](m map[string]string) *T {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
@@ -35,7 +34,7 @@ type imlUpstreamModule struct {
|
||||
}
|
||||
|
||||
func (i *imlUpstreamModule) ExportAll(ctx context.Context) ([]*upstream_dto.ExportUpstream, error) {
|
||||
latestCommits, err := i.upstreamService.ListLatestCommit(ctx, cluster.DefaultClusterID)
|
||||
latestCommits, err := i.upstreamService.ListLatestCommit(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ func (p *plugin) aiAPIs() []pm3.Api {
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/ai/providers", []string{"context"}, []string{"providers"}, p.aiProviderController.SimpleProviders),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/provider/config", []string{"context", "query:provider"}, []string{"provider"}, p.aiProviderController.Provider, access.SystemSettingsAiProviderView),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/ai/provider/llms", []string{"context", "query:provider"}, []string{"llms", "provider"}, p.aiProviderController.LLMs),
|
||||
//pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/enable", []string{"context", "query:provider"}, nil, p.aiProviderController.isStop),
|
||||
//pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/enable", []string{"context", "query:provider"}, nil, p.aiProviderController.Enable),
|
||||
//pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/disable", []string{"context", "query:provider"}, nil, p.aiProviderController.Disable),
|
||||
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/config", []string{"context", "query:provider", "body"}, nil, p.aiProviderController.UpdateProviderConfig, access.SystemSettingsAiProviderManager),
|
||||
//pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/ai/provider/default-llm", []string{"context", "query:provider", "body"}, nil, p.aiProviderController.UpdateProviderDefaultLLM),
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
func (p *plugin) apiApis() []pm3.Api {
|
||||
return []pm3.Api{
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/simple/service/apis", []string{"context", "body"}, []string{"apis"}, p.routerController.Simple),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/routers", []string{"context", "query:keyword", "query:service"}, []string{"routers"}, p.routerController.Search, access.SystemWorkspaceServiceViewAll, access.TeamServiceApiView),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/router/detail", []string{"context", "query:service", "query:router"}, []string{"router"}, p.routerController.Detail, access.SystemWorkspaceServiceViewAll, access.TeamServiceApiView),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/service/router", []string{"context", "query:service", "body"}, []string{"router"}, p.routerController.Create, access.SystemWorkspaceServiceManagerAll, access.TeamServiceApiManager),
|
||||
|
||||
@@ -3,10 +3,6 @@ package core
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/APIParkLab/APIPark/controller/log"
|
||||
|
||||
"github.com/APIParkLab/APIPark/controller/strategy"
|
||||
|
||||
"github.com/APIParkLab/APIPark/controller/ai"
|
||||
ai_api "github.com/APIParkLab/APIPark/controller/ai-api"
|
||||
"github.com/APIParkLab/APIPark/controller/monitor"
|
||||
@@ -76,7 +72,6 @@ type plugin struct {
|
||||
aiAPIController ai_api.IAPIController `autowired:""`
|
||||
apiDocController router.IAPIDocController `autowired:""`
|
||||
subscribeController subscribe.ISubscribeController `autowired:""`
|
||||
strategyController strategy.IStrategyController `autowired:""`
|
||||
appAuthorizationController application_authorization.IAuthorizationController `autowired:""`
|
||||
releaseController release.IReleaseController `autowired:""`
|
||||
roleController role.IRoleController `autowired:""`
|
||||
@@ -89,7 +84,6 @@ type plugin struct {
|
||||
aiProviderController ai.IProviderController `autowired:""`
|
||||
settingController system.ISettingController `autowired:""`
|
||||
initController system.IInitController `autowired:""`
|
||||
logController log.ILogController `autowired:""`
|
||||
apis []pm3.Api
|
||||
}
|
||||
|
||||
@@ -111,8 +105,6 @@ func (p *plugin) OnComplete() {
|
||||
p.apis = append(p.apis, p.commonApis()...)
|
||||
p.apis = append(p.apis, p.systemApis()...)
|
||||
p.apis = append(p.apis, p.aiAPIs()...)
|
||||
p.apis = append(p.apis, p.strategyApis()...)
|
||||
p.apis = append(p.apis, p.logApis()...)
|
||||
}
|
||||
|
||||
func (p *plugin) Name() string {
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/eolinker/go-common/pm3"
|
||||
)
|
||||
|
||||
func (p *plugin) logApis() []pm3.Api {
|
||||
return []pm3.Api{
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/log/:driver", []string{"context", "rest:driver"}, []string{"info"}, p.logController.Get),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/log/:driver", []string{"context", "rest:driver", "body"}, nil, p.logController.Save),
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,5 @@ func (p *plugin) monitorStatisticApis() []pm3.Api {
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/monitor/config", []string{"context", "body"}, []string{"info"}, p.monitorConfigController.SaveMonitorConfig, access.SystemSettingsDataSourceManager),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/monitor/config", []string{"context"}, []string{"info"}, p.monitorConfigController.GetMonitorConfig, access.SystemSettingsDataSourceView),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/monitor/clusters", []string{"context"}, []string{"clusters"}, p.monitorConfigController.GetMonitorCluster),
|
||||
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/monitor/:data_type", []string{"context", "rest:data_type", "body"}, []string{"statistics"}, p.monitorStatisticController.Statistics),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/monitor/:data_type/trend", []string{"context", "rest:data_type", "query:id", "body"}, []string{"tendency", "time_interval"}, p.monitorStatisticController.InvokeTrend),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/monitor/:data_type/trend/:typ", []string{"context", "rest:data_type", "rest:typ", "query:api", "query:provider", "query:subscriber", "body"}, []string{"tendency", "time_interval"}, p.monitorStatisticController.InvokeTrendInner),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/monitor/:data_type/statistics/:typ", []string{"context", "rest:data_type", "rest:typ", "query:id", "body"}, []string{"statistics"}, p.monitorStatisticController.StatisticsInner),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,14 +3,11 @@ package core
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/eolinker/go-common/ignore"
|
||||
|
||||
"github.com/APIParkLab/APIPark/resources/access"
|
||||
"github.com/eolinker/go-common/pm3"
|
||||
)
|
||||
|
||||
func (p *plugin) ServiceApis() []pm3.Api {
|
||||
ignore.IgnorePath("login", http.MethodGet, "/api/v1/service/swagger/:id")
|
||||
return []pm3.Api{
|
||||
// 项目
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/info", []string{"context", "query:service"}, []string{"service"}, p.serviceController.Get, access.SystemWorkspaceServiceViewAll, access.TeamTeamServiceView),
|
||||
@@ -18,8 +15,6 @@ func (p *plugin) ServiceApis() []pm3.Api {
|
||||
pm3.CreateApiWidthDoc(http.MethodDelete, "/api/v1/service/info", []string{"context", "query:service"}, nil, p.serviceController.Delete, access.SystemWorkspaceServiceManagerAll, access.TeamTeamServiceManager),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/my_services", []string{"context", "query:team", "query:keyword"}, []string{"services"}, p.serviceController.SearchMyServices),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/services", []string{"context", "query:team", "query:keyword"}, []string{"services"}, p.serviceController.Search, access.SystemWorkspaceServiceViewAll, access.TeamTeamServiceView),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/services", []string{"context"}, []string{"services"}, p.serviceController.Simple),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/simple/services/mine", []string{"context"}, []string{"services"}, p.serviceController.MySimple),
|
||||
// 应用相关
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/app/info", []string{"context", "query:app"}, []string{"app"}, p.appController.GetApp, access.SystemWorkspaceApplicationViewAll, access.TeamTeamConsumerView),
|
||||
pm3.CreateApiWidthDoc(http.MethodDelete, "/api/v1/app", []string{"context", "query:app"}, nil, p.appController.DeleteApp, access.SystemWorkspaceApplicationManagerAll, access.TeamTeamConsumerManager),
|
||||
@@ -32,7 +27,5 @@ func (p *plugin) ServiceApis() []pm3.Api {
|
||||
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/service/doc", []string{"context", "query:service"}, []string{"doc"}, p.serviceController.ServiceDoc, access.SystemWorkspaceServiceViewAll, access.TeamServiceServiceIntroView),
|
||||
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/service/doc", []string{"context", "query:service", "body"}, nil, p.serviceController.SaveServiceDoc, access.SystemWorkspaceServiceManagerAll, access.TeamServiceServiceIntroManager),
|
||||
pm3.CreateApiSimple(http.MethodGet, "/api/v1/service/swagger/:id", p.serviceController.Swagger),
|
||||
pm3.CreateApiSimple(http.MethodGet, "/api/v1/export/openapi/:id", p.serviceController.ExportSwagger),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/eolinker/go-common/pm3"
|
||||
)
|
||||
|
||||
func (p *plugin) strategyApis() []pm3.Api {
|
||||
return []pm3.Api{
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/global/:driver/list", []string{"context", "query:keyword", "rest:driver", "query:page", "query:page_size", "query:order", "query:sort", "query:filters"}, []string{"list", "total"}, p.strategyController.GlobalStrategyList),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/global/:driver", []string{"context", "query:strategy"}, []string{"strategy"}, p.strategyController.GetStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/strategy/global/:driver", []string{"context", "rest:driver", "body"}, nil, p.strategyController.CreateGlobalStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/strategy/global/:driver", []string{"context", "query:strategy", "body"}, nil, p.strategyController.EditStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodDelete, "/api/v1/strategy/global/:driver", []string{"context", "query:strategy"}, nil, p.strategyController.DeleteStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPatch, "/api/v1/strategy/global/:driver/enable", []string{"context", "query:strategy"}, nil, p.strategyController.EnableStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPatch, "/api/v1/strategy/global/:driver/disable", []string{"context", "query:strategy"}, nil, p.strategyController.DisableStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/strategy/global/:driver/publish", []string{"context", "rest:driver"}, nil, p.strategyController.PublishGlobalStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPatch, "/api/v1/strategy/global/:driver/restore", []string{"context", "query:strategy"}, nil, p.strategyController.Restore),
|
||||
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/service/:driver/list", []string{"context", "query:keyword", "query:service", "rest:driver", "query:page", "query:page_size", "query:order", "query:sort", "query:filters"}, []string{"list", "total"}, p.strategyController.ServiceStrategyList),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/service/:driver", []string{"context", "query:strategy"}, []string{"strategy"}, p.strategyController.GetStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPost, "/api/v1/strategy/service/:driver", []string{"context", "query:service", "rest:driver", "body"}, nil, p.strategyController.CreateServiceStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPut, "/api/v1/strategy/service/:driver", []string{"context", "query:strategy", "body"}, nil, p.strategyController.EditStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPatch, "/api/v1/strategy/service/:driver/enable", []string{"context", "query:strategy"}, nil, p.strategyController.EnableStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPatch, "/api/v1/strategy/service/:driver/disable", []string{"context", "query:strategy"}, nil, p.strategyController.DisableStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodDelete, "/api/v1/strategy/service/:driver", []string{"context", "query:service", "query:strategy"}, nil, p.strategyController.DeleteServiceStrategy),
|
||||
pm3.CreateApiWidthDoc(http.MethodPatch, "/api/v1/strategy/service/:driver/restore", []string{"context", "query:strategy"}, nil, p.strategyController.Restore),
|
||||
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/global/filter-options", []string{"context"}, []string{"options"}, p.strategyController.FilterGlobalOptions),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/service/filter-options", []string{"context"}, []string{"options"}, p.strategyController.FilterServiceOptions),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/filter-remote/:name", []string{"context", "rest:name"}, []string{"titles", "list", "total", "key", "value"}, p.strategyController.FilterGlobalRemote),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/service/filter-remote/:name", []string{"context", "query:service", "rest:name"}, []string{"titles", "list", "total", "key", "value"}, p.strategyController.FilterServiceRemote),
|
||||
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/global/:driver/to-publishs", []string{"context", "rest:driver"}, []string{"strategies", "source", "version_name", "is_publish"}, p.strategyController.ToPublish),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/global/:driver/logs", []string{"context", "query:keyword", "query:strategy", "query:begin", "query:end", "query:page_size", "query:page"}, []string{"logs", "total"}, p.strategyController.GetStrategyLogs),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/service/:driver/logs", []string{"context", "query:keyword", "query:strategy", "query:begin", "query:end", "query:page_size", "query:page"}, []string{"logs", "total"}, p.strategyController.GetStrategyLogs),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/global/:driver/log", []string{"context", "query:log"}, []string{"log"}, p.strategyController.LogInfo),
|
||||
pm3.CreateApiWidthDoc(http.MethodGet, "/api/v1/strategy/service/:driver/log", []string{"context", "query:log"}, []string{"log"}, p.strategyController.LogInfo),
|
||||
}
|
||||
}
|
||||
@@ -131,16 +131,6 @@ system:
|
||||
value: 'manager'
|
||||
dependents:
|
||||
- system.settings.log_configuration.view
|
||||
- name: global strategy
|
||||
value: "strategy"
|
||||
children:
|
||||
- name: view
|
||||
value: 'view'
|
||||
guest_allow: true
|
||||
- name: manager
|
||||
value: 'manager'
|
||||
dependents:
|
||||
- system.settings.strategy.view
|
||||
team:
|
||||
- name: service
|
||||
value: 'service'
|
||||
@@ -207,16 +197,6 @@ team:
|
||||
value: 'manager'
|
||||
dependents:
|
||||
- team.service.subscription.view
|
||||
- name: service strategy
|
||||
value: 'strategy'
|
||||
children:
|
||||
- name: view
|
||||
value: 'view'
|
||||
guest_allow: true
|
||||
- name: manager
|
||||
value: 'manager'
|
||||
dependents:
|
||||
- team.service.strategy.view
|
||||
- name: consumer
|
||||
value: 'consumer'
|
||||
children:
|
||||
|
||||
@@ -19,8 +19,6 @@ system:
|
||||
- system.settings.role.view
|
||||
- system.settings.ssl_certificate.manager
|
||||
- system.settings.ssl_certificate.view
|
||||
- system.settings.strategy.view
|
||||
- system.settings.strategy.manager
|
||||
- system.workspace.application.manager_all
|
||||
- system.workspace.application.view_all
|
||||
- system.workspace.service.manager_all
|
||||
@@ -51,8 +49,6 @@ system:
|
||||
- system.settings.log_configuration.view
|
||||
- system.settings.ssl_certificate.manager
|
||||
- system.settings.ssl_certificate.view
|
||||
- system.settings.strategy.view
|
||||
- system.settings.strategy.manager
|
||||
- system.workspace.application.view_all
|
||||
- system.workspace.service.view_all
|
||||
- system.workspace.team.view_all
|
||||
@@ -79,8 +75,6 @@ team:
|
||||
- team.service.release.view
|
||||
- team.service.service_intro.manager
|
||||
- team.service.service_intro.view
|
||||
- team.service.strategy.view
|
||||
- team.service.strategy.manager
|
||||
- team.service.subscription.manager
|
||||
- team.service.subscription.view
|
||||
- team.service.upstream.manager
|
||||
@@ -105,8 +99,6 @@ team:
|
||||
- team.service.release.view
|
||||
- team.service.service_intro.manager
|
||||
- team.service.service_intro.view
|
||||
- team.service.strategy.view
|
||||
- team.service.strategy.manager
|
||||
- team.service.subscription.manager
|
||||
- team.service.subscription.view
|
||||
- team.service.upstream.manager
|
||||
@@ -128,7 +120,7 @@ team:
|
||||
- team.service.service.manager
|
||||
- team.service.service_intro.manager
|
||||
- team.service.service_intro.view
|
||||
- team.service.strategy.view
|
||||
- team.service.subscription.manager
|
||||
- team.service.subscription.view
|
||||
- team.service.upstream.manager
|
||||
- team.service.upstream.view
|
||||
|
||||
@@ -5,19 +5,12 @@
|
||||
"api": "API",
|
||||
"api doc": "API Documentation",
|
||||
"api gateway": "API Gateway",
|
||||
"api method": "API Request Method",
|
||||
"api name": "API Name",
|
||||
"api path": "API Path",
|
||||
"all consumer": "All Consumers",
|
||||
"all method": "All Methods",
|
||||
"api portal": "API Portal",
|
||||
"authorization": "Authorization",
|
||||
"authorization": "Access Authorization",
|
||||
"consumer": "Consumer",
|
||||
"consumer id": "Consumer ID",
|
||||
"consumer admin": "Consumer Admin",
|
||||
"consumer developer": "Consumer Developer",
|
||||
"create": "Create",
|
||||
"description": "Description",
|
||||
"data source": "Data Source",
|
||||
"devops admin": "DevOps Admin",
|
||||
"general": "General Settings",
|
||||
@@ -29,7 +22,7 @@
|
||||
"member": "Member",
|
||||
"release": "Release",
|
||||
"role": "Role",
|
||||
"run view": "Runtime View",
|
||||
"run view": "Run View",
|
||||
"service": "Service",
|
||||
"service admin": "Service Admin",
|
||||
"service developer": "Service Developer",
|
||||
@@ -49,7 +42,5 @@
|
||||
"view all service": "View All Services",
|
||||
"view all team": "View All Teams",
|
||||
"view subscribed services": "View Subscribed Services",
|
||||
"workspace": "Workspace",
|
||||
"request path": "Request Path",
|
||||
"methods": "Request Methods"
|
||||
"workspace": "Workspace"
|
||||
}
|
||||
|
||||
@@ -5,38 +5,31 @@
|
||||
"api": "API",
|
||||
"api doc": "APIドキュメント",
|
||||
"api gateway": "APIゲートウェイ",
|
||||
"api method": "APIリクエストメソッド",
|
||||
"api name": "API名",
|
||||
"api path": "APIパス",
|
||||
"all consumer": "全てのコンシューマー",
|
||||
"all method": "全てのリクエスト方式",
|
||||
"api portal": "APIポータル",
|
||||
"authorization": "認証",
|
||||
"consumer": "コンシューマー",
|
||||
"consumer id": "コンシューマーID",
|
||||
"consumer admin": "コンシューマー管理者",
|
||||
"consumer developer": "コンシューマーデベロッパー",
|
||||
"authorization": "アクセス許可",
|
||||
"consumer": "消費者",
|
||||
"consumer admin": "消費者管理者",
|
||||
"consumer developer": "消費者開発者",
|
||||
"create": "作成",
|
||||
"description": "説明",
|
||||
"data source": "データソース",
|
||||
"devops admin": "DevOps管理者",
|
||||
"general": "一般設定",
|
||||
"general member": "一般メンバー",
|
||||
"log configuration": "ログ設定",
|
||||
"manager": "管理者",
|
||||
"manager all consumer": "全てのコンシューマーを管理",
|
||||
"manager subscribed services": "購読済みサービスを管理",
|
||||
"manager all consumer": "すべての消費者を管理",
|
||||
"manager subscribed services": "購読したサービスを管理",
|
||||
"member": "メンバー",
|
||||
"release": "リリース",
|
||||
"role": "役割",
|
||||
"run view": "実行ビュー",
|
||||
"service": "サービス",
|
||||
"service admin": "サービス管理者",
|
||||
"service developer": "サービスデベロッパー",
|
||||
"service developer": "サービス開発者",
|
||||
"service intro": "サービスドキュメント",
|
||||
"ssl certificate": "SSL証明書",
|
||||
"allow subscribe service": "サービスの購読を許可",
|
||||
"subscription review": "購読審査",
|
||||
"subscription review": "購読レビュー",
|
||||
"subscription service": "購読サービス",
|
||||
"super admin": "スーパ管理者",
|
||||
"system settings": "システム設定",
|
||||
@@ -45,11 +38,9 @@
|
||||
"team admin": "チーム管理者",
|
||||
"upstream": "アップストリーム",
|
||||
"view": "表示",
|
||||
"view all consumer": "全てのコンシューマーを表示",
|
||||
"view all service": "全てのサービスを表示",
|
||||
"view all team": "全てのチームを表示",
|
||||
"view subscribed services": "購読済みサービスを表示",
|
||||
"workspace": "ワークスペース",
|
||||
"request path": "リクエストパス",
|
||||
"methods": "リクエスト方式"
|
||||
"view all consumer": "すべての消費者を表示",
|
||||
"view all service": "すべてのサービスを表示",
|
||||
"view all team": "すべてのチームを表示",
|
||||
"view subscribed services": "購読したサービスを表示",
|
||||
"workspace": "ワークスペース"
|
||||
}
|
||||
|
||||
@@ -5,19 +5,12 @@
|
||||
"api": "API",
|
||||
"api doc": "API文档",
|
||||
"api gateway": "API网关",
|
||||
"api method": "API请求方法",
|
||||
"api name": "API名称",
|
||||
"api path": "API路径",
|
||||
"all consumer": "所有消费者",
|
||||
"all method": "全部请求方式",
|
||||
"api portal": "API门户",
|
||||
"authorization": "访问授权",
|
||||
"consumer": "消费者",
|
||||
"consumer id": "消费者ID",
|
||||
"consumer admin": "消费者管理员",
|
||||
"consumer developer": "消费者开发者",
|
||||
"create": "创建",
|
||||
"description": "描述",
|
||||
"data source": "数据源",
|
||||
"devops admin": "运维管理员",
|
||||
"general": "常规设置",
|
||||
@@ -49,7 +42,5 @@
|
||||
"view all service": "查看所有服务",
|
||||
"view all team": "查看所有团队",
|
||||
"view subscribed services": "查看已经订阅的服务",
|
||||
"workspace": "工作空间",
|
||||
"request path": "请求路径",
|
||||
"methods": "请求方法"
|
||||
"workspace": "工作空间"
|
||||
}
|
||||
|
||||
@@ -1,55 +1,46 @@
|
||||
{
|
||||
"account": "帳號",
|
||||
"ai provider": "AI 模型供應商",
|
||||
"ai provider": "AI 供應商",
|
||||
"analysis": "分析報告",
|
||||
"api": "API",
|
||||
"api doc": "API 文件",
|
||||
"api gateway": "API 閘道",
|
||||
"api method": "API 請求方法",
|
||||
"api name": "API 名稱",
|
||||
"api path": "API 路徑",
|
||||
"all consumer": "所有消費者",
|
||||
"all method": "全部請求方式",
|
||||
"api portal": "API 門戶",
|
||||
"authorization": "訪問授權",
|
||||
"consumer": "消費者",
|
||||
"consumer id": "消費者 ID",
|
||||
"consumer admin": "消費者管理員",
|
||||
"consumer developer": "消費者開發者",
|
||||
"create": "創建",
|
||||
"description": "描述",
|
||||
"data source": "資料源",
|
||||
"devops admin": "運維管理員",
|
||||
"general": "常規設置",
|
||||
"general member": "普通成員",
|
||||
"log configuration": "日誌配置",
|
||||
"api portal": "API 入口網站",
|
||||
"authorization": "存取授權",
|
||||
"consumer": "使用者",
|
||||
"consumer admin": "使用者管理員",
|
||||
"consumer developer": "使用者開發人員",
|
||||
"create": "建立",
|
||||
"data source": "資料來源",
|
||||
"devops admin": "DevOps 管理員",
|
||||
"general": "一般設定",
|
||||
"general member": "一般成員",
|
||||
"log configuration": "日誌設定",
|
||||
"manager": "管理",
|
||||
"manager all consumer": "管理所有消費者",
|
||||
"manager all consumer": "管理所有使用者",
|
||||
"manager subscribed services": "管理已訂閱的服務",
|
||||
"member": "成員",
|
||||
"release": "發布",
|
||||
"release": "發佈",
|
||||
"role": "角色",
|
||||
"run view": "運行視圖",
|
||||
"run view": "執行檢視",
|
||||
"service": "服務",
|
||||
"service admin": "服務管理員",
|
||||
"service developer": "服務開發者",
|
||||
"service intro": "服務文檔",
|
||||
"ssl certificate": "SSL 證書",
|
||||
"service developer": "服務開發人員",
|
||||
"service intro": "服務說明文件",
|
||||
"ssl certificate": "SSL 憑證",
|
||||
"allow subscribe service": "允許訂閱服務",
|
||||
"subscription review": "訂閱審核",
|
||||
"subscription service": "訂閱服務",
|
||||
"super admin": "超級管理員",
|
||||
"system settings": "系統設置",
|
||||
"system settings": "系統設定",
|
||||
"team": "團隊",
|
||||
"team settings": "團隊設置",
|
||||
"team settings": "團隊設定",
|
||||
"team admin": "團隊管理員",
|
||||
"upstream": "上游",
|
||||
"view": "查看",
|
||||
"view all consumer": "查看所有消費者",
|
||||
"view all service": "查看所有服務",
|
||||
"view all team": "查看所有團隊",
|
||||
"view subscribed services": "查看已訂閱的服務",
|
||||
"workspace": "工作空間",
|
||||
"request path": "請求路徑",
|
||||
"methods": "請求方法"
|
||||
"view": "檢視",
|
||||
"view all consumer": "檢視所有使用者",
|
||||
"view all service": "檢視所有服務",
|
||||
"view all team": "檢視所有團隊",
|
||||
"view subscribed services": "檢視已訂閱的服務",
|
||||
"workspace": "工作區"
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user