Skip to content

Commit

Permalink
d2-AI prompt:
Browse files Browse the repository at this point in the history
{
  "prompt": "开发 K8s 中 NetworkPolicy 资源的 UI,它在菜单中的名字为“Network Policies”,父级菜单是网络。\n在列表中,增加一列展示 ingress 和 egress rules 的总量,以及一列用于展示出 pod selector 规则。\n\r\n\r\n\r\n在详情区域,增加对 ingress 和 egress 的展示。\r\n\r\n在 ingress 详情中,每个 ingress 用一个 tab 展示。渲染每个 ingress 时,根据 ingress.from 中各条规则的类型分别渲染:\r\n- IP block 类型,展示 CIDR 和 exceptions 字段;\r\n- Namespace Selector 类型,展示 key、operator、value,并统计选中了多少个 namespace;\r\n- Pod selector 类型,展示 key、operator、value,并统计选中了多少个 pod。\r\n最后再将 ingress.ports 展示出来,包含 port 和 protocol 信息。\r\n\r\ningress.from 的格式如下:\r\n```yaml\r\nfrom:\r\n  - ipBlock:\r\n      cidr: 172.17.0.0/16\r\n      except:\r\n        - 172.17.1.0/24\r\n  - namespaceSelector:\r\n      matchLabels:\r\n        project: myproject\r\n  - podSelector:\r\n      matchLabels:\r\n        role: frontend\r\n```\r\n\r\n在 egress 详情中,每个 egress 用一个 tab 展示。渲染每个 egress 时,根据 egress.to 中各条规则的类型分别渲染:\r\n- IP block 类型,展示 CIDR 和 exceptions 字段;\r\n最后再将 egress.ports 展示出来,包含 port 和 protocol 信息。\r\n\r\negress.to 的格式如下:\r\n```yaml\r\n      to:\r\n        - ipBlock:\r\n            cidr: 10.0.0.0/24\r\n```",
  "images": [
    "https://github.com/webzard-io/dovetail-v2/assets/13651389/a4976e91-fd81-4560-8fc9-fa7695b25a92"
  ]
}
  • Loading branch information
Yuyz0112 committed Dec 15, 2023
1 parent 5268a8d commit 754cb43
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/refine/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Route, Router } from 'react-router-dom';
import { Layout } from './components';
import { Dovetail } from './Dovetail';
import { ConfigMapConfig } from './pages/configmaps';
import { NetworkPolicyConfig } from './pages/networkpolicies';
import { CronJobForm, CronJobList, CronJobShow } from './pages/cronjobs';
import { DaemonSetForm, DaemonSetList, DaemonSetShow } from './pages/daemonsets';
import { DeploymentForm, DeploymentList, DeploymentShow } from './pages/deployments';
Expand Down Expand Up @@ -66,6 +67,7 @@ function App() {
ConfigMapConfig,
SecretsConfig,
ServicesConfig,
NetworkPolicyConfig,
];
}, []);

Expand Down
106 changes: 106 additions & 0 deletions packages/refine/src/components/ShowContent/fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,109 @@ export const ServicePodsField = (_: i18n): ShowField<ResourceModel> => {
},
};
};
import { List, Tabs, Table } from 'antd';
import { get } from 'lodash';
import {
NetworkPolicyEgressRule,
NetworkPolicyIngressRule,
} from 'kubernetes-types/networking/v1';

const { TabPane } = Tabs;

// IP block renderer
const IPBlockRenderer: React.FC<{ data: { cidr: string; except?: string[] } }> = ({
data,
}) => (
<>
<div>CIDR: {data.cidr}</div>
{data.except && (
<div>
Except:
<List
dataSource={data.except}
renderItem={item => <List.Item>{item}</List.Item>}
/>
</div>
)}
</>
);

// Namespace selector renderer
export const NamespaceSelectorField = (i18n: i18n): ShowField<ResourceModel> => ({
key: 'namespaceSelector',
title: i18n.t('namespaceSelector'),
path: ['rawYaml', 'ingress', 'from', 'namespaceSelector'],
render: selector => {
// Table data will be fetched and provided based on the `selector` criteria
const columns = [
{ key: 'key', title: 'Key', dataIndex: 'key' },
{ key: 'operator', title: 'Operator', dataIndex: 'operator' },
{ key: 'value', title: 'Value', dataIndex: 'value' },
];
return (
<Table
columns={columns}
dataSource={selector.matchLabels}
pagination={false}
size="small"
/>
);
},
});

// Pod selector renderer
export const PodSelectorField = (i18n: i18n): ShowField<ResourceModel> => ({
key: 'podSelector',
title: i18n.t('podSelector'),
path: ['rawYaml', 'ingress', 'from', 'podSelector'],
render: selector => {
// Table data will be fetched and provided based on the `selector` criteria
const columns = [
{ key: 'key', title: 'Key', dataIndex: 'key' },
{ key: 'operator', title: 'Operator', dataIndex: 'operator' },
{ key: 'value', title: 'Value', dataIndex: 'value' },
];
return (
<Table
columns={columns}
dataSource={selector.matchLabels}
pagination={false}
size="small"
/>
);
},
});

// Ingress ports renderer
export const IngressPortsField = (i18n: i18n): ShowField<ResourceModel> => ({
key: 'ingressPorts',
title: i18n.t('ingressPorts'),
path: ['rawYaml', 'ingress', 'ports'],
render: ports => (
<List
dataSource={ports || []}
renderItem={port => (
<List.Item>
Port: {port.port}, Protocol: {port.protocol}
</List.Item>
)}
/>
),
});

// Egress ports renderer
export const EgressPortsField = (i18n: i18n): ShowField<ResourceModel> => ({
key: 'egressPorts',
title: i18n.t('egressPorts'),
path: ['rawYaml', 'egress', 'ports'],
render: ports => (
<List
dataSource={ports || []}
renderItem={port => (
<List.Item>
Port: {port.port}, Protocol: {port.protocol}
</List.Item>
)}
/>
),
});
53 changes: 53 additions & 0 deletions packages/refine/src/hooks/useEagleTable/columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,56 @@ export const ServiceTypeColumnRenderer = <Model extends ResourceModel>(
sorter: CommonSorter(dataIndex),
};
};
import { NetworkPolicy } from 'kubernetes-types/networking/v1';

export const CountRulesColumnRenderer = (i18n: i18n): Column<ResourceModel> => {
return {
key: 'countRules',
display: true,
dataIndex: ['rawYaml'],
title: i18n.t('count_rules'),
sortable: true,
sorter: (a, b) => {
const aPolicy: NetworkPolicy = a.rawYaml;
const bPolicy: NetworkPolicy = b.rawYaml;
const aCount =
(get(aPolicy, 'spec.ingress', []).length || 0) +
(get(aPolicy, 'spec.egress', []).length || 0);
const bCount =
(get(bPolicy, 'spec.ingress', []).length || 0) +
(get(bPolicy, 'spec.egress', []).length || 0);
return aCount - bCount;
},
render: (value: NetworkPolicy) => {
const ingressCount = get(value, 'spec.ingress', []).length;
const egressCount = get(value, 'spec.egress', []).length;
return <span>{ingressCount + egressCount}</span>;
},
};
};

export const PodSelectorColumnRenderer = (i18n: i18n): Column<ResourceModel> => {
return {
key: 'podSelector',
display: true,
dataIndex: ['rawYaml'],
title: i18n.t('pod_selector'),
sortable: true,
sorter: (a, b) => {
// For sorting purposes, converting labels object to string
const aPolicy: NetworkPolicy = a.rawYaml;
const bPolicy: NetworkPolicy = b.rawYaml;
const aSelectorString = JSON.stringify(
get(aPolicy, 'spec.podSelector.matchLabels', {})
);
const bSelectorString = JSON.stringify(
get(bPolicy, 'spec.podSelector.matchLabels', {})
);
return aSelectorString.localeCompare(bSelectorString);
},
render: (value: NetworkPolicy) => {
const selectors = get(value, 'spec.podSelector.matchLabels', null);
return <span>{selectors ? JSON.stringify(selectors) : i18n.t('none')}</span>;
},
};
};
49 changes: 49 additions & 0 deletions packages/refine/src/pages/networkpolicies/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { CountRulesColumnRenderer } from '../../hooks/useEagleTable/columns';
import { PodSelectorColumnRenderer } from '../../hooks/useEagleTable/columns';
import { NamespaceSelectorField } from '../../components/ShowContent/fields';
import { PodSelectorField } from '../../components/ShowContent/fields';
import { IngressPortsField } from '../../components/ShowContent/fields';
import { EgressPortsField } from '../../components/ShowContent/fields';
import { i18n } from 'i18next';
import { RESOURCE_GROUP, ResourceConfig, WithId } from '../../types';
import { ResourceModel } from '../../model';
import { NetworkPolicy } from 'kubernetes-types/networking.k8s.io/v1';

const NETWORKPOLICY_INIT_VALUE = {
apiVersion: 'networking.k8s.io/v1',
kind: 'NetworkPolicy',
metadata: {
name: '',
namespace: 'default',
annotations: {},
labels: {},
},
spec: {
podSelector: {},
policyTypes: ['Ingress', 'Egress'],
},
};

export const NetworkPolicyConfig: ResourceConfig<WithId<NetworkPolicy>, ResourceModel> = {
name: 'networkpolicies',
kind: 'NetworkPolicy',
basePath: '/apis/networking.k8s.io/v1',
apiVersion: 'v1',
parent: RESOURCE_GROUP.NETWORK,
label: 'Network Policies',
columns: (i18n: i18n) => [
CountRulesColumnRenderer(i18n),
PodSelectorColumnRenderer(i18n),
],
showFields: (i18n: i18n) => [
[],
[],
[
NamespaceSelectorField(i18n),
PodSelectorField(i18n),
IngressPortsField(i18n),
EgressPortsField(i18n),
],
],
initValue: NETWORKPOLICY_INIT_VALUE,
};

0 comments on commit 754cb43

Please sign in to comment.