Skip to content

Commit

Permalink
feat: 路由列表支持查看已启用策略,策略列表标注已启用策略 (higress-group#429)
Browse files Browse the repository at this point in the history
  • Loading branch information
VinciWu557 authored Feb 26, 2025
1 parent 0a992d2 commit d343d96
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,8 @@ public void deleteServiceInstance(@PathVariable("serviceName") @NotBlank String

private ResponseEntity<PaginatedResponse<WasmPluginInstance>> listInstances(WasmPluginInstanceScope scope,
String target) {
List<WasmPluginInstance> instances = wasmPluginInstanceService.list(scope, target);
instances.removeIf(WasmPluginInstance::isInternal);
List<WasmPluginInstance> instances = wasmPluginInstanceService.list(scope, target).
stream().filter(instance -> !instance.isInternal()).toList();
return ControllerUtil.buildResponseEntity(PaginatedResult.createFromFullList(instances, null));
}

Expand Down
55 changes: 54 additions & 1 deletion frontend/src/interfaces/route.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { getRoutePluginInstances } from "@/services";
import { BUILTIN_ROUTE_PLUGIN_LIST } from "@/pages/plugin/components/PluginList/constant";
import { message } from "antd";

export interface CorsConfig {
allowOrigins: string[];
allowMethods: string[];
allowHeaders: string[];
exposeHeader: string[];
maxAgent?: number;
allowCredentials?: boolean;
enabled: boolean;
}

export interface Header {
Expand All @@ -15,6 +20,7 @@ export interface Header {
export interface HeaderModifyConfig {
request: HeaderModifyStageConfig;
response: HeaderModifyStageConfig;
enabled: boolean;
}

export interface HeaderModifyStageConfig {
Expand All @@ -26,24 +32,29 @@ export interface HeaderModifyStageConfig {
export interface MockConfig {
status: number;
url: string;
enabled: boolean;
}
export interface RateLimitConfig {
qps: number;
enabled: boolean;
}

export interface RedirectConfig {
status: number;
url: string;
enabled: boolean;
}

export interface RetryConfig {
attempt: number;
retryOn: string;
enabled: boolean;
}

export interface RewriteConfig {
path?: string;
host?: string;
enabled: boolean;
}

export interface RoutePredicate {
Expand Down Expand Up @@ -115,7 +126,49 @@ export interface WasmPluginData {
customConfigs?: {
[key: string]: string;
};

enabled?: boolean;
internal?: boolean;
resKey?: string;
key?: string;
}

export const getRouteBuiltInPlugins = (route: Route): WasmPluginData[] => {
const PLUGIN_KEY_TO_PROPERTY: Record<string, string> = {
retries: 'proxyNextUpstream',
headerModify: 'headerControl',
};

return BUILTIN_ROUTE_PLUGIN_LIST.filter(pluginConfig => {
const routeProperty = PLUGIN_KEY_TO_PROPERTY[pluginConfig.key] || pluginConfig.key;
return route[routeProperty]?.enabled;
}).map(pluginConfig => ({
name: pluginConfig.key,
title: pluginConfig.title,
description: pluginConfig.description,
internal: true,
builtIn: true,
enabled: true,
}));
}

export const fetchPluginsByRoute = async (record: Route): Promise<WasmPluginData[]> => {
const data: Record<string, WasmPluginData[]> = {};
try {
const response = await getRoutePluginInstances(record.name);
const plugins = response.map((plugin: { pluginName: any; description: any; enabled: any; internal: any }) => {
return {
...plugin,
name: plugin.pluginName,
enabled: plugin.enabled,
internal: plugin.internal,
};
});
data[record.name] = plugins || [];
} catch (error) {
message.error(`Failed to fetch strategies: ${error.message || error}`);
}

const builtInPlugins = getRouteBuiltInPlugins(record);
data[record.name] = data[record.name] ? data[record.name].concat(builtInPlugins) : builtInPlugins;
return data[record.name] || [];
};
3 changes: 3 additions & 0 deletions frontend/src/locales/en-US/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,14 @@
},
"plugins": {
"title": "Strategy Configuration",
"description": "Strategy Description",
"subTitle": {
"domain": "Domain Name: ",
"route": "Route Name: ",
"aiRoute": "AI Route Name: "
},
"enabled": "Enabled",
"emptyPlugins": "No plugins configured.",
"addPlugin": "Add Plugin",
"editPlugin": "Edit Plugin",
"addSuccess": "Added successfully.",
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/locales/zh-CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,14 @@
},
"plugins": {
"title": "策略配置",
"description": "策略描述",
"subTitle": {
"domain": "域名名称:",
"route": "路由名称:",
"aiRoute": "AI路由名称:"
},
"enabled": "已启用",
"emptyPlugins": "未启用策略",
"addPlugin": "添加插件",
"editPlugin": "编辑插件",
"addSuccess": "添加成功",
Expand Down Expand Up @@ -595,6 +598,8 @@
"close": "关闭",
"save": "保存",
"strategy": "策略",
"strategyList": "策略列表",
"description": "描述",
"configure": "配置",
"information": "信息",
"action": "操作",
Expand Down
50 changes: 42 additions & 8 deletions frontend/src/pages/plugin/components/PluginList/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import i18n from '@/i18n';
import { WasmPluginData } from '@/interfaces/route';
import { getWasmPlugins } from '@/services';
import { fetchPluginsByRoute, WasmPluginData } from '@/interfaces/route';
import { getGatewayRouteDetail, getWasmPlugins } from '@/services';
import { EllipsisOutlined } from '@ant-design/icons';
import { useRequest } from 'ahooks';
import { Avatar, Button, Card, Col, Dropdown, Popconfirm, Row, Typography } from 'antd';
import { Avatar, Button, Card, Col, Dropdown, Popconfirm, Row, Typography, Tag } from 'antd';
import { useSearchParams } from 'ice';
import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -41,18 +41,44 @@ const PluginList = forwardRef((props: Props, ref) => {
const [pluginList, setPluginList] = useState<WasmPluginData[]>([]);

const { loading, run: loadWasmPlugins } = useRequest(() => {
return getWasmPlugins(i18n.language)
return getWasmPlugins(i18n.language);
}, {
manual: true,
onSuccess: (result = []) => {
onSuccess: async (result = []) => {
let plugins = result || [];
if (type === QueryType.ROUTE) {
plugins = BUILTIN_ROUTE_PLUGIN_LIST.concat(plugins);
}
const hiddenPlugins = HIDDEN_PLUGINS_BY_QUERY_TYPE[type];
if (Array.isArray(hiddenPlugins)) {
plugins = plugins.filter(p => p.builtIn && hiddenPlugins.indexOf(p.name) === -1);
}
if (type === QueryType.ROUTE) {
const routeName = searchParams.get('name');
if (routeName) {
const currentRoute = await getGatewayRouteDetail(routeName);
if (!currentRoute) {
plugins = BUILTIN_ROUTE_PLUGIN_LIST.concat(plugins);
setPluginList(plugins);
return
}

const pluginByRoutes = await fetchPluginsByRoute(currentRoute);
const builtInPlugins: WasmPluginData[] = BUILTIN_ROUTE_PLUGIN_LIST.map((plugin) => {
const foundPlugin = pluginByRoutes.find((p) => p.name === plugin.key && p.internal);
return {
...plugin,
name: plugin.key,
enabled: foundPlugin ? foundPlugin.enabled : false,
};
});
const updatedPlugins = result.map((plugin: { name: string }) => {
const foundPlugin = pluginByRoutes.find((p) => p.name === plugin.name);
return {
...plugin,
enabled: foundPlugin ? foundPlugin.enabled : false,
};
});
plugins = builtInPlugins.concat(updatedPlugins)
}
}
setPluginList(plugins);
},
});
Expand Down Expand Up @@ -120,6 +146,7 @@ const PluginList = forwardRef((props: Props, ref) => {
<Row gutter={[16, 16]}>
{pluginList.map((item) => {
const key = item.key || `${item.name}:${item.imageVersion}`;
const showTag = type === QueryType.ROUTE;
return (
<Col span={6} key={key} xl={6} lg={12} md={12} sm={12} xs={24}>
<Card
Expand Down Expand Up @@ -149,6 +176,13 @@ const PluginList = forwardRef((props: Props, ref) => {
<div style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{getI18nValue(item, 'title')}
</div>
{showTag && item.enabled && (
<Tag
color="green"
style={{ marginLeft: 6, fontSize: '10px', lineHeight: '16px', padding: '0 4px', borderRadius: '2px' }}
>{t('plugins.enabled')}
</Tag>
)}
{
createPluginDropdown(item)
}
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/pages/plugin/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,21 @@ export default function RouterConfig() {
updateWasmPlugin(val.name, val).then(() => {
message.success(t('plugins.updateSuccess'));
formOperatorBack();
listRef.current?.refresh();
});
} else {
createWasmPlugin(val).then(() => {
message.success(t('plugins.addSuccess'));
formOperatorBack();
listRef.current?.refresh();
});
}
};

const init = () => {
if (name && type === 'route') {
loadRouteDetail(name);
loadRouteDetail(name)
listRef.current?.refresh();
}
};

Expand Down
Loading

0 comments on commit d343d96

Please sign in to comment.