mirror of
https://github.com/APIParkLab/APIPark.git
synced 2026-06-26 16:01:56 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e449f86c01 | |||
| a1bdc048a7 | |||
| 0a1b08157d | |||
| d36c66371f | |||
| 517007c941 | |||
| 4c685a9ec6 | |||
| 1aca2099de | |||
| a93e5b4ff8 | |||
| 85d25bebe2 | |||
| 080bfc3a44 | |||
| f6956ddeca | |||
| 9f56fa5e14 | |||
| 22455e2301 | |||
| 8ed2c84b68 | |||
| ccd2a209e2 | |||
| 836c7699b8 |
+2
-1
@@ -2,4 +2,5 @@
|
|||||||
/.idea/
|
/.idea/
|
||||||
/config.yml
|
/config.yml
|
||||||
/build/
|
/build/
|
||||||
/apipark
|
/apipark
|
||||||
|
.gitlab-ci.yml
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -27,7 +27,7 @@ type imlAPIController struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_api_dto.CreateAPI) (*ai_api_dto.API, error) {
|
func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_api_dto.CreateAPI) (*ai_api_dto.API, error) {
|
||||||
info, err := i.serviceModule.Get(ctx, serviceId)
|
_, err := i.serviceModule.Get(ctx, serviceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_
|
|||||||
plugins["ai_formatter"] = api.PluginSetting{
|
plugins["ai_formatter"] = api.PluginSetting{
|
||||||
Config: plugin_model.ConfigType{
|
Config: plugin_model.ConfigType{
|
||||||
"model": input.AiModel.Id,
|
"model": input.AiModel.Id,
|
||||||
"provider": fmt.Sprintf("%s@ai-provider", info.Provider.Id),
|
"provider": fmt.Sprintf("%s@ai-provider", input.AiModel.Provider),
|
||||||
"config": input.AiModel.Config,
|
"config": input.AiModel.Config,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_
|
|||||||
Retry: input.Retry,
|
Retry: input.Retry,
|
||||||
Plugins: plugins,
|
Plugins: plugins,
|
||||||
},
|
},
|
||||||
Upstream: info.Provider.Id,
|
Upstream: input.AiModel.Provider,
|
||||||
Disable: false,
|
Disable: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -86,7 +86,7 @@ func (i *imlAPIController) Create(ctx *gin.Context, serviceId string, input *ai_
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string, input *ai_api_dto.EditAPI) (*ai_api_dto.API, error) {
|
func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string, input *ai_api_dto.EditAPI) (*ai_api_dto.API, error) {
|
||||||
info, err := i.serviceModule.Get(ctx, serviceId)
|
_, err := i.serviceModule.Get(ctx, serviceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -106,11 +106,11 @@ func (i *imlAPIController) Edit(ctx *gin.Context, serviceId string, apiId string
|
|||||||
proxy.Plugins["ai_formatter"] = api.PluginSetting{
|
proxy.Plugins["ai_formatter"] = api.PluginSetting{
|
||||||
Config: plugin_model.ConfigType{
|
Config: plugin_model.ConfigType{
|
||||||
"model": input.AiModel.Id,
|
"model": input.AiModel.Id,
|
||||||
"provider": fmt.Sprintf("%s@ai-provider", info.Provider.Id),
|
"provider": fmt.Sprintf("%s@ai-provider", input.AiModel.Provider),
|
||||||
"config": input.AiModel.Config,
|
"config": input.AiModel.Config,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
upstream = &info.Provider.Id
|
upstream = &input.AiModel.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
if input.AiPrompt != nil {
|
if input.AiPrompt != nil {
|
||||||
|
|||||||
@@ -326,7 +326,33 @@ func (i *imlServiceController) Create(ctx *gin.Context, teamID string, input *se
|
|||||||
if input.Kind == "ai" {
|
if input.Kind == "ai" {
|
||||||
return i.createAIService(ctx, teamID, input)
|
return i.createAIService(ctx, teamID, input)
|
||||||
}
|
}
|
||||||
return i.module.Create(ctx, teamID, input)
|
var err error
|
||||||
|
var info *service_dto.Service
|
||||||
|
err = i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||||
|
info, err = i.module.Create(txCtx, teamID, input)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
path := fmt.Sprintf("/%s/", strings.Trim(input.Prefix, "/"))
|
||||||
|
_, err = i.routerModule.Create(txCtx, info.Id, &router_dto.Create{
|
||||||
|
Id: uuid.New().String(),
|
||||||
|
Name: "",
|
||||||
|
Path: path + "*",
|
||||||
|
Methods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch, http.MethodOptions},
|
||||||
|
Description: "auto create by create service",
|
||||||
|
Protocols: []string{"http", "https"},
|
||||||
|
MatchRules: nil,
|
||||||
|
Upstream: "",
|
||||||
|
Proxy: &router_dto.InputProxy{
|
||||||
|
Path: path,
|
||||||
|
Timeout: 30000,
|
||||||
|
Retry: 0,
|
||||||
|
},
|
||||||
|
Disable: false,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
return info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlServiceController) Edit(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error) {
|
func (i *imlServiceController) Edit(ctx *gin.Context, id string, input *service_dto.EditService) (*service_dto.Service, error) {
|
||||||
|
|||||||
@@ -265,7 +265,8 @@ func (i *imlInitController) OnInit() {
|
|||||||
return fmt.Errorf("create default team error: %v", err)
|
return fmt.Errorf("create default team error: %v", err)
|
||||||
}
|
}
|
||||||
// 创建Rest服务
|
// 创建Rest服务
|
||||||
_, err = i.serviceModule.Create(ctx, info.Id, &service_dto.CreateService{
|
restPath := "/rest-demo"
|
||||||
|
serviceInfo, err := i.serviceModule.Create(ctx, info.Id, &service_dto.CreateService{
|
||||||
Name: "REST Demo Service",
|
Name: "REST Demo Service",
|
||||||
Prefix: "/rest-demo",
|
Prefix: "/rest-demo",
|
||||||
Description: "Auto created By APIPark",
|
Description: "Auto created By APIPark",
|
||||||
@@ -277,6 +278,26 @@ func (i *imlInitController) OnInit() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("create default service error: %v", err)
|
return fmt.Errorf("create default service error: %v", err)
|
||||||
}
|
}
|
||||||
|
path := fmt.Sprintf("/%s/", strings.Trim(restPath, "/"))
|
||||||
|
_, err = i.routerModule.Create(ctx, serviceInfo.Id, &router_dto.Create{
|
||||||
|
Id: uuid.NewString(),
|
||||||
|
Name: "",
|
||||||
|
Path: path + "*",
|
||||||
|
Methods: []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodDelete, http.MethodPatch, http.MethodOptions},
|
||||||
|
Description: "auto create by create service",
|
||||||
|
Protocols: []string{"http", "https"},
|
||||||
|
MatchRules: nil,
|
||||||
|
Upstream: "",
|
||||||
|
Proxy: &router_dto.InputProxy{
|
||||||
|
Path: path,
|
||||||
|
Timeout: 30000,
|
||||||
|
Retry: 0,
|
||||||
|
},
|
||||||
|
Disable: false,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("create default router error: %v", err)
|
||||||
|
}
|
||||||
// 创建AI服务
|
// 创建AI服务
|
||||||
err = i.createAIService(ctx, info.Id, &service_dto.CreateService{
|
err = i.createAIService(ctx, info.Id, &service_dto.CreateService{
|
||||||
Name: "AI Demo Service",
|
Name: "AI Demo Service",
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:@typescript-eslint/recommended",
|
||||||
|
"prettier"
|
||||||
|
],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": "latest",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["react", "@typescript-eslint", "prettier"],
|
||||||
|
"rules": {
|
||||||
|
"react/react-in-jsx-scope": "off",
|
||||||
|
"prettier/prettier": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "warn",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": ["warn"]
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"react": {
|
||||||
|
"version": "detect"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"printWidth": 100,
|
||||||
|
"bracketSpacing": true,
|
||||||
|
"arrowParens": "avoid",
|
||||||
|
"jsxSingleQuote": false
|
||||||
|
}
|
||||||
@@ -4,69 +4,88 @@ import { memo, useEffect, useMemo } from 'react';
|
|||||||
import { useGlobalContext } from '@common/contexts/GlobalStateContext';
|
import { useGlobalContext } from '@common/contexts/GlobalStateContext';
|
||||||
import { Icon } from '@iconify/react/dist/iconify.js';
|
import { Icon } from '@iconify/react/dist/iconify.js';
|
||||||
|
|
||||||
const LanguageSetting = ({mode = 'light'}:{mode?:'dark'|'light'}) => {
|
const LanguageSetting = ({ mode = 'light' }: { mode?: 'dark' | 'light' }) => {
|
||||||
const { dispatch,state} = useGlobalContext()
|
const { dispatch, state } = useGlobalContext();
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
key: 'en-US',
|
key: 'en-US',
|
||||||
label:<Button key="en" type="text" className="border-none p-0 flex items-center bg-transparent ">
|
label: (
|
||||||
English
|
<Button key="en" type="text" className="flex items-center p-0 bg-transparent border-none">
|
||||||
</Button>,
|
English
|
||||||
title:'English'
|
</Button>
|
||||||
},
|
),
|
||||||
{
|
title: 'English',
|
||||||
key: 'ja-JP',
|
},
|
||||||
label: <Button key="jp" type="text" className="border-none p-0 flex items-center bg-transparent ">
|
{
|
||||||
|
key: 'ja-JP',
|
||||||
|
label: (
|
||||||
|
<Button key="jp" type="text" className="flex items-center p-0 bg-transparent border-none">
|
||||||
日本語
|
日本語
|
||||||
</Button>,
|
</Button>
|
||||||
title: '日本語',
|
),
|
||||||
},
|
title: '日本語',
|
||||||
{
|
},
|
||||||
key: 'zh-TW',
|
{
|
||||||
label: <Button key="tw" type="text" className="border-none p-0 flex items-center bg-transparent ">
|
key: 'zh-TW',
|
||||||
繁體中文
|
label: (
|
||||||
</Button>,
|
<Button key="tw" type="text" className="flex items-center p-0 bg-transparent border-none">
|
||||||
title: '繁體中文',
|
繁體中文
|
||||||
},
|
</Button>
|
||||||
{
|
),
|
||||||
key: 'zh-CN',
|
title: '繁體中文',
|
||||||
label: <Button key="cn" type="text" className="border-none p-0 flex items-center bg-transparent ">
|
},
|
||||||
简体中文
|
{
|
||||||
</Button>,
|
key: 'zh-CN',
|
||||||
title: '简体中文',
|
label: (
|
||||||
},
|
<Button key="cn" type="text" className="flex items-center p-0 bg-transparent border-none">
|
||||||
|
简体中文
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
title: '简体中文',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const langLabel = useMemo(()=>items.find((item) => item?.key === state.language)?.title,[state.language])
|
const langLabel = useMemo(
|
||||||
|
() => items.find(item => item?.key === state.language)?.title,
|
||||||
|
[state.language]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(() => {
|
||||||
const savedLang = sessionStorage.getItem('i18nextLng')
|
const savedLang = sessionStorage.getItem('i18nextLng');
|
||||||
const browserLang = navigator.language || navigator.userLanguage
|
const browserLang = navigator.language || navigator.userLanguage;
|
||||||
if(savedLang){
|
if (savedLang) return;
|
||||||
dispatch({ type: 'UPDATE_LANGUAGE', language: savedLang });
|
|
||||||
}else{
|
dispatch({ type: 'UPDATE_LANGUAGE', language: browserLang });
|
||||||
dispatch({ type: 'UPDATE_LANGUAGE', language: browserLang });
|
}, []);
|
||||||
}
|
|
||||||
},[
|
|
||||||
])
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
trigger={['hover']}
|
trigger={['hover']}
|
||||||
menu={{
|
menu={{
|
||||||
items,
|
items,
|
||||||
style:{minWidth:'80px'},
|
style: { minWidth: '80px' },
|
||||||
onClick: (e) => {
|
onClick: e => {
|
||||||
const { key } = e;
|
const { key } = e;
|
||||||
dispatch({ type: 'UPDATE_LANGUAGE', language: key });
|
dispatch({ type: 'UPDATE_LANGUAGE', language: key });
|
||||||
i18n.changeLanguage(key);
|
i18n.changeLanguage(key);
|
||||||
}
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button className={`border-none ${mode==='dark' ? "text-[#333] hover:text-[#333333b3]" : "text-[#ffffffb3] hover:text-[#fff] "}`} type="default" ghost >
|
<Button
|
||||||
<span className='flex items-center gap-[8px]'> <Icon icon="ic:baseline-language" width="14" height="14"/>{langLabel}</span>
|
className={`border-none ${
|
||||||
</Button>
|
mode === 'dark'
|
||||||
|
? 'text-[#333] hover:text-[#333333b3]'
|
||||||
|
: 'text-[#ffffffb3] hover:text-[#fff] '
|
||||||
|
}`}
|
||||||
|
type="default"
|
||||||
|
ghost
|
||||||
|
>
|
||||||
|
<span className="flex items-center gap-[8px]">
|
||||||
|
{' '}
|
||||||
|
<Icon icon="ic:baseline-language" width="14" height="14" />
|
||||||
|
{langLabel}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default memo(LanguageSetting);
|
export default memo(LanguageSetting);
|
||||||
|
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ export interface IconParkIconElement extends HTMLElement {
|
|||||||
| 'apispace'
|
| 'apispace'
|
||||||
| 'auto-generate-api'
|
| 'auto-generate-api'
|
||||||
| 'compare-api'
|
| 'compare-api'
|
||||||
| 'multi-protocal'
|
| 'multi-protocol'
|
||||||
| 'read-good'
|
| 'read-good'
|
||||||
| 'richdoc'
|
| 'richdoc'
|
||||||
| 'mockapi'
|
| 'mockapi'
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ func NewDynamicClient(client admin_client.Client, resource string) (*DynamicClie
|
|||||||
cfg, has := gateway.GetDynamicResourceDriver(resource)
|
cfg, has := gateway.GetDynamicResourceDriver(resource)
|
||||||
if !has {
|
if !has {
|
||||||
return nil, errors.New("resource not found")
|
return nil, errors.New("resource not found")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &DynamicClient{client: client, profession: cfg.Profession, driver: cfg.Driver}, nil
|
return &DynamicClient{client: client, profession: cfg.Profession, driver: cfg.Driver}, nil
|
||||||
|
|||||||
+4
-36
@@ -57,42 +57,10 @@ var dynamicResourceMap = map[string]Worker{
|
|||||||
Profession: ProfessionCertificate,
|
Profession: ProfessionCertificate,
|
||||||
Driver: "server",
|
Driver: "server",
|
||||||
},
|
},
|
||||||
//"openai": {
|
"loki": {
|
||||||
// Profession: ProfessionAIProvider,
|
Profession: ProfessionOutput,
|
||||||
// Driver: "openai",
|
Driver: "loki",
|
||||||
//},
|
},
|
||||||
//"google": {
|
|
||||||
// Profession: ProfessionAIProvider,
|
|
||||||
// Driver: "google",
|
|
||||||
//},
|
|
||||||
//"anthropic": {
|
|
||||||
// Profession: ProfessionAIProvider,
|
|
||||||
// Driver: "anthropic",
|
|
||||||
//},
|
|
||||||
//"moonshot": {
|
|
||||||
// Profession: ProfessionAIProvider,
|
|
||||||
// Driver: "moonshot",
|
|
||||||
//},
|
|
||||||
//"tongyi": {
|
|
||||||
// Profession: ProfessionAIProvider,
|
|
||||||
// Driver: "tongyi",
|
|
||||||
//},
|
|
||||||
//"zhipuai": {
|
|
||||||
// Profession: ProfessionAIProvider,
|
|
||||||
// Driver: "zhipuai",
|
|
||||||
//},
|
|
||||||
//"fireworks": {
|
|
||||||
// Profession: ProfessionAIProvider,
|
|
||||||
// Driver: "fireworks",
|
|
||||||
//},
|
|
||||||
//"novita": {
|
|
||||||
// Profession: ProfessionAIProvider,
|
|
||||||
// Driver: "novita",
|
|
||||||
//},
|
|
||||||
//"mistralai": {
|
|
||||||
// Profession: ProfessionAIProvider,
|
|
||||||
// Driver: "mistralai",
|
|
||||||
//},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Worker struct {
|
type Worker struct {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type IFactory interface {
|
type IFactory interface {
|
||||||
Create(config string) (ILogDriver, error)
|
Create(config string) (ILogDriver, map[string]interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type factoryManager struct {
|
type factoryManager struct {
|
||||||
|
|||||||
+21
-7
@@ -11,6 +11,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/eolinker/eosc/log"
|
||||||
|
|
||||||
log_driver "github.com/APIParkLab/APIPark/log-driver"
|
log_driver "github.com/APIParkLab/APIPark/log-driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ func init() {
|
|||||||
type factory struct {
|
type factory struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *factory) Create(config string) (log_driver.ILogDriver, error) {
|
func (f *factory) Create(config string) (log_driver.ILogDriver, map[string]interface{}, error) {
|
||||||
|
|
||||||
return NewDriver(config)
|
return NewDriver(config)
|
||||||
}
|
}
|
||||||
@@ -35,24 +37,27 @@ type Driver struct {
|
|||||||
headers map[string]string
|
headers map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDriver(config string) (*Driver, error) {
|
func NewDriver(config string) (*Driver, map[string]interface{}, error) {
|
||||||
cfg := new(DriverConfig)
|
cfg := new(DriverConfig)
|
||||||
err := json.Unmarshal([]byte(config), cfg)
|
err := json.Unmarshal([]byte(config), cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
err = cfg.Check()
|
err = cfg.Check()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
headers := map[string]string{}
|
headers := map[string]string{}
|
||||||
for _, h := range cfg.Header {
|
for _, h := range cfg.Header {
|
||||||
headers[h.Key] = h.Value
|
headers[h.Key] = h.Value
|
||||||
}
|
}
|
||||||
return &Driver{
|
return &Driver{
|
||||||
url: cfg.URL,
|
url: cfg.URL,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
}, nil
|
}, map[string]interface{}{
|
||||||
|
"url": cfg.URL,
|
||||||
|
"headers": headers,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) LogInfo(clusterId string, id string) (*log_driver.LogInfo, error) {
|
func (d *Driver) LogInfo(clusterId string, id string) (*log_driver.LogInfo, error) {
|
||||||
@@ -66,6 +71,8 @@ func (d *Driver) LogInfo(clusterId string, id string) (*log_driver.LogInfo, erro
|
|||||||
queries.Set("start", strconv.FormatInt(start.UnixNano(), 10))
|
queries.Set("start", strconv.FormatInt(start.UnixNano(), 10))
|
||||||
queries.Set("end", strconv.FormatInt(now.UnixNano(), 10))
|
queries.Set("end", strconv.FormatInt(now.UnixNano(), 10))
|
||||||
queries.Set("limit", "1")
|
queries.Set("limit", "1")
|
||||||
|
log.Debug("query is ", queries.Get("query"))
|
||||||
|
|
||||||
list, err := send[LogInfo](http.MethodGet, fmt.Sprintf("%s/loki/api/v1/query_range", d.url), d.headers, queries, "")
|
list, err := send[LogInfo](http.MethodGet, fmt.Sprintf("%s/loki/api/v1/query_range", d.url), d.headers, queries, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -100,10 +107,13 @@ func (d *Driver) LogCount(clusterId string, conditions map[string]string, spendH
|
|||||||
}
|
}
|
||||||
queries := url.Values{}
|
queries := url.Values{}
|
||||||
queries.Set("query", fmt.Sprintf("sum(count_over_time({cluster=\"%s\"} | json %s [%dh])) by (%s)", clusterId, tmpCondition, spendHour, group))
|
queries.Set("query", fmt.Sprintf("sum(count_over_time({cluster=\"%s\"} | json %s [%dh])) by (%s)", clusterId, tmpCondition, spendHour, group))
|
||||||
|
sendRequestTime := time.Now()
|
||||||
list, err := send[LogCount](http.MethodGet, fmt.Sprintf("%s/loki/api/v1/query", d.url), d.headers, queries, "")
|
list, err := send[LogCount](http.MethodGet, fmt.Sprintf("%s/loki/api/v1/query", d.url), d.headers, queries, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
log.DebugF("send request spend time: %v", time.Now().Sub(sendRequestTime))
|
||||||
|
log.Debug("query is ", queries.Get("query"))
|
||||||
result := make(map[string]int64)
|
result := make(map[string]int64)
|
||||||
for _, l := range list {
|
for _, l := range list {
|
||||||
if len(l.Value) != 2 {
|
if len(l.Value) != 2 {
|
||||||
@@ -158,6 +168,7 @@ func (d *Driver) Logs(clusterId string, conditions map[string]string, start time
|
|||||||
queries.Set("limit", strconv.FormatInt(limit, 10))
|
queries.Set("limit", strconv.FormatInt(limit, 10))
|
||||||
queries.Set("direction", "backward")
|
queries.Set("direction", "backward")
|
||||||
queries.Set("start", strconv.FormatInt(start.UnixNano(), 10))
|
queries.Set("start", strconv.FormatInt(start.UnixNano(), 10))
|
||||||
|
log.Debug("query is ", queries.Get("query"))
|
||||||
logs, err := d.recuseLogs(queries, end, offset)
|
logs, err := d.recuseLogs(queries, end, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -259,10 +270,13 @@ func send[T any](method string, uri string, headers map[string]string, queries u
|
|||||||
for key, value := range headers {
|
for key, value := range headers {
|
||||||
req.Header.Set(key, value)
|
req.Header.Set(key, value)
|
||||||
}
|
}
|
||||||
|
log.DebugF("do request: %s", uri)
|
||||||
|
doRequestTime := time.Now()
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to send request: %w", err)
|
return nil, fmt.Errorf("failed to send request: %w", err)
|
||||||
}
|
}
|
||||||
|
log.DebugF("do request spend time: %v", time.Now().Sub(doRequestTime))
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
respData, err := io.ReadAll(resp.Body)
|
respData, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+1
-1
@@ -34,7 +34,7 @@ func newAIUpstream(provider string, uri model_runtime.IProviderURI) *gateway.Dyn
|
|||||||
"driver": "http",
|
"driver": "http",
|
||||||
"balance": "round-robin",
|
"balance": "round-robin",
|
||||||
"nodes": []string{fmt.Sprintf("%s weight=100", uri.Host())},
|
"nodes": []string{fmt.Sprintf("%s weight=100", uri.Host())},
|
||||||
"pass_node": "node",
|
"pass_host": "node",
|
||||||
"scheme": uri.Scheme(),
|
"scheme": uri.Scheme(),
|
||||||
"timeout": 300000,
|
"timeout": 300000,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package api_doc
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
api_doc_dto "github.com/APIParkLab/APIPark/module/api-doc/dto"
|
||||||
api_doc "github.com/APIParkLab/APIPark/service/api-doc"
|
api_doc "github.com/APIParkLab/APIPark/service/api-doc"
|
||||||
"github.com/APIParkLab/APIPark/service/service"
|
"github.com/APIParkLab/APIPark/service/service"
|
||||||
@@ -20,16 +21,19 @@ type imlAPIDocModule struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlAPIDocModule) UpdateDoc(ctx context.Context, serviceId string, input *api_doc_dto.UpdateDoc) (*api_doc_dto.ApiDocDetail, error) {
|
func (i *imlAPIDocModule) UpdateDoc(ctx context.Context, serviceId string, input *api_doc_dto.UpdateDoc) (*api_doc_dto.ApiDocDetail, error) {
|
||||||
_, err := i.serviceService.Get(ctx, serviceId)
|
info, err := i.serviceService.Get(ctx, serviceId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if input.Id == "" {
|
if input.Id == "" {
|
||||||
input.Id = uuid.New().String()
|
input.Id = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
// 每个API加上前缀
|
||||||
|
|
||||||
err = i.apiDocService.UpdateDoc(ctx, serviceId, &api_doc.UpdateDoc{
|
err = i.apiDocService.UpdateDoc(ctx, serviceId, &api_doc.UpdateDoc{
|
||||||
ID: input.Id,
|
ID: input.Id,
|
||||||
Content: input.Content,
|
Content: input.Content,
|
||||||
|
Prefix: info.Prefix,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package aksk
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
auth_driver "github.com/APIParkLab/APIPark/module/application-authorization/auth-driver"
|
auth_driver "github.com/APIParkLab/APIPark/module/application-authorization/auth-driver"
|
||||||
|
|
||||||
application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto"
|
application_authorization_dto "github.com/APIParkLab/APIPark/module/application-authorization/dto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,8 +26,7 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *Config) ID() string {
|
func (a *Config) ID() string {
|
||||||
//TODO implement me
|
return a.Ak
|
||||||
panic("implement me")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Config) Valid() ([]byte, error) {
|
func (a *Config) Valid() ([]byte, error) {
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ func (i *imlAuthorizationModule) getApplications(ctx context.Context, appIds []s
|
|||||||
Expire: a.ExpireTime,
|
Expire: a.ExpireTime,
|
||||||
Config: authCfg,
|
Config: authCfg,
|
||||||
HideCredential: a.HideCredential,
|
HideCredential: a.HideCredential,
|
||||||
|
Label: map[string]string{
|
||||||
|
"authorization": a.UUID,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|||||||
+167
-5
@@ -4,6 +4,13 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log_driver "github.com/APIParkLab/APIPark/log-driver"
|
||||||
|
|
||||||
|
"github.com/APIParkLab/APIPark/gateway"
|
||||||
|
|
||||||
|
"github.com/eolinker/go-common/store"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
@@ -13,15 +20,64 @@ import (
|
|||||||
|
|
||||||
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
||||||
"github.com/APIParkLab/APIPark/service/log"
|
"github.com/APIParkLab/APIPark/service/log"
|
||||||
|
log_print "github.com/eolinker/eosc/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ ILogModule = (*imlLogModule)(nil)
|
var _ ILogModule = (*imlLogModule)(nil)
|
||||||
|
|
||||||
type imlLogModule struct {
|
type imlLogModule struct {
|
||||||
service log.ILogService `autowired:""`
|
service log.ILogService `autowired:""`
|
||||||
|
clusterService cluster.IClusterService `autowired:""`
|
||||||
|
transaction store.ITransaction `autowired:""`
|
||||||
|
}
|
||||||
|
|
||||||
|
var labels = map[string]string{
|
||||||
|
"cluster": "$cluster",
|
||||||
|
"node": "$node",
|
||||||
|
}
|
||||||
|
var logFormatter = map[string]interface{}{
|
||||||
|
"fields": []string{
|
||||||
|
"$msec",
|
||||||
|
"$service",
|
||||||
|
"$provider",
|
||||||
|
"$scheme as request_scheme",
|
||||||
|
"$url as request_uri",
|
||||||
|
"$host as request_host",
|
||||||
|
"$header as request_header",
|
||||||
|
"$remote_addr",
|
||||||
|
"$request_body",
|
||||||
|
"$proxy_body",
|
||||||
|
"$proxy_method",
|
||||||
|
"$proxy_scheme",
|
||||||
|
"$proxy_uri",
|
||||||
|
"$api",
|
||||||
|
"$proxy_host",
|
||||||
|
"$proxy_header",
|
||||||
|
"$proxy_addr",
|
||||||
|
"$response_headers",
|
||||||
|
"$status",
|
||||||
|
"$content_type",
|
||||||
|
"$proxy_status",
|
||||||
|
"$request_time",
|
||||||
|
"$response_time",
|
||||||
|
"$node",
|
||||||
|
"$cluster",
|
||||||
|
"$application",
|
||||||
|
"$src_ip",
|
||||||
|
"$block_name as strategy",
|
||||||
|
"$request_id",
|
||||||
|
"$request_method",
|
||||||
|
"$authorization",
|
||||||
|
"$response_body",
|
||||||
|
"$proxy_response_body",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlLogModule) Save(ctx context.Context, driver string, input *log_dto.Save) error {
|
func (i *imlLogModule) Save(ctx context.Context, driver string, input *log_dto.Save) error {
|
||||||
|
factory, has := log_driver.GetFactory(driver)
|
||||||
|
if !has {
|
||||||
|
return errors.New("driver not found")
|
||||||
|
}
|
||||||
input.Cluster = cluster.DefaultClusterID
|
input.Cluster = cluster.DefaultClusterID
|
||||||
var cfg *string
|
var cfg *string
|
||||||
if input.Config != nil {
|
if input.Config != nil {
|
||||||
@@ -29,10 +85,57 @@ func (i *imlLogModule) Save(ctx context.Context, driver string, input *log_dto.S
|
|||||||
tmp := string(data)
|
tmp := string(data)
|
||||||
cfg = &tmp
|
cfg = &tmp
|
||||||
}
|
}
|
||||||
return i.service.UpdateLogSource(ctx, driver, &log.Save{
|
return i.transaction.Transaction(ctx, func(txCtx context.Context) error {
|
||||||
ID: input.ID,
|
err := i.service.UpdateLogSource(txCtx, driver, &log.Save{
|
||||||
Cluster: &input.Cluster,
|
ID: input.ID,
|
||||||
Config: cfg,
|
Cluster: &input.Cluster,
|
||||||
|
Config: cfg,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
info, err := i.service.GetLogSource(txCtx, driver)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d, c, err := factory.Create(info.Config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := i.clusterService.GatewayClient(txCtx, input.Cluster)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer client.Close(txCtx)
|
||||||
|
dynamicClient, err := client.Dynamic(driver)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
attr := make(map[string]interface{})
|
||||||
|
attr["driver"] = driver
|
||||||
|
attr["formatter"] = logFormatter
|
||||||
|
attr["labels"] = labels
|
||||||
|
attr["method"] = "POST"
|
||||||
|
attr["scopes"] = []string{"access_log"}
|
||||||
|
attr["type"] = "json"
|
||||||
|
for k, v := range c {
|
||||||
|
attr[k] = v
|
||||||
|
}
|
||||||
|
err = dynamicClient.Online(txCtx, &gateway.DynamicRelease{
|
||||||
|
BasicItem: &gateway.BasicItem{
|
||||||
|
ID: driver,
|
||||||
|
Description: "collect access log",
|
||||||
|
Version: time.Now().Format("20060102150405"),
|
||||||
|
Resource: gateway.ProfessionOutput,
|
||||||
|
},
|
||||||
|
Attr: attr,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log_driver.SetDriver(driver, d)
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,3 +163,62 @@ func (i *imlLogModule) Get(ctx context.Context, driver string) (*log_dto.LogSour
|
|||||||
UpdateAt: auto.TimeLabel(info.UpdateAt),
|
UpdateAt: auto.TimeLabel(info.UpdateAt),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *imlLogModule) OnComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *imlLogModule) initGateway(ctx context.Context, clusterId string, clientDriver gateway.IClientDriver) error {
|
||||||
|
drivers := log_driver.Drivers()
|
||||||
|
if len(drivers) < 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, driver := range drivers {
|
||||||
|
factory, has := log_driver.GetFactory(driver)
|
||||||
|
if !has {
|
||||||
|
log_print.Errorf("driver %s not found", driver)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
info, err := i.service.GetLogSource(ctx, driver)
|
||||||
|
if err != nil {
|
||||||
|
log_print.Errorf("get log source %s error: %s", driver, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d, c, err := factory.Create(info.Config)
|
||||||
|
if err != nil {
|
||||||
|
log_print.Errorf("create driver %s error: %s,config: %s", driver, err, info.Config)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log_driver.SetDriver(driver, d)
|
||||||
|
dynamicClient, err := clientDriver.Dynamic(driver)
|
||||||
|
if err != nil {
|
||||||
|
log_print.Errorf("get dynamic client %s error: %s", driver, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
attr := make(map[string]interface{})
|
||||||
|
attr["driver"] = driver
|
||||||
|
attr["formatter"] = logFormatter
|
||||||
|
attr["labels"] = labels
|
||||||
|
attr["method"] = "POST"
|
||||||
|
for k, v := range c {
|
||||||
|
attr[k] = v
|
||||||
|
}
|
||||||
|
err = dynamicClient.Online(ctx, &gateway.DynamicRelease{
|
||||||
|
BasicItem: &gateway.BasicItem{
|
||||||
|
ID: driver,
|
||||||
|
Description: "collect access log",
|
||||||
|
Version: time.Now().Format("20060102150405"),
|
||||||
|
Resource: gateway.ProfessionOutput,
|
||||||
|
},
|
||||||
|
Attr: attr,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log_print.Errorf("online driver %s error: %s", driver, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/eolinker/go-common/autowire"
|
"github.com/eolinker/go-common/autowire"
|
||||||
|
|
||||||
|
"github.com/APIParkLab/APIPark/gateway"
|
||||||
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
log_dto "github.com/APIParkLab/APIPark/module/log/dto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,7 +16,11 @@ type ILogModule interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
logModule := new(imlLogModule)
|
||||||
|
|
||||||
autowire.Auto[ILogModule](func() reflect.Value {
|
autowire.Auto[ILogModule](func() reflect.Value {
|
||||||
return reflect.ValueOf(new(imlLogModule))
|
|
||||||
|
gateway.RegisterInitHandleFunc(logModule.initGateway)
|
||||||
|
return reflect.ValueOf(logModule)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -359,3 +359,36 @@ func (i *imlStrategyModule) Delete(ctx context.Context, id string) error {
|
|||||||
}
|
}
|
||||||
return i.strategyService.SortDelete(ctx, id)
|
return i.strategyService.SortDelete(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *imlStrategyModule) initGateway(ctx context.Context, clusterId string, clientDriver gateway.IClientDriver) error {
|
||||||
|
commits, err := i.strategyService.ListLatestStrategyCommit(ctx, strategy_dto.ScopeGlobal, "")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
publishStrategies := make([]*eosc.Base[gateway.StrategyRelease], 0, len(commits))
|
||||||
|
for _, c := range commits {
|
||||||
|
l := c.Data
|
||||||
|
if l.IsDelete {
|
||||||
|
err = i.strategyService.Delete(ctx, l.Id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d, has := strategy_driver.GetDriver(l.Driver)
|
||||||
|
if !has {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
publishStrategies = append(publishStrategies, d.ToRelease(strategy_dto.ToStrategy(&strategy.Strategy{
|
||||||
|
Id: l.Id,
|
||||||
|
Name: l.Name,
|
||||||
|
Priority: l.Priority,
|
||||||
|
Filters: l.Filters,
|
||||||
|
Config: l.Config,
|
||||||
|
Driver: l.Driver,
|
||||||
|
IsStop: l.IsStop,
|
||||||
|
IsDelete: l.IsDelete,
|
||||||
|
}), nil, 5000))
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientDriver.Strategy().Online(ctx, publishStrategies...)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/APIParkLab/APIPark/gateway"
|
||||||
|
|
||||||
"github.com/eolinker/go-common/autowire"
|
"github.com/eolinker/go-common/autowire"
|
||||||
|
|
||||||
_ "github.com/APIParkLab/APIPark/module/strategy/driver/data-masking"
|
_ "github.com/APIParkLab/APIPark/module/strategy/driver/data-masking"
|
||||||
@@ -32,6 +34,7 @@ type IStrategyModule interface {
|
|||||||
func init() {
|
func init() {
|
||||||
strategyModule := new(imlStrategyModule)
|
strategyModule := new(imlStrategyModule)
|
||||||
autowire.Auto[IStrategyModule](func() reflect.Value {
|
autowire.Auto[IStrategyModule](func() reflect.Value {
|
||||||
|
gateway.RegisterInitHandleFunc(strategyModule.initGateway)
|
||||||
return reflect.ValueOf(strategyModule)
|
return reflect.ValueOf(strategyModule)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-1
@@ -76,6 +76,17 @@ func (i *imlAPIDocService) UpdateDoc(ctx context.Context, serviceId string, inpu
|
|||||||
if err := doc.Valid(); err != nil {
|
if err := doc.Valid(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if input.Prefix != "" {
|
||||||
|
err = doc.AddPrefixInAll(input.Prefix)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data, err := doc.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
input.Content = string(data)
|
||||||
|
|
||||||
info, err := i.store.First(ctx, map[string]interface{}{
|
info, err := i.store.First(ctx, map[string]interface{}{
|
||||||
"service": serviceId,
|
"service": serviceId,
|
||||||
@@ -94,9 +105,9 @@ func (i *imlAPIDocService) UpdateDoc(ctx context.Context, serviceId string, inpu
|
|||||||
APICount: doc.APICount(),
|
APICount: doc.APICount(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
info.Content = input.Content
|
||||||
info.Updater = operator
|
info.Updater = operator
|
||||||
info.UpdateAt = time.Now()
|
info.UpdateAt = time.Now()
|
||||||
info.Content = input.Content
|
|
||||||
info.APICount = doc.APICount()
|
info.APICount = doc.APICount()
|
||||||
return i.store.Save(ctx, info)
|
return i.store.Save(ctx, info)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import "time"
|
|||||||
type UpdateDoc struct {
|
type UpdateDoc struct {
|
||||||
ID string
|
ID string
|
||||||
Content string
|
Content string
|
||||||
|
Prefix string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Doc struct {
|
type Doc struct {
|
||||||
|
|||||||
+32
-10
@@ -3,10 +3,14 @@ package api_doc
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
yaml "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
"github.com/APIParkLab/APIPark/service/universally/commit"
|
"github.com/APIParkLab/APIPark/service/universally/commit"
|
||||||
"github.com/eolinker/go-common/autowire"
|
"github.com/eolinker/go-common/autowire"
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
"github.com/getkin/kin-openapi/openapi3"
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type IAPIDocService interface {
|
type IAPIDocService interface {
|
||||||
@@ -65,15 +69,6 @@ func (d *DocLoader) Valid() error {
|
|||||||
if d.openAPI3Doc.Paths == nil {
|
if d.openAPI3Doc.Paths == nil {
|
||||||
return fmt.Errorf("openAPI3Doc.Paths is nil")
|
return fmt.Errorf("openAPI3Doc.Paths is nil")
|
||||||
}
|
}
|
||||||
//err := d.openAPI3Doc.Validate(openapi3Loader.Context)
|
|
||||||
//if err != nil {
|
|
||||||
// openAPI2Doc, err := openapi2conv.FromV3(d.openAPI3Doc)
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// validate.
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,3 +105,30 @@ func (d *DocLoader) APICount() int64 {
|
|||||||
}
|
}
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DocLoader) AddPrefixInAll(prefix string) error {
|
||||||
|
prefix = strings.TrimSpace(prefix)
|
||||||
|
if prefix == "" || d.openAPI3Doc == nil || d.openAPI3Doc.Paths == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix = fmt.Sprintf("/%s/", strings.Trim(prefix, "/"))
|
||||||
|
for path, item := range d.openAPI3Doc.Paths.Map() {
|
||||||
|
path = strings.TrimSpace(path)
|
||||||
|
if strings.HasPrefix(path, prefix) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
newPath := fmt.Sprintf("%s%s", prefix, strings.TrimPrefix(path, "/"))
|
||||||
|
d.openAPI3Doc.Paths.Delete(path)
|
||||||
|
d.openAPI3Doc.Paths.Set(newPath, item)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DocLoader) Marshal() ([]byte, error) {
|
||||||
|
result, err := d.openAPI3Doc.MarshalYAML()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return yaml.Marshal(result)
|
||||||
|
}
|
||||||
|
|||||||
@@ -162,6 +162,9 @@ func (i *imlAPIService) Save(ctx context.Context, id string, model *Edit) error
|
|||||||
if model.Disable != nil {
|
if model.Disable != nil {
|
||||||
ev.Disable = *model.Disable
|
ev.Disable = *model.Disable
|
||||||
}
|
}
|
||||||
|
if model.Upstream != nil {
|
||||||
|
ev.Upstream = *model.Upstream
|
||||||
|
}
|
||||||
|
|
||||||
e := i.apiInfoStore.Save(ctx, ev)
|
e := i.apiInfoStore.Save(ctx, ev)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
|
|||||||
+16
-15
@@ -5,6 +5,8 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log_print "github.com/eolinker/eosc/log"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
log_driver "github.com/APIParkLab/APIPark/log-driver"
|
log_driver "github.com/APIParkLab/APIPark/log-driver"
|
||||||
@@ -26,29 +28,31 @@ type imlLogService struct {
|
|||||||
|
|
||||||
func (i *imlLogService) OnComplete() {
|
func (i *imlLogService) OnComplete() {
|
||||||
drivers := log_driver.Drivers()
|
drivers := log_driver.Drivers()
|
||||||
for _, d := range drivers {
|
if len(drivers) < 1 {
|
||||||
factory, has := log_driver.GetFactory(d)
|
return
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
for _, driver := range drivers {
|
||||||
|
factory, has := log_driver.GetFactory(driver)
|
||||||
if !has {
|
if !has {
|
||||||
|
log_print.Errorf("driver %s not found", driver)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s, err := i.GetLogSource(context.Background(), d)
|
info, err := i.GetLogSource(ctx, driver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log_print.Errorf("get log source %s error: %s", driver, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
driver, err := factory.Create(s.Config)
|
d, _, err := factory.Create(info.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log_print.Errorf("create driver %s error: %s,config: %s", driver, err, info.Config)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
log_driver.SetDriver(d, driver)
|
log_driver.SetDriver(driver, d)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *imlLogService) UpdateLogSource(ctx context.Context, driver string, input *Save) error {
|
func (i *imlLogService) UpdateLogSource(ctx context.Context, driver string, input *Save) error {
|
||||||
factory, has := log_driver.GetFactory(driver)
|
|
||||||
if !has {
|
|
||||||
return errors.New("driver not found")
|
|
||||||
}
|
|
||||||
s, err := i.store.First(ctx, map[string]interface{}{"driver": driver})
|
s, err := i.store.First(ctx, map[string]interface{}{"driver": driver})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
@@ -83,15 +87,12 @@ func (i *imlLogService) UpdateLogSource(ctx context.Context, driver string, inpu
|
|||||||
s.Updater = utils.UserId(ctx)
|
s.Updater = utils.UserId(ctx)
|
||||||
s.UpdateAt = time.Now()
|
s.UpdateAt = time.Now()
|
||||||
}
|
}
|
||||||
newDriver, err := factory.Create(s.Config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = i.store.Save(ctx, s)
|
err = i.store.Save(ctx, s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log_driver.SetDriver(driver, newDriver)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user