mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-14 20:41:15 +08:00
Merge branch 'main' of http://gitlab.eolink.com/apipark/APIPark
This commit is contained in:
+1
-2
@@ -2,5 +2,4 @@
|
||||
/.idea/
|
||||
/config.yml
|
||||
/build/
|
||||
/apipark
|
||||
.gitlab-ci.yml
|
||||
/apipark
|
||||
@@ -0,0 +1,98 @@
|
||||
variables:
|
||||
PATH: /opt/go-1.21/go/bin/:/opt/node/node/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
|
||||
GOROOT: /opt/go-1.21/go
|
||||
GOPROXY: https://goproxy.cn
|
||||
VERSION: $CI_COMMIT_SHORT_SHA
|
||||
APP: apipark
|
||||
APP_PRE: ${APP}_${VERSION}
|
||||
BUILD_DIR: ${APP}-build
|
||||
DEPLOY_DESC: "DEV 环境"
|
||||
VIEW_ADDR: http://172.18.166.219:8288
|
||||
SAVE_DIR: /opt/${APP}
|
||||
NODE_OPTIONS: --max_old_space_size=8192
|
||||
|
||||
stages:
|
||||
- notice
|
||||
- prefix
|
||||
- build
|
||||
- deploy
|
||||
- webhook
|
||||
|
||||
feishu-informer: # 飞书回调
|
||||
stage: notice
|
||||
variables:
|
||||
DIFF_URL: "$CI_MERGE_REQUEST_PROJECT_URL/-/merge_requests/$CI_MERGE_REQUEST_IID/diffs"
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE=="merge_request_event" && $CI_COMMIT_BRANCH =~ "main"
|
||||
script:
|
||||
- echo "merge request"
|
||||
- |
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"项目:${CI_PROJECT_NAME}\\n提交人:${GITLAB_USER_NAME}\\n提交信息:${CI_MERGE_REQUEST_TITLE}\\n合并分支信息:${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} -> ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}\\n差异性地址:${DIFF_URL}\\n请及时review代码\"}}" \
|
||||
https://open.feishu.cn/open-apis/bot/v2/hook/1c334752-2874-41a1-8f1b-3060f2d46b6c
|
||||
|
||||
prebuild:
|
||||
stage: prefix
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
script:
|
||||
- echo "prebuild"
|
||||
- chmod +x ./scripts/prefix.sh
|
||||
- ./scripts/prefix.sh
|
||||
|
||||
builder:
|
||||
stage: build
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
script:
|
||||
- set -e
|
||||
- |
|
||||
if [ ! -d "../artifacts" ]; then
|
||||
mkdir -p ../artifacts
|
||||
fi
|
||||
if [ -d "../artifacts/dist" ]; then
|
||||
cp -r ../artifacts/dist frontend/dist
|
||||
fi
|
||||
- |
|
||||
if [ -n "$(git diff --name-status HEAD~1 HEAD -- frontend)" ]; then
|
||||
./scripts/build.sh $BUILD_DIR ${VERSION} all ""
|
||||
else
|
||||
./scripts/build.sh $BUILD_DIR ${VERSION}
|
||||
fi
|
||||
if [ -d "frontend/dist" ]; then
|
||||
echo "copy frontend/dist to artifacts/dist"
|
||||
rm -fr ../artifacts/dist
|
||||
cp -r frontend/dist ../artifacts/dist
|
||||
fi
|
||||
cp $BUILD_DIR/${APP_PRE}_linux_amd64.tar.gz ${SAVE_DIR}
|
||||
|
||||
deployer:
|
||||
stage: deploy
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
variables:
|
||||
APIPARK_GUEST_MODE: allow
|
||||
APIPARK_GUEST_ID: dklejrfbhjqwdh
|
||||
script:
|
||||
- cd ${SAVE_DIR};mkdir -p ${APP_PRE};tar -zxvf ${APP_PRE}_linux_amd64.tar.gz -C ${APP_PRE};cd ${APP_PRE};./install.sh ${SAVE_DIR};./run.sh restart;cd ${SAVE_DIR} && ./clean.sh ${APP_PRE}
|
||||
when: on_success
|
||||
success:
|
||||
stage: webhook
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
script:
|
||||
- |
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"最近一次提交:${CI_COMMIT_TITLE}\\n提交人:${GITLAB_USER_NAME}\\n项目:${CI_PROJECT_NAME}\\n环境:${DEPLOY_DESC}\\n更新部署完成.\\n访问地址:${VIEW_ADDR}\\n工作流地址:${CI_PIPELINE_URL}\"}}" \
|
||||
https://open.feishu.cn/open-apis/bot/v2/hook/c3672932-4dfa-4989-8023-0128bae59338
|
||||
when: on_success
|
||||
failure:
|
||||
stage: webhook
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH == "main"
|
||||
script:
|
||||
- |
|
||||
curl -X POST -H "Content-Type: application/json" \
|
||||
-d "{\"msg_type\":\"text\",\"content\":{\"text\":\"最近一次提交:${CI_COMMIT_TITLE}\\n提交人:${GITLAB_USER_NAME}\\n项目:${CI_PROJECT_NAME}\\n环境:${DEPLOY_DESC}\\n更新部署失败,请及时到gitlab上查看\\n工作流地址:${CI_PIPELINE_URL}\"}}" \
|
||||
https://open.feishu.cn/open-apis/bot/v2/hook/c3672932-4dfa-4989-8023-0128bae59338
|
||||
when: on_failure
|
||||
@@ -45,8 +45,8 @@ func (p *imlCluster) Check(ctx *gin.Context, input *cluster_dto.CheckCluster) ([
|
||||
// return id, nil
|
||||
//}
|
||||
//
|
||||
//func (p *imlCluster) Search(ctx *gin.Context, keyword string) ([]*parition_dto.Item, error) {
|
||||
// return p.module.Search(ctx, keyword)
|
||||
//func (p *imlCluster) SearchByDriver(ctx *gin.Context, keyword string) ([]*parition_dto.Item, error) {
|
||||
// return p.module.SearchByDriver(ctx, keyword)
|
||||
//}
|
||||
//
|
||||
//func (p *imlCluster) Simple(ctx *gin.Context) ([]*parition_dto.Simple, error) {
|
||||
|
||||
@@ -17,6 +17,70 @@ 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,7 +16,12 @@ 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)
|
||||
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)
|
||||
}
|
||||
|
||||
type IMonitorConfigController interface {
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
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)
|
||||
@@ -15,6 +16,10 @@ 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,10 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||
"reflect"
|
||||
|
||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
@@ -24,6 +25,7 @@ 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 {
|
||||
|
||||
+120
-27
@@ -7,6 +7,16 @@ 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"
|
||||
@@ -25,7 +35,6 @@ 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"
|
||||
@@ -42,29 +51,102 @@ 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:""`
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
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
|
||||
}
|
||||
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) {
|
||||
@@ -228,21 +310,12 @@ 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) {
|
||||
@@ -336,3 +409,23 @@ 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,12 +24,11 @@ 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)
|
||||
|
||||
//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)
|
||||
Swagger(ctx *gin.Context)
|
||||
ExportSwagger(ctx *gin.Context)
|
||||
}
|
||||
|
||||
type IAppController interface {
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
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)
|
||||
}
|
||||
|
||||
type IStrategyCommonController interface {
|
||||
}
|
||||
|
||||
func init() {
|
||||
autowire.Auto[IStrategyController](func() reflect.Value {
|
||||
return reflect.ValueOf(&imlStrategyController{})
|
||||
})
|
||||
}
|
||||
@@ -41,6 +41,7 @@ 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,6 +284,7 @@ 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,
|
||||
@@ -301,6 +302,7 @@ 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) Search(ctx context.Context, keyword string) ([]*paritiondto.Item, error) {
|
||||
// partitions, err := m.partitionService.Search(ctx, keyword, nil)
|
||||
//func (m *imlClusterModule) SearchByDriver(ctx context.Context, keyword string) ([]*paritiondto.Item, error) {
|
||||
// partitions, err := m.partitionService.SearchByDriver(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.Search(ctx, "")
|
||||
// //oDetails, err := m.organizationService.SearchByDriver(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.Search(ctx, "", nil)
|
||||
// pm, err := m.partitionService.SearchByDriver(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.Search(ctx, "", map[string]interface{}{
|
||||
// pm, err := m.partitionService.SearchByDriver(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.Search(ctx, "", nil)
|
||||
// pm, err := m.partitionService.SearchByDriver(ctx, "", nil)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
@@ -24,7 +24,7 @@ type CommonInput struct {
|
||||
|
||||
type StatisticInput struct {
|
||||
Apis []string `json:"apis"`
|
||||
Projects []string `json:"projects"`
|
||||
Services []string `json:"services"`
|
||||
Path string `json:"path"`
|
||||
*CommonInput
|
||||
}
|
||||
|
||||
@@ -21,12 +21,12 @@ type ApiStatisticBasicItem struct {
|
||||
*MonCommonData
|
||||
}
|
||||
|
||||
type ProjectStatisticItem struct {
|
||||
*ProjectStatisticBasicItem
|
||||
type ServiceStatisticItem struct {
|
||||
*ServiceStatisticBasicItem
|
||||
IsRed bool `json:"is_red"` //是否标红
|
||||
}
|
||||
|
||||
type ProjectStatisticBasicItem struct {
|
||||
type ServiceStatisticBasicItem struct {
|
||||
Id string `json:"id"` //订阅方ID
|
||||
Name string `json:"name"` //订阅方名称
|
||||
*MonCommonData
|
||||
|
||||
+447
-11
@@ -5,14 +5,15 @@ 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"
|
||||
|
||||
@@ -42,6 +43,442 @@ 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)
|
||||
@@ -173,7 +610,7 @@ func (i *imlMonitorStatisticModule) TopAPIStatistics(ctx context.Context, limit
|
||||
|
||||
}
|
||||
|
||||
func (i *imlMonitorStatisticModule) TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, error) {
|
||||
func (i *imlMonitorStatisticModule) TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
@@ -182,7 +619,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.ProjectStatisticItem, error) {
|
||||
func (i *imlMonitorStatisticModule) TopProviderStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ServiceStatisticItem, error) {
|
||||
clusterId := cluster.DefaultClusterID
|
||||
_, err := i.clusterService.Get(ctx, clusterId)
|
||||
if err != nil {
|
||||
@@ -191,12 +628,12 @@ func (i *imlMonitorStatisticModule) TopProviderStatistics(ctx context.Context, l
|
||||
return i.topProjectStatistics(ctx, clusterId, "provider", input, limit)
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
statisticMap, err := i.statistics(ctx, partitionId, groupBy, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, limit)
|
||||
statisticMap, err := i.statistics(ctx, clusterId, groupBy, formatTimeByMinute(input.Start), formatTimeByMinute(input.End), wheres, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -216,10 +653,10 @@ func (i *imlMonitorStatisticModule) topProjectStatistics(ctx context.Context, pa
|
||||
return t.Id
|
||||
})
|
||||
|
||||
result := make([]*monitor_dto.ProjectStatisticItem, 0, len(statisticMap))
|
||||
result := make([]*monitor_dto.ServiceStatisticItem, 0, len(statisticMap))
|
||||
for key, item := range statisticMap {
|
||||
statisticItem := &monitor_dto.ProjectStatisticItem{
|
||||
ProjectStatisticBasicItem: &monitor_dto.ProjectStatisticBasicItem{
|
||||
statisticItem := &monitor_dto.ServiceStatisticItem{
|
||||
ServiceStatisticBasicItem: &monitor_dto.ServiceStatisticBasicItem{
|
||||
Id: key,
|
||||
MonCommonData: monitor_dto.ToMonCommonData(item),
|
||||
},
|
||||
@@ -407,7 +844,6 @@ 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,18 +13,36 @@ 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.ProjectStatisticItem, error)
|
||||
TopSubscriberStatistics(ctx context.Context, limit int, input *monitor_dto.CommonInput) ([]*monitor_dto.ProjectStatisticItem, 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)
|
||||
// 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 {
|
||||
|
||||
+43
-3
@@ -5,6 +5,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/strategy"
|
||||
|
||||
api_doc "github.com/APIParkLab/APIPark/service/api-doc"
|
||||
service_doc "github.com/APIParkLab/APIPark/service/service-doc"
|
||||
|
||||
@@ -40,11 +42,39 @@ 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.StrategyCommit], 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.StrategyCommit] {
|
||||
key := fmt.Sprintf("service-%s", s.Id)
|
||||
return &commit.Commit[strategy.StrategyCommit]{
|
||||
Target: s.Id,
|
||||
Key: key,
|
||||
Data: &strategy.StrategyCommit{
|
||||
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 *imlReleaseModule) Create(ctx context.Context, serviceId string, input *dto.CreateInput) (string, error) {
|
||||
|
||||
proInfo, err := m.projectService.Check(ctx, serviceId, projectRuleMustServer)
|
||||
@@ -83,7 +113,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, serviceId)
|
||||
upstreams, err := m.upstreamService.ListLatestCommit(ctx, cluster.DefaultClusterID, serviceId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return "", errors.New("api config or document not found")
|
||||
@@ -103,6 +133,13 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input *
|
||||
return c.Key, c.UUID
|
||||
})
|
||||
})
|
||||
strategies, err := m.latestStrategyCommits(ctx, serviceId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
strategyCommits := utils.SliceToMapO(strategies, func(c *commit.Commit[strategy.StrategyCommit]) (string, string) {
|
||||
return c.Target, c.UUID
|
||||
})
|
||||
|
||||
var newRelease *release.Release
|
||||
err = m.transaction.Transaction(ctx, func(ctx context.Context) error {
|
||||
@@ -126,6 +163,9 @@ 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)
|
||||
@@ -151,7 +191,7 @@ func (m *imlReleaseModule) Create(ctx context.Context, serviceId string, input *
|
||||
}
|
||||
serviceDocCommit, err := m.serviceDocService.LatestDocCommit(ctx, serviceId)
|
||||
if err != nil {
|
||||
|
||||
return err
|
||||
}
|
||||
if !m.releaseService.Completeness(utils.SliceToSlice(clusters, func(s *cluster.Cluster) string {
|
||||
return s.Uuid
|
||||
@@ -161,7 +201,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)
|
||||
newRelease, err = m.releaseService.CreateRelease(ctx, serviceId, input.Version, input.Remark, requestCommitMap, apiProxyCommits, docCommit.UUID, serviceDocCommit.UUID, upstreamCommitsForUKC, strategyCommits)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -102,3 +102,7 @@ type ListInput struct {
|
||||
type UpdateDoc struct {
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type InputSimpleAPI struct {
|
||||
Services []string `json:"services"`
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ type Item struct {
|
||||
type SimpleItem struct {
|
||||
Id string `json:"id"`
|
||||
Methods []string `json:"methods"`
|
||||
Name string `json:"name"`
|
||||
Path string `json:"request_path"`
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
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,6 +46,28 @@ 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,9 +2,11 @@ package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/APIParkLab/APIPark/module/system"
|
||||
"reflect"
|
||||
|
||||
"github.com/APIParkLab/APIPark/module/system"
|
||||
strategy_filter "github.com/APIParkLab/APIPark/strategy-filter"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
|
||||
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
|
||||
@@ -29,6 +31,7 @@ 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)
|
||||
}
|
||||
|
||||
@@ -45,4 +48,8 @@ func init() {
|
||||
autowire.Auto[IExportRouterModule](func() reflect.Value {
|
||||
return reflect.ValueOf(apiModule)
|
||||
})
|
||||
|
||||
filter := new(imlRouterFilter)
|
||||
autowire.Autowired(filter)
|
||||
strategy_filter.RegisterRemoteFilter(filter)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/strategy"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/service"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/api"
|
||||
@@ -23,6 +25,7 @@ type imlServiceDiff struct {
|
||||
apiDocService api_doc.IAPIDocService `autowired:""`
|
||||
upstreamService upstream.IUpstreamService `autowired:""`
|
||||
releaseService release.IReleaseService `autowired:""`
|
||||
strategyService strategy.IStrategyService `autowired:""`
|
||||
clusterService cluster.IClusterService `autowired:""`
|
||||
}
|
||||
|
||||
@@ -79,6 +82,34 @@ func (m *imlServiceDiff) getBaseInfo(ctx context.Context, serviceId, baseRelease
|
||||
|
||||
return base, nil
|
||||
}
|
||||
|
||||
func (m *imlServiceDiff) latestStrategyCommits(ctx context.Context, serviceId string) ([]*commit.Commit[strategy.StrategyCommit], 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.StrategyCommit] {
|
||||
key := fmt.Sprintf("service-%s", s.Id)
|
||||
return &commit.Commit[strategy.StrategyCommit]{
|
||||
Target: s.Id,
|
||||
Key: key,
|
||||
Data: &strategy.StrategyCommit{
|
||||
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 {
|
||||
@@ -88,6 +119,9 @@ 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
|
||||
@@ -122,7 +156,7 @@ func (m *imlServiceDiff) DiffForLatest(ctx context.Context, serviceId string, ba
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
upstreamCommits, err := m.upstreamService.ListLatestCommit(ctx, serviceId)
|
||||
upstreamCommits, err := m.upstreamService.ListLatestCommit(ctx, cluster.DefaultClusterID, serviceId)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
@@ -130,6 +164,11 @@ 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
|
||||
@@ -140,6 +179,7 @@ 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 {
|
||||
@@ -211,6 +251,46 @@ func (m *imlServiceDiff) getReleaseInfo(ctx context.Context, releaseId string) (
|
||||
upstreamCommits: upstreamCommits,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *imlServiceDiff) diffStrategies(base, target []*commit.Commit[strategy.StrategyCommit]) []*service_diff.StrategyDiff {
|
||||
baseStrategy := utils.SliceToMap(base, func(i *commit.Commit[strategy.StrategyCommit]) string {
|
||||
return i.Target
|
||||
})
|
||||
targetStrategy := utils.SliceToMap(target, func(i *commit.Commit[strategy.StrategyCommit]) string {
|
||||
return i.Target
|
||||
})
|
||||
out := make([]*service_diff.StrategyDiff, 0, len(target))
|
||||
for _, tc := range targetStrategy {
|
||||
key := tc.Target
|
||||
t := tc.Data
|
||||
o := &service_diff.StrategyDiff{
|
||||
Strategy: key,
|
||||
Name: t.Name,
|
||||
Priority: t.Priority,
|
||||
Change: service_diff.ChangeTypeNone,
|
||||
Status: 0,
|
||||
}
|
||||
b, hasB := baseStrategy[key]
|
||||
if !hasB {
|
||||
o.Change = service_diff.ChangeTypeNew
|
||||
} else if b.UUID != tc.UUID {
|
||||
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,
|
||||
@@ -328,6 +408,7 @@ func (m *imlServiceDiff) diff(partitions []string, base, target *projectInfo) *s
|
||||
}
|
||||
}
|
||||
}
|
||||
out.Strategies = m.diffStrategies(base.strategyCommits, target.strategyCommits)
|
||||
|
||||
return out
|
||||
}
|
||||
@@ -373,5 +454,13 @@ 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,13 +4,15 @@ 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"`
|
||||
Routers []*RouterDiffOut `json:"routers"`
|
||||
Upstreams []*UpstreamDiffOut `json:"upstreams"`
|
||||
Strategies []*StrategyDiffOut `json:"strategies"`
|
||||
}
|
||||
|
||||
type RouterDiffOut struct {
|
||||
@@ -30,6 +32,13 @@ 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
|
||||
@@ -37,4 +46,5 @@ type projectInfo struct {
|
||||
apiProxyCommits []*commit.Commit[api.Proxy]
|
||||
apiDocCommits []*commit.Commit[api_doc.DocCommit]
|
||||
upstreamCommits []*commit.Commit[upstream.Config]
|
||||
strategyCommits []*commit.Commit[strategy.StrategyCommit]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
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
|
||||
}
|
||||
+43
-45
@@ -109,9 +109,7 @@ 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
|
||||
}
|
||||
@@ -176,7 +174,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.Search(ctx, keyword, w)
|
||||
// services, err := i.serviceService.SearchByDriver(ctx, keyword, w)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
@@ -191,47 +189,47 @@ func (i *imlServiceModule) SearchMyServices(ctx context.Context, teamId string,
|
||||
// }), 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) 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) Get(ctx context.Context, id string) (*service_dto.Service, error) {
|
||||
now := time.Now()
|
||||
|
||||
@@ -4,6 +4,8 @@ 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"
|
||||
@@ -25,11 +27,11 @@ type IServiceModule interface {
|
||||
// Delete 删除项目
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// Simple 获取简易项目列表
|
||||
//Simple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error)
|
||||
//Simple 获取简易项目列表
|
||||
Simple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error)
|
||||
|
||||
// MySimple 获取我的简易项目列表
|
||||
//MySimple(ctx context.Context, keyword string) ([]*service_dto.SimpleServiceItem, error)
|
||||
//MySimple 获取我的简易项目列表
|
||||
MySimple(ctx context.Context) ([]*service_dto.SimpleServiceItem, error)
|
||||
}
|
||||
|
||||
type IServiceDocModule interface {
|
||||
@@ -83,4 +85,8 @@ func init() {
|
||||
return reflect.ValueOf(serviceDocModule)
|
||||
})
|
||||
|
||||
filter := new(imlAppFilter)
|
||||
autowire.Autowired(filter)
|
||||
strategy_filter.RegisterRemoteFilter(filter)
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
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"`
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package data_masking
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
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) ToApinto(s strategy_dto.Strategy) interface{} {
|
||||
filters := make(map[string][]string)
|
||||
|
||||
for _, f := range s.Filters {
|
||||
filters[f.Name] = f.Values
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"name": s.Filters,
|
||||
"description": s.Desc,
|
||||
"priority": s.Priority,
|
||||
"filters": filters,
|
||||
d.confName: s.Config,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
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": {},
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package strategy_driver
|
||||
|
||||
import (
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
)
|
||||
|
||||
type IStrategyDriver interface {
|
||||
Driver() string
|
||||
ToApinto(strategy strategy_dto.Strategy) interface{}
|
||||
Check(config interface{}) error
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
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"`
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
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) *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: 0,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
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 int `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"`
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gorm.io/gorm"
|
||||
|
||||
"github.com/eolinker/eosc/log"
|
||||
|
||||
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:""`
|
||||
transaction store.ITransaction `autowired:""`
|
||||
}
|
||||
|
||||
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.StrategyCommit]) (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,
|
||||
})
|
||||
}
|
||||
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
|
||||
}
|
||||
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.StrategyCommit]) (string, string) { return c.Data.Id, c.Data.Version })
|
||||
items := make([]*strategy_dto.StrategyItem, 0, len(list))
|
||||
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, ";"))
|
||||
items = append(items, item)
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
for _, l := range list {
|
||||
if l.IsDelete {
|
||||
err = i.strategyService.Delete(ctx, l.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO:同步到网关
|
||||
err = i.strategyService.CommitStrategy(txCtx, scope, target, l.Id, l)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"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
|
||||
}
|
||||
|
||||
func init() {
|
||||
strategyModule := new(imlStrategyModule)
|
||||
autowire.Auto[IStrategyModule](func() reflect.Value {
|
||||
return reflect.ValueOf(strategyModule)
|
||||
})
|
||||
}
|
||||
@@ -7,6 +7,7 @@ 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,6 +7,7 @@ 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,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
@@ -34,7 +35,7 @@ type imlUpstreamModule struct {
|
||||
}
|
||||
|
||||
func (i *imlUpstreamModule) ExportAll(ctx context.Context) ([]*upstream_dto.ExportUpstream, error) {
|
||||
latestCommits, err := i.upstreamService.ListLatestCommit(ctx)
|
||||
latestCommits, err := i.upstreamService.ListLatestCommit(ctx, cluster.DefaultClusterID)
|
||||
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.Enable),
|
||||
//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/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,6 +9,7 @@ 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,6 +3,8 @@ package core
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"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"
|
||||
@@ -72,6 +74,7 @@ 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:""`
|
||||
@@ -105,6 +108,7 @@ 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()...)
|
||||
}
|
||||
|
||||
func (p *plugin) Name() string {
|
||||
|
||||
@@ -17,5 +17,10 @@ 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,11 +3,14 @@ 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),
|
||||
@@ -15,6 +18,8 @@ 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),
|
||||
@@ -27,5 +32,7 @@ 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),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
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),
|
||||
}
|
||||
}
|
||||
@@ -131,6 +131,16 @@ 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'
|
||||
@@ -197,6 +207,16 @@ 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,6 +19,8 @@ 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
|
||||
@@ -49,6 +51,8 @@ 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
|
||||
@@ -75,6 +79,8 @@ 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
|
||||
@@ -99,6 +105,8 @@ 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
|
||||
@@ -120,7 +128,7 @@ team:
|
||||
- team.service.service.manager
|
||||
- team.service.service_intro.manager
|
||||
- team.service.service_intro.view
|
||||
- team.service.subscription.manager
|
||||
- team.service.strategy.view
|
||||
- team.service.subscription.view
|
||||
- team.service.upstream.manager
|
||||
- team.service.upstream.view
|
||||
|
||||
@@ -5,12 +5,19 @@
|
||||
"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": "Access Authorization",
|
||||
"authorization": "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",
|
||||
@@ -22,7 +29,7 @@
|
||||
"member": "Member",
|
||||
"release": "Release",
|
||||
"role": "Role",
|
||||
"run view": "Run View",
|
||||
"run view": "Runtime View",
|
||||
"service": "Service",
|
||||
"service admin": "Service Admin",
|
||||
"service developer": "Service Developer",
|
||||
@@ -42,5 +49,7 @@
|
||||
"view all service": "View All Services",
|
||||
"view all team": "View All Teams",
|
||||
"view subscribed services": "View Subscribed Services",
|
||||
"workspace": "Workspace"
|
||||
"workspace": "Workspace",
|
||||
"request path": "Request Path",
|
||||
"methods": "Request Methods"
|
||||
}
|
||||
|
||||
@@ -5,31 +5,38 @@
|
||||
"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 admin": "消費者管理者",
|
||||
"consumer developer": "消費者開発者",
|
||||
"authorization": "認証",
|
||||
"consumer": "コンシューマー",
|
||||
"consumer id": "コンシューマーID",
|
||||
"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": "システム設定",
|
||||
@@ -38,9 +45,11 @@
|
||||
"team admin": "チーム管理者",
|
||||
"upstream": "アップストリーム",
|
||||
"view": "表示",
|
||||
"view all consumer": "すべての消費者を表示",
|
||||
"view all service": "すべてのサービスを表示",
|
||||
"view all team": "すべてのチームを表示",
|
||||
"view subscribed services": "購読したサービスを表示",
|
||||
"workspace": "ワークスペース"
|
||||
"view all consumer": "全てのコンシューマーを表示",
|
||||
"view all service": "全てのサービスを表示",
|
||||
"view all team": "全てのチームを表示",
|
||||
"view subscribed services": "購読済みサービスを表示",
|
||||
"workspace": "ワークスペース",
|
||||
"request path": "リクエストパス",
|
||||
"methods": "リクエスト方式"
|
||||
}
|
||||
|
||||
@@ -5,12 +5,19 @@
|
||||
"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": "常规设置",
|
||||
@@ -42,5 +49,7 @@
|
||||
"view all service": "查看所有服务",
|
||||
"view all team": "查看所有团队",
|
||||
"view subscribed services": "查看已经订阅的服务",
|
||||
"workspace": "工作空间"
|
||||
"workspace": "工作空间",
|
||||
"request path": "请求路径",
|
||||
"methods": "请求方法"
|
||||
}
|
||||
|
||||
@@ -1,46 +1,55 @@
|
||||
{
|
||||
"account": "帳號",
|
||||
"ai provider": "AI 供應商",
|
||||
"ai provider": "AI 模型供應商",
|
||||
"analysis": "分析報告",
|
||||
"api": "API",
|
||||
"api doc": "API 文件",
|
||||
"api gateway": "API 閘道",
|
||||
"api portal": "API 入口網站",
|
||||
"authorization": "存取授權",
|
||||
"consumer": "使用者",
|
||||
"consumer admin": "使用者管理員",
|
||||
"consumer developer": "使用者開發人員",
|
||||
"create": "建立",
|
||||
"data source": "資料來源",
|
||||
"devops admin": "DevOps 管理員",
|
||||
"general": "一般設定",
|
||||
"general member": "一般成員",
|
||||
"log configuration": "日誌設定",
|
||||
"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": "日誌配置",
|
||||
"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": "工作區"
|
||||
"view": "查看",
|
||||
"view all consumer": "查看所有消費者",
|
||||
"view all service": "查看所有服務",
|
||||
"view all team": "查看所有團隊",
|
||||
"view subscribed services": "查看已訂閱的服務",
|
||||
"workspace": "工作空間",
|
||||
"request path": "請求路徑",
|
||||
"methods": "請求方法"
|
||||
}
|
||||
|
||||
@@ -41,6 +41,30 @@ type imlAPIService struct {
|
||||
universally.IServiceDelete
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListForServices(ctx context.Context, serviceIds ...string) ([]*API, error) {
|
||||
w := map[string]interface{}{}
|
||||
if len(serviceIds) > 0 {
|
||||
w["service"] = serviceIds
|
||||
}
|
||||
list, err := i.store.List(ctx, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, FromEntity), nil
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListInfoForServices(ctx context.Context, serviceIds ...string) ([]*Info, error) {
|
||||
w := map[string]interface{}{}
|
||||
if len(serviceIds) > 0 {
|
||||
w["service"] = serviceIds
|
||||
}
|
||||
list, err := i.apiInfoStore.List(ctx, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, FromEntityInfo), nil
|
||||
}
|
||||
|
||||
func (i *imlAPIService) ListLatestCommitRequest(ctx context.Context, aid ...string) ([]*commit.Commit[Request], error) {
|
||||
return i.requestCommitService.ListLatest(ctx, aid...)
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@ type IAPIService interface {
|
||||
CountMapByService(ctx context.Context, service ...string) (map[string]int64, error)
|
||||
Exist(ctx context.Context, aid string, api *Exist) error
|
||||
ListForService(ctx context.Context, serviceId string) ([]*API, error)
|
||||
ListForServices(ctx context.Context, serviceIds ...string) ([]*API, error)
|
||||
GetInfo(ctx context.Context, aid string) (*Info, error)
|
||||
ListInfo(ctx context.Context, aids ...string) ([]*Info, error)
|
||||
ListInfoForService(ctx context.Context, serviceId string) ([]*Info, error)
|
||||
ListInfoForServices(ctx context.Context, serviceIds ...string) ([]*Info, error)
|
||||
|
||||
ListLatestCommitProxy(ctx context.Context, aid ...string) ([]*commit.Commit[Proxy], error)
|
||||
LatestProxy(ctx context.Context, aid string) (*commit.Commit[Proxy], error)
|
||||
|
||||
@@ -8,4 +8,5 @@ const (
|
||||
CommitUpstream CommitType = "upstream"
|
||||
CommitApiProxy CommitType = "api_proxy"
|
||||
CommitServiceDoc CommitType = "service_doc"
|
||||
CommitStrategy CommitType = "strategy"
|
||||
)
|
||||
|
||||
+14
-5
@@ -281,7 +281,7 @@ func (s *imlReleaseService) SetRunning(ctx context.Context, service string, id s
|
||||
|
||||
}
|
||||
|
||||
func (s *imlReleaseService) CreateRelease(ctx context.Context, service string, version string, remark string, apiRequestCommit, apisProxyCommits map[string]string, apiDocCommit, serviceDocCommit string, upstreams map[string]map[string]string) (*Release, error) {
|
||||
func (s *imlReleaseService) CreateRelease(ctx context.Context, service, version, remark string, apiRequestCommit, apisProxyCommits map[string]string, apiDocCommits, serviceDocCommits string, upstreams map[string]map[string]string, strategies map[string]string) (*Release, error) {
|
||||
operator := utils.UserId(ctx)
|
||||
releaseId := uuid.NewString()
|
||||
commits := make([]*release.Commit, 0, len(apisProxyCommits)+len(upstreams)+2)
|
||||
@@ -315,23 +315,32 @@ func (s *imlReleaseService) CreateRelease(ctx context.Context, service string, v
|
||||
})
|
||||
}
|
||||
}
|
||||
if apiDocCommit != "" {
|
||||
if apiDocCommits != "" {
|
||||
commits = append(commits, &release.Commit{
|
||||
Type: CommitApiDocument,
|
||||
Target: service,
|
||||
Release: releaseId,
|
||||
Key: CommitApiDocument,
|
||||
Commit: apiDocCommit,
|
||||
Commit: apiDocCommits,
|
||||
})
|
||||
}
|
||||
|
||||
if serviceDocCommit != "" {
|
||||
if serviceDocCommits != "" {
|
||||
commits = append(commits, &release.Commit{
|
||||
Type: CommitServiceDoc,
|
||||
Target: service,
|
||||
Release: releaseId,
|
||||
Key: CommitServiceDoc,
|
||||
Commit: serviceDocCommit,
|
||||
Commit: serviceDocCommits,
|
||||
})
|
||||
}
|
||||
for key, value := range strategies {
|
||||
commits = append(commits, &release.Commit{
|
||||
Type: CommitStrategy,
|
||||
Target: key,
|
||||
Release: releaseId,
|
||||
Key: CommitStrategy,
|
||||
Commit: value,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ type IReleaseService interface {
|
||||
// GetRelease 获取发布信息
|
||||
GetRelease(ctx context.Context, id string) (*Release, error)
|
||||
// CreateRelease 创建发布
|
||||
CreateRelease(ctx context.Context, service string, version string, remark string, apiRequestCommit, apisProxyCommits map[string]string, apiDocCommits, serviceDocCommits string, upstreams map[string]map[string]string) (*Release, error)
|
||||
CreateRelease(ctx context.Context, service, version, remark string, apiRequestCommit, apisProxyCommits map[string]string, apiDocCommits, serviceDocCommits string, upstreams map[string]map[string]string, strategies map[string]string) (*Release, error)
|
||||
// DeleteRelease 删除发布
|
||||
DeleteRelease(ctx context.Context, id string) error
|
||||
List(ctx context.Context, service string) ([]*Release, error)
|
||||
|
||||
@@ -39,8 +39,17 @@ type UpstreamDiff struct {
|
||||
Status StatusType `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
type Diff struct {
|
||||
Clusters []string `json:"clusters,omitempty"`
|
||||
Apis []*ApiDiff `json:"apis"`
|
||||
Upstreams []*UpstreamDiff `json:"upstreams"`
|
||||
type StrategyDiff struct {
|
||||
Strategy string `json:"strategy,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Priority int `json:"priority"`
|
||||
Change ChangeType `json:"change,omitempty"`
|
||||
Status StatusType `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
type Diff struct {
|
||||
Clusters []string `json:"clusters,omitempty"`
|
||||
Apis []*ApiDiff `json:"apis"`
|
||||
Upstreams []*UpstreamDiff `json:"upstreams"`
|
||||
Strategies []*StrategyDiff `json:"strategies"`
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ var (
|
||||
|
||||
const (
|
||||
KeyInvokeAddress = "system.node.invoke_address"
|
||||
KeySitePrefix = "system.setting.site_prefix"
|
||||
)
|
||||
|
||||
type imlSettingService struct {
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||
|
||||
"github.com/eolinker/go-common/utils"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally"
|
||||
"github.com/APIParkLab/APIPark/stores/strategy"
|
||||
)
|
||||
|
||||
var _ IStrategyService = (*imlStrategyService)(nil)
|
||||
|
||||
type imlStrategyService struct {
|
||||
store strategy.IStrategyStore `autowired:""`
|
||||
commitService commit.ICommitService[StrategyCommit] `autowired:""`
|
||||
universally.IServiceCreate[Create]
|
||||
universally.IServiceEdit[Edit]
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) All(ctx context.Context, scope int, target string) ([]*Strategy, error) {
|
||||
w := make(map[string]interface{})
|
||||
w["scope"] = scope
|
||||
if target != "" {
|
||||
w["target"] = target
|
||||
}
|
||||
list, err := i.store.List(ctx, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, FromEntity), nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) Restore(ctx context.Context, id string) error {
|
||||
_, err := i.store.UpdateWhere(ctx, map[string]interface{}{"uuid": id}, map[string]interface{}{"is_delete": false})
|
||||
return err
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) SearchAllByDriver(ctx context.Context, keyword string, driver string, scope int, target string) ([]*Strategy, error) {
|
||||
w := make(map[string]interface{})
|
||||
w["scope"] = scope
|
||||
if target != "" {
|
||||
w["target"] = target
|
||||
}
|
||||
list, err := i.store.Search(ctx, keyword, w, "update_at")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, FromEntity), nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) AllByDriver(ctx context.Context, driver string, scope int, target string) ([]*Strategy, error) {
|
||||
w := make(map[string]interface{})
|
||||
w["scope"] = scope
|
||||
if target != "" {
|
||||
w["target"] = target
|
||||
}
|
||||
w["driver"] = driver
|
||||
list, err := i.store.List(ctx, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.SliceToSlice(list, FromEntity), nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) CommitStrategy(ctx context.Context, scope string, target string, strategyId string, data *Strategy) error {
|
||||
key := scope
|
||||
if target != "" {
|
||||
key = fmt.Sprintf("%s-%s", scope, target)
|
||||
}
|
||||
|
||||
return i.commitService.Save(ctx, strategyId, key, &StrategyCommit{
|
||||
Id: data.Id,
|
||||
Name: data.Name,
|
||||
Priority: data.Priority,
|
||||
Filters: data.Filters,
|
||||
Config: data.Config,
|
||||
Driver: data.Driver,
|
||||
IsStop: data.IsStop,
|
||||
Version: data.UpdateAt.Format("20060102150405"),
|
||||
})
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) GetStrategyCommit(ctx context.Context, commitId string) (*commit.Commit[StrategyCommit], error) {
|
||||
return i.commitService.Get(ctx, commitId)
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) LatestStrategyCommit(ctx context.Context, scope string, target string, strategyId string) (*commit.Commit[StrategyCommit], error) {
|
||||
key := scope
|
||||
if target != "" {
|
||||
key = fmt.Sprintf("%s-%s", scope, target)
|
||||
}
|
||||
return i.commitService.Latest(ctx, strategyId, key)
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) ListLatestStrategyCommit(ctx context.Context, scope string, target string, strategyIds ...string) ([]*commit.Commit[StrategyCommit], error) {
|
||||
key := scope
|
||||
if target != "" {
|
||||
key = fmt.Sprintf("%s-%s", scope, target)
|
||||
}
|
||||
return i.commitService.ListLatest(ctx, key, strategyIds...)
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) ListStrategyCommit(ctx context.Context, commitIds ...string) ([]*commit.Commit[StrategyCommit], error) {
|
||||
if len(commitIds) < 1 {
|
||||
return nil, fmt.Errorf("commit ids is empty")
|
||||
}
|
||||
|
||||
return i.commitService.List(ctx, commitIds...)
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) SearchByDriver(ctx context.Context, keyword string, driver string, scope int, target string, page int, pageSize int, filters []string, order ...string) ([]*Strategy, int64, error) {
|
||||
w := map[string]interface{}{
|
||||
"scope": scope,
|
||||
"driver": driver,
|
||||
}
|
||||
if target != "" {
|
||||
w["target"] = target
|
||||
}
|
||||
for _, f := range filters {
|
||||
switch f {
|
||||
case "enable":
|
||||
w["enable"] = true
|
||||
case "disable":
|
||||
w["enable"] = false
|
||||
}
|
||||
}
|
||||
if len(order) < 1 {
|
||||
order = []string{"update_at desc"}
|
||||
}
|
||||
list, total, err := i.store.SearchByPage(ctx, keyword, w, page, pageSize, order...)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return utils.SliceToSlice(list, FromEntity), total, nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) Get(ctx context.Context, id string) (*Strategy, error) {
|
||||
info, err := i.store.GetByUUID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return FromEntity(info), nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) SortDelete(ctx context.Context, id string) error {
|
||||
return i.store.SoftDelete(ctx, map[string]interface{}{"uuid": id})
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) Delete(ctx context.Context, id ...string) error {
|
||||
if len(id) == 0 {
|
||||
return nil
|
||||
}
|
||||
_, err := i.store.DeleteWhere(ctx, map[string]interface{}{"uuid": id})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *imlStrategyService) OnComplete() {
|
||||
|
||||
i.IServiceCreate = universally.NewCreator[Create, strategy.Strategy](i.store, "strategy", createEntityHandler, uniquestHandler, labelHandler)
|
||||
|
||||
i.IServiceEdit = universally.NewEdit[Edit, strategy.Strategy](i.store, updateHandler, labelHandler)
|
||||
}
|
||||
|
||||
func labelHandler(e *strategy.Strategy) []string {
|
||||
return []string{e.Name, e.UUID, e.Desc}
|
||||
}
|
||||
func uniquestHandler(i *Create) []map[string]interface{} {
|
||||
return []map[string]interface{}{{"uuid": i.Id}}
|
||||
}
|
||||
func createEntityHandler(i *Create) *strategy.Strategy {
|
||||
now := time.Now()
|
||||
return &strategy.Strategy{
|
||||
UUID: i.Id,
|
||||
Name: i.Name,
|
||||
Priority: i.Priority,
|
||||
Desc: i.Desc,
|
||||
Filters: i.Filters,
|
||||
Config: i.Config,
|
||||
Driver: i.Driver,
|
||||
Scope: i.Scope,
|
||||
Target: i.Target,
|
||||
CreateAt: now,
|
||||
UpdateAt: now,
|
||||
IsStop: false,
|
||||
IsDelete: false,
|
||||
}
|
||||
}
|
||||
func updateHandler(e *strategy.Strategy, i *Edit) {
|
||||
if i.Name != nil {
|
||||
e.Name = *i.Name
|
||||
}
|
||||
if i.Priority != nil {
|
||||
e.Priority = *i.Priority
|
||||
}
|
||||
if i.Desc != nil {
|
||||
e.Desc = *i.Desc
|
||||
}
|
||||
if i.Filters != nil {
|
||||
e.Filters = *i.Filters
|
||||
}
|
||||
if i.Config != nil {
|
||||
e.Config = *i.Config
|
||||
}
|
||||
if i.IsStop != nil {
|
||||
e.IsStop = *i.IsStop
|
||||
}
|
||||
e.UpdateAt = time.Now()
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/APIParkLab/APIPark/stores/strategy"
|
||||
)
|
||||
|
||||
type Strategy struct {
|
||||
Id string
|
||||
Name string
|
||||
Priority int
|
||||
Desc string
|
||||
Filters string
|
||||
Config string
|
||||
Driver string
|
||||
Scope int
|
||||
Target string
|
||||
Creator string
|
||||
Updater string
|
||||
CreateAt time.Time
|
||||
UpdateAt time.Time
|
||||
IsStop bool
|
||||
IsDelete bool
|
||||
}
|
||||
|
||||
func FromEntity(e *strategy.Strategy) *Strategy {
|
||||
return &Strategy{
|
||||
Id: e.UUID,
|
||||
Name: e.Name,
|
||||
Priority: e.Priority,
|
||||
Driver: e.Driver,
|
||||
Desc: e.Desc,
|
||||
Filters: e.Filters,
|
||||
Config: e.Config,
|
||||
Scope: e.Scope,
|
||||
Target: e.Target,
|
||||
Creator: e.Creator,
|
||||
Updater: e.Updater,
|
||||
CreateAt: e.CreateAt,
|
||||
UpdateAt: e.UpdateAt,
|
||||
IsStop: e.IsStop,
|
||||
IsDelete: e.IsDelete,
|
||||
}
|
||||
}
|
||||
|
||||
type Create struct {
|
||||
Id string
|
||||
Name string
|
||||
Priority int
|
||||
Desc string
|
||||
Filters string
|
||||
Config string
|
||||
Scope int
|
||||
Target string
|
||||
Driver string
|
||||
}
|
||||
|
||||
type Edit struct {
|
||||
Name *string
|
||||
Priority *int
|
||||
Desc *string
|
||||
Filters *string
|
||||
Config *string
|
||||
IsStop *bool
|
||||
}
|
||||
|
||||
type StrategyCommit struct {
|
||||
Id string
|
||||
Name string
|
||||
Priority int
|
||||
Filters string
|
||||
Config string
|
||||
Driver string
|
||||
IsStop bool
|
||||
Version string
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
|
||||
"github.com/APIParkLab/APIPark/service/universally"
|
||||
)
|
||||
|
||||
type IStrategyService interface {
|
||||
universally.IServiceCreate[Create]
|
||||
universally.IServiceEdit[Edit]
|
||||
All(ctx context.Context, scope int, target string) ([]*Strategy, error)
|
||||
AllByDriver(ctx context.Context, driver string, scope int, target string) ([]*Strategy, error)
|
||||
SearchByDriver(ctx context.Context, keyword string, driver string, scope int, target string, page int, pageSize int, filters []string, order ...string) ([]*Strategy, int64, error)
|
||||
SearchAllByDriver(ctx context.Context, keyword string, driver string, scope int, target string) ([]*Strategy, error)
|
||||
Get(ctx context.Context, id string) (*Strategy, error)
|
||||
SortDelete(ctx context.Context, id string) error
|
||||
Delete(ctx context.Context, id ...string) error
|
||||
|
||||
Restore(ctx context.Context, id string) error
|
||||
|
||||
CommitStrategy(ctx context.Context, scope string, target string, strategyId string, data *Strategy) error
|
||||
GetStrategyCommit(ctx context.Context, commitId string) (*commit.Commit[StrategyCommit], error)
|
||||
LatestStrategyCommit(ctx context.Context, scope string, target string, strategyId string) (*commit.Commit[StrategyCommit], error)
|
||||
ListLatestStrategyCommit(ctx context.Context, scope string, target string, strategyIds ...string) ([]*commit.Commit[StrategyCommit], error)
|
||||
ListStrategyCommit(ctx context.Context, commitIds ...string) ([]*commit.Commit[StrategyCommit], error)
|
||||
}
|
||||
|
||||
func init() {
|
||||
autowire.Auto[IStrategyService](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlStrategyService))
|
||||
})
|
||||
commit.InitCommitService[StrategyCommit]("strategy")
|
||||
}
|
||||
@@ -2,9 +2,10 @@ package commit
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/eolinker/go-common/utils"
|
||||
"gorm.io/gorm"
|
||||
|
||||
|
||||
"github.com/APIParkLab/APIPark/stores/universally/commit"
|
||||
)
|
||||
|
||||
@@ -18,7 +19,7 @@ type imlCommitWithKeyService[T any] struct {
|
||||
}
|
||||
|
||||
func (i *imlCommitWithKeyService[T]) List(ctx context.Context, uuids ...string) ([]*Commit[T], error) {
|
||||
|
||||
|
||||
list, err := i.store.List(ctx, uuids...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -31,7 +32,7 @@ func (i *imlCommitWithKeyService[T]) ListLatest(ctx context.Context, target ...s
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
return utils.SliceToSlice(list, newCommit[T]), nil
|
||||
}
|
||||
|
||||
@@ -40,7 +41,7 @@ func (i *imlCommitWithKeyService[T]) Get(ctx context.Context, uuid string) (*Com
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
return newCommit(r), nil
|
||||
}
|
||||
|
||||
@@ -52,7 +53,7 @@ func (i *imlCommitWithKeyService[T]) Latest(ctx context.Context, target string)
|
||||
if len(list) == 0 {
|
||||
return nil, gorm.ErrRecordNotFound
|
||||
}
|
||||
|
||||
|
||||
result := list[0]
|
||||
return result, nil
|
||||
}
|
||||
@@ -70,13 +71,13 @@ func (i *imlCommitService[T]) List(ctx context.Context, uuids ...string) ([]*Com
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
return utils.SliceToSlice(list, newCommit[T]), nil
|
||||
|
||||
|
||||
}
|
||||
|
||||
func (i *imlCommitService[T]) ListLatest(ctx context.Context, target ...string) ([]*Commit[T], error) {
|
||||
list, err := i.store.Latest(ctx, "", target...)
|
||||
func (i *imlCommitService[T]) ListLatest(ctx context.Context, key string, target ...string) ([]*Commit[T], error) {
|
||||
list, err := i.store.Latest(ctx, key, target...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -88,7 +89,7 @@ func (i *imlCommitService[T]) Get(ctx context.Context, uuid string) (*Commit[T],
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
return newCommit(r), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package commit
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
|
||||
|
||||
"github.com/APIParkLab/APIPark/stores/universally/commit"
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
)
|
||||
@@ -18,7 +18,7 @@ type ICommitWithKeyService[T any] interface {
|
||||
|
||||
func InitCommitWithKeyService[T any](name string, key string) {
|
||||
autowire.Auto[commit.ICommitWKStore[T]](func() reflect.Value {
|
||||
|
||||
|
||||
return reflect.ValueOf(commit.NewCommitWithKey[T](name, key))
|
||||
})
|
||||
autowire.Auto[ICommitWithKeyService[T]](func() reflect.Value {
|
||||
@@ -28,7 +28,7 @@ func InitCommitWithKeyService[T any](name string, key string) {
|
||||
|
||||
type ICommitService[T any] interface {
|
||||
Latest(ctx context.Context, target string, key string) (*Commit[T], error)
|
||||
ListLatest(ctx context.Context, target ...string) ([]*Commit[T], error)
|
||||
ListLatest(ctx context.Context, key string, target ...string) ([]*Commit[T], error)
|
||||
Save(ctx context.Context, target string, key string, data *T) error
|
||||
Get(ctx context.Context, uuid string) (*Commit[T], error)
|
||||
List(ctx context.Context, uuids ...string) ([]*Commit[T], error)
|
||||
|
||||
@@ -50,7 +50,7 @@ func (i *imlUpstreamService) ListCommit(ctx context.Context, uuid ...string) ([]
|
||||
return i.commitService.List(ctx, uuid...)
|
||||
}
|
||||
|
||||
func (i *imlUpstreamService) ListLatestCommit(ctx context.Context, serviceIds ...string) ([]*commit.Commit[Config], error) {
|
||||
func (i *imlUpstreamService) ListLatestCommit(ctx context.Context, clusterId string, serviceIds ...string) ([]*commit.Commit[Config], error) {
|
||||
w := make(map[string]interface{})
|
||||
if len(serviceIds) > 0 {
|
||||
w["service"] = serviceIds
|
||||
@@ -67,7 +67,7 @@ func (i *imlUpstreamService) ListLatestCommit(ctx context.Context, serviceIds ..
|
||||
targetId := utils.SliceToSlice(upstreams, func(u *upstream.Upstream) string {
|
||||
return u.UUID
|
||||
})
|
||||
return i.commitService.ListLatest(ctx, targetId...)
|
||||
return i.commitService.ListLatest(ctx, clusterId, targetId...)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ type IUpstreamService interface {
|
||||
Delete(ctx context.Context, id string) error
|
||||
List(ctx context.Context, serviceIds ...string) ([]*Upstream, error)
|
||||
LatestCommit(ctx context.Context, uid string, clusterId string) (*commit.Commit[Config], error)
|
||||
ListLatestCommit(ctx context.Context, serviceIds ...string) ([]*commit.Commit[Config], error)
|
||||
ListLatestCommit(ctx context.Context, clusterId string, serviceIds ...string) ([]*commit.Commit[Config], error)
|
||||
SaveCommit(ctx context.Context, uid string, partition string, cfg *Config) error
|
||||
GetCommit(ctx context.Context, uuid string) (*commit.Commit[Config], error)
|
||||
ListCommit(ctx context.Context, uuid ...string) ([]*commit.Commit[Config], error)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package strategy
|
||||
|
||||
import "time"
|
||||
|
||||
type Strategy struct {
|
||||
Id int64 `gorm:"column:id;type:BIGINT(20);AUTO_INCREMENT;NOT NULL;comment:id;primary_key;comment:主键ID;"`
|
||||
UUID string `gorm:"type:varchar(36);not null;column:uuid;uniqueIndex:uuid;comment:UUID;"`
|
||||
Name string `gorm:"type:varchar(100);not null;column:name;comment:name"`
|
||||
Priority int `gorm:"type:int(11);not null;column:priority;comment:优先级"`
|
||||
Desc string `gorm:"type:text;null;column:desc;comment:描述"`
|
||||
Filters string `gorm:"type:mediumtext;null;column:filters;comment:筛选条件"`
|
||||
Config string `gorm:"type:mediumtext;null;column:config;comment:配置"`
|
||||
Driver string `gorm:"type:varchar(100);not null;column:driver;comment:驱动"`
|
||||
Scope int `gorm:"type:tinyint(1);not null;column:scope;comment:范围 0:全局 1:团队 2:服务"`
|
||||
Target string `gorm:"type:varchar(36);null;column:target;comment:目标ID"`
|
||||
Creator string `gorm:"type:varchar(36);not null;column:creator;comment:创建人" aovalue:"creator"`
|
||||
Updater string `gorm:"type:varchar(36);null;column:updater;comment:更新人" aovalue:"updater"`
|
||||
CreateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:create_at;comment:创建时间"`
|
||||
UpdateAt time.Time `gorm:"type:timestamp;NOT NULL;DEFAULT:CURRENT_TIMESTAMP;column:update_at;comment:更新时间"`
|
||||
IsStop bool `gorm:"type:tinyint(1);not null;column:enable;comment:是否禁用 0:否 1:是"`
|
||||
IsDelete bool `gorm:"type:tinyint(1);not null;column:is_delete;comment:是否删除 0:未删除 1:已删除"`
|
||||
}
|
||||
|
||||
func (s *Strategy) TableName() string {
|
||||
return "strategy"
|
||||
}
|
||||
|
||||
func (s *Strategy) IdValue() int64 {
|
||||
return s.Id
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package strategy
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/eolinker/go-common/autowire"
|
||||
"github.com/eolinker/go-common/store"
|
||||
)
|
||||
|
||||
type IStrategyStore store.ISearchStore[Strategy]
|
||||
|
||||
type imlStrategyStore struct {
|
||||
store.SearchStore[Strategy]
|
||||
}
|
||||
|
||||
func init() {
|
||||
autowire.Auto[IStrategyStore](func() reflect.Value {
|
||||
return reflect.ValueOf(new(imlStrategyStore))
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package strategy_filter
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/eolinker/eosc"
|
||||
|
||||
strategy_dto "github.com/APIParkLab/APIPark/module/strategy/dto"
|
||||
)
|
||||
|
||||
var (
|
||||
filterHandler = NewHandler()
|
||||
)
|
||||
|
||||
type Option struct {
|
||||
Name string
|
||||
Title string
|
||||
Type string
|
||||
Pattern *regexp.Regexp
|
||||
Options []string
|
||||
}
|
||||
|
||||
const (
|
||||
TypeRemote = "remote"
|
||||
TypePattern = "pattern"
|
||||
TypeStatic = "static"
|
||||
|
||||
ValuesALL = "ALL"
|
||||
|
||||
ScopeGlobal = "global"
|
||||
ScopeTeam = "team"
|
||||
ScopeService = "service"
|
||||
)
|
||||
|
||||
const (
|
||||
HttpALL = "ALL"
|
||||
)
|
||||
|
||||
func CheckFilters(name string, scope strategy_dto.Scope, filters []*strategy_dto.Filter) error {
|
||||
fs, ok := filterHandler.Options(scope.String())
|
||||
if !ok {
|
||||
return fmt.Errorf("unknown scope %s", scope)
|
||||
}
|
||||
filterNameSet := make(map[string]struct{})
|
||||
for _, filter := range filters {
|
||||
op, ok := fs[filter.Name]
|
||||
if !ok {
|
||||
return fmt.Errorf("%s filter %s not found", name, filter.Name)
|
||||
}
|
||||
for _, value := range filter.Values {
|
||||
if op.Pattern != nil && !op.Pattern.MatchString(value) {
|
||||
return fmt.Errorf("%s filter %s value %s not match pattern", name, filter.Name, value)
|
||||
}
|
||||
}
|
||||
|
||||
if len(filter.Values) == 0 {
|
||||
return fmt.Errorf("%s.Options can't be null. filter.Name:%s ", name, filter.Name)
|
||||
}
|
||||
|
||||
if _, has := filterNameSet[filter.Name]; has {
|
||||
return fmt.Errorf("%s.Name %s is reduplicative. ", name, filter.Name)
|
||||
}
|
||||
filterNameSet[filter.Name] = struct{}{}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type OptionTitle struct {
|
||||
Field string `json:"field"`
|
||||
Title string `json:"title" aoi18n:""`
|
||||
}
|
||||
|
||||
type IRemoteFilter interface {
|
||||
IFilter
|
||||
Titles() []OptionTitle
|
||||
Key() string
|
||||
Target() string
|
||||
RemoteList(ctx context.Context, keyword string, condition map[string]interface{}, page int, pageSize int) ([]any, int64, error)
|
||||
}
|
||||
|
||||
type IFilter interface {
|
||||
Name() string
|
||||
Title() string
|
||||
Labels(values ...string) []string
|
||||
Type() string
|
||||
Scopes() []string
|
||||
Option() *Option
|
||||
}
|
||||
|
||||
type IFilterHandler interface {
|
||||
RemoteFilter(name string) (IRemoteFilter, bool)
|
||||
Options(scope string) (map[string]*Option, bool)
|
||||
FilterLabel(name string, values []string) (*Info, error)
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Title string
|
||||
Label string
|
||||
}
|
||||
|
||||
type ScopeFilterOption eosc.Untyped[string, *Option]
|
||||
|
||||
type Handler struct {
|
||||
filters eosc.Untyped[string, IFilter]
|
||||
remoteFilters eosc.Untyped[string, IRemoteFilter]
|
||||
options eosc.Untyped[string, ScopeFilterOption]
|
||||
}
|
||||
|
||||
func NewHandler() *Handler {
|
||||
return &Handler{
|
||||
filters: eosc.BuildUntyped[string, IFilter](),
|
||||
remoteFilters: eosc.BuildUntyped[string, IRemoteFilter](),
|
||||
options: eosc.BuildUntyped[string, ScopeFilterOption](),
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Handler) RemoteFilter(name string) (IRemoteFilter, bool) {
|
||||
return f.remoteFilters.Get(name)
|
||||
}
|
||||
|
||||
func (f *Handler) RegisterRemoteFilter(filter IRemoteFilter) {
|
||||
f.remoteFilters.Set(filter.Name(), filter)
|
||||
f.setScopes(filter)
|
||||
}
|
||||
|
||||
func (f *Handler) RegisterFilter(filter IFilter) {
|
||||
f.filters.Set(filter.Name(), filter)
|
||||
f.setScopes(filter)
|
||||
}
|
||||
|
||||
func (f *Handler) setScopes(filter IFilter) {
|
||||
for _, scope := range filter.Scopes() {
|
||||
tmp, has := f.options.Get(scope)
|
||||
if !has {
|
||||
tmp = eosc.BuildUntyped[string, *Option]()
|
||||
f.options.Set(scope, tmp)
|
||||
}
|
||||
tmp.Set(filter.Name(), filter.Option())
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Handler) Options(scope string) (map[string]*Option, bool) {
|
||||
options, has := f.options.Get(scope)
|
||||
if !has {
|
||||
return nil, false
|
||||
}
|
||||
return options.All(), true
|
||||
}
|
||||
|
||||
func (f *Handler) FilterLabel(name string, values []string) (*Info, error) {
|
||||
if tmp, has := f.remoteFilters.Get(name); has {
|
||||
return &Info{
|
||||
Title: tmp.Title(),
|
||||
Label: strings.Join(tmp.Labels(values...), ","),
|
||||
}, nil
|
||||
}
|
||||
if tmp, has := f.filters.Get(name); has {
|
||||
return &Info{
|
||||
Title: tmp.Title(),
|
||||
Label: strings.Join(tmp.Labels(values...), ","),
|
||||
}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("filter %s not found", name)
|
||||
}
|
||||
|
||||
func RegisterRemoteFilter(filter IRemoteFilter) {
|
||||
filterHandler.RegisterRemoteFilter(filter)
|
||||
}
|
||||
|
||||
func RemoteFilter(name string) (IRemoteFilter, bool) {
|
||||
return filterHandler.RemoteFilter(name)
|
||||
}
|
||||
|
||||
func Options(scope string) (map[string]*Option, bool) {
|
||||
return filterHandler.Options(scope)
|
||||
}
|
||||
|
||||
func FilterLabel(name string, values []string) (*Info, error) {
|
||||
return filterHandler.FilterLabel(name, values)
|
||||
}
|
||||
|
||||
func FilterGet(name string) (IFilter, bool) {
|
||||
f, has := filterHandler.remoteFilters.Get(name)
|
||||
if has {
|
||||
return f, true
|
||||
}
|
||||
return filterHandler.filters.Get(name)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package strategy_filter
|
||||
|
||||
import "regexp"
|
||||
|
||||
var (
|
||||
CIDRIpv4Exp = `^(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([1-9]|[1-2]\d|3[0-2]))?$`
|
||||
)
|
||||
|
||||
var _ IFilter = &ipFilter{}
|
||||
|
||||
func init() {
|
||||
filterHandler.RegisterFilter(newIpFilter())
|
||||
}
|
||||
|
||||
type ipFilter struct {
|
||||
name string
|
||||
title string
|
||||
typ string
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
|
||||
func newIpFilter() *ipFilter {
|
||||
return &ipFilter{
|
||||
name: "ip",
|
||||
title: "IP",
|
||||
typ: TypePattern,
|
||||
pattern: regexp.MustCompile(CIDRIpv4Exp),
|
||||
}
|
||||
}
|
||||
|
||||
func (i *ipFilter) Name() string {
|
||||
return i.name
|
||||
}
|
||||
|
||||
func (i *ipFilter) Title() string {
|
||||
return i.title
|
||||
}
|
||||
|
||||
func (i *ipFilter) Labels(values ...string) []string {
|
||||
return values
|
||||
}
|
||||
|
||||
func (i *ipFilter) Type() string {
|
||||
return i.typ
|
||||
}
|
||||
|
||||
func (i *ipFilter) Scopes() []string {
|
||||
return []string{ScopeGlobal, ScopeService}
|
||||
}
|
||||
|
||||
func (i *ipFilter) Option() *Option {
|
||||
return &Option{
|
||||
Name: i.name,
|
||||
Title: i.title,
|
||||
Type: i.typ,
|
||||
Pattern: i.pattern,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package strategy_filter
|
||||
|
||||
import "net/http"
|
||||
|
||||
var _ IFilter = &methodFilter{}
|
||||
|
||||
func init() {
|
||||
filterHandler.RegisterFilter(newMethodFilter())
|
||||
}
|
||||
|
||||
type methodFilter struct {
|
||||
name string
|
||||
title string
|
||||
typ string
|
||||
options []string
|
||||
}
|
||||
|
||||
func newMethodFilter() *methodFilter {
|
||||
return &methodFilter{
|
||||
name: "method",
|
||||
title: "api method",
|
||||
typ: TypeStatic,
|
||||
options: []string{HttpALL, http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch, http.MethodHead, http.MethodOptions},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *methodFilter) Name() string {
|
||||
return m.name
|
||||
}
|
||||
|
||||
func (m *methodFilter) Title() string {
|
||||
return m.title
|
||||
}
|
||||
|
||||
func (m *methodFilter) Labels(values ...string) []string {
|
||||
if len(values) > 0 && values[0] != ValuesALL {
|
||||
return []string{"all method"}
|
||||
}
|
||||
if len(values) == 0 {
|
||||
return []string{"-"}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
func (m *methodFilter) Type() string {
|
||||
return m.typ
|
||||
}
|
||||
|
||||
func (m *methodFilter) Scopes() []string {
|
||||
return []string{ScopeGlobal, ScopeService}
|
||||
}
|
||||
|
||||
func (m *methodFilter) Option() *Option {
|
||||
return &Option{
|
||||
Name: m.name,
|
||||
Title: m.title,
|
||||
Type: m.typ,
|
||||
Options: m.options,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package strategy_filter
|
||||
|
||||
import "regexp"
|
||||
|
||||
var _ IFilter = &pathFilter{}
|
||||
|
||||
var (
|
||||
ApiPathRegexp = `^\*?[\w-/]+\*?$`
|
||||
)
|
||||
|
||||
type pathFilter struct {
|
||||
name string
|
||||
title string
|
||||
typ string
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
|
||||
func init() {
|
||||
filterHandler.RegisterFilter(newPathFilter())
|
||||
}
|
||||
|
||||
func newPathFilter() *pathFilter {
|
||||
return &pathFilter{
|
||||
name: "path",
|
||||
title: "api path",
|
||||
typ: TypePattern,
|
||||
pattern: regexp.MustCompile(ApiPathRegexp),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pathFilter) Name() string {
|
||||
return p.name
|
||||
}
|
||||
|
||||
func (p *pathFilter) Title() string {
|
||||
return p.title
|
||||
}
|
||||
|
||||
func (p *pathFilter) Labels(values ...string) []string {
|
||||
return values
|
||||
}
|
||||
|
||||
func (p *pathFilter) Type() string {
|
||||
return p.typ
|
||||
}
|
||||
|
||||
func (p *pathFilter) Scopes() []string {
|
||||
return []string{ScopeGlobal, ScopeService}
|
||||
}
|
||||
|
||||
func (p *pathFilter) Option() *Option {
|
||||
return &Option{
|
||||
Name: p.name,
|
||||
Title: p.title,
|
||||
Type: p.typ,
|
||||
Pattern: p.pattern,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user