Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[master] fix: Add Ingresses and Volumes components to ResourceStatus view #4398

Merged
merged 1 commit into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@ module.exports = {
UNABLE_TO_ACCESS_TIP:
'Make sure that domain name resolution policies have been configured in your DNS server or the hosts file of your client machine.',
CERTIFICATE_VALUE: 'Certificate: {value}',
// Metadata
// Events
ROUTE_PATH: 'Path',
ROUTE_PORT: 'Port',
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ module.exports = {
UNABLE_TO_ACCESS_TIP:
'Make sure that domain name resolution policies have been configured in your DNS server or the hosts file of your client machine.',
CERTIFICATE_VALUE: 'Certificate: {value}',
ROUTE_PATH: 'Path',
ROUTE_PORT: 'Port',
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ module.exports = {
UNABLE_TO_ACCESS_TIP:
'Make sure that domain name resolution policies have been configured in your DNS server or the hosts file of your client machine.',
CERTIFICATE_VALUE: 'Certificate: {value}',
ROUTE_PATH: '路徑',
ROUTE_PORT: '端口',
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ module.exports = {
UNABLE_TO_ACCESS: '无法访问服务',
UNABLE_TO_ACCESS_TIP: '请确保已在您的 DNS 服务器或客户机 hosts 文件中配置域名解析规则。',
CERTIFICATE_VALUE: '证书:{value}',
ROUTE_PATH: '路径',
ROUTE_PORT: '端口',
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,70 +5,119 @@

import React, { useMemo } from 'react';
import { Link } from 'react-router-dom';
import { Field } from '@kubed/components';
import { getDisplayName } from '../../../../../../utils';
import Icon from '../../../../../Icon';
import { ItemWrapper } from '../styles';
import { AccessButton, RulesWrapper } from './styles';
import { AccessButton, Content, Path, Tip, Title } from './styles';
import { find, get, isEmpty } from 'lodash';
import { gatewayStore } from '../../../../../../stores';
import { Col, Row, Tooltip } from '@kubed/components';

const { useQueryNewGatewayByProject } = gatewayStore;
type Props = {
detail: any;
gateway: any;
ingress: any;
prefix?: string;
params: Record<string, string>;
};

function IngressesItem({ prefix, detail, gateway }: Props): JSX.Element {
const tls = detail.tls || [];
const ports = useMemo(() => {
const finalPorts: Record<string, any> = {};
if (gateway && gateway.ports && gateway.type === 'NodePort') {
gateway.ports.forEach((_port: any) => {
if (_port.name === 'http' && _port.nodePort !== 80) {
finalPorts.http = _port.nodePort;
}
if (_port.name === 'https' && _port.nodePort !== 443) {
finalPorts.https = _port.nodePort;
}
});
}
type Tls = {
hosts: string[];
secretName: string;
}[];

function IngressesItem({ prefix, ingress, params }: Props): JSX.Element {
const { data } = useQueryNewGatewayByProject(params, {
enabled: !!params.cluster && !!params.workspace,
});
const rules = get(ingress, 'spec.rules', []);
const ingressClassName = get(ingress, 'spec.ingressClassName', '');

return finalPorts;
}, []);
const gateway = useMemo(() => {
return find(data, item => item.ingressClass === ingressClassName);
}, [data, ingressClassName]);
const tls: Tls = get(ingress, 'spec.tls', []);

return (
<ItemWrapper>
<Field
className="mb12"
avatar={<Icon name="loadbalancer" size={40} />}
label={t('DOMAIN_NAME_VALUE', {
value: detail.rules.map((rule: any) => rule.host).join(', '),
})}
value={<Link to={`${prefix}/ingresses/${detail.name}`}>{getDisplayName(detail)}</Link>}
/>
<RulesWrapper>
{detail.rules.map((rule: any) => {
const protocol = tls.hosts && tls.hosts.includes(rule.host) ? 'https' : 'http';
let host = `${protocol}://${rule.host}`;
if (ports[protocol]) {
host = `${host}:${ports[protocol]}`;
{rules.map((rule: any) => {
const tlsItem = tls.find(item => item.hosts && item.hosts.includes(rule.host));
const protocol = tlsItem ? 'https' : 'http';
let host = rule.host;
const service = get(gateway, 'service', []);
if (!isEmpty(service)) {
const tempPort = find(service, item => item.name === protocol);
if (
tempPort &&
((protocol === 'http' && tempPort.nodePort !== 80) ||
(protocol === 'https' && tempPort.nodePort !== 443))
) {
host = `${host}:${tempPort.nodePort}`;
}

return rule.http.paths.map((path: any) => (
<li key={`${rule.host}${path.path}`}>
<span>URL:&nbsp;&nbsp;</span>
<span>
<strong>
{host}
{path.path}
</strong>
</span>
<a href={`${host}${path.path}`} target="_blank" rel="noreferrer noopener">
<AccessButton>{t('ACCESS_SERVICE')}</AccessButton>
</a>
</li>
));
})}
</RulesWrapper>
}
return (
<>
<Content>
<Icon name="earth" size={40} />
<Title>
{host}
<div>
<span>
{t('PROTOCOL_VALUE')}
{protocol.toUpperCase()}
</span>
{protocol === 'https' && (
<span>
{t('CERTIFICATE_VALUE')}
{tlsItem?.secretName}
</span>
)}
<Tip>
{t('UNABLE_TO_ACCESS')}
&nbsp;&nbsp;
<Tooltip content={t('UNABLE_TO_ACCESS_TIP')}>
<Icon name="question" />
</Tooltip>
</Tip>
</div>
</Title>
</Content>
{rule.http.paths.map((path: any, i: number) => (
<Path key={`${path.path}-${i}`}>
<Row>
<Col span={3}>
<span>
{t('ROUTE_PATH')}:<strong>{path.path}</strong>
</span>
</Col>
<Col span={3}>
<span>
{t('SERVICE_COLON')}
<strong>
<Link replace to={`${prefix}/services/${path.backend.service.name}`}>
{path.backend.service.name}
</Link>
</strong>
</span>
</Col>
<Col span={3}>
<span>
{t('ROUTE_PORT')}:<strong>{path.backend.service.port.number}</strong>
</span>
</Col>
<Col span={3}>
<a
href={`${protocol}://${host}${path.path}`}
target="_blank"
rel="noreferrer noopener"
>
<AccessButton>{t('ACCESS_SERVICE')}</AccessButton>
</a>
</Col>
</Row>
</Path>
))}
</>
);
})}
</ItemWrapper>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,48 @@
* https://github.com/kubesphere/console/blob/master/LICENSE
*/

import React, { useMemo } from 'react';
import { isEmpty } from 'lodash';
import { useQueries } from 'react-query';
import React, { useEffect, useMemo, useState } from 'react';

import { joinSelector } from '../../../../../../utils';
import { gatewayStore } from '../../../../../../stores';
import IngressesItem from './Item';
import ResourceCard from '../ResourceCard';
import { openpitrixStore } from '../../../../../../stores';
const { useBaseK8sList } = openpitrixStore;

const { fetchDetail } = gatewayStore;
import { EmptyTips } from './styles';

type Props = {
cluster?: string;
namespace?: string;
prefix?: string;
title?: string;
selector?: any;
};

function Ingresses({ title, cluster, namespace, selector, prefix }: Props): JSX.Element {
const k8sParams = useMemo(() => {
if (!isEmpty(selector)) {
return {
cluster,
namespace,
labelSelector: joinSelector(selector),
};
}
detail: any;

return {};
}, [selector]);
const gateWays = useQueries([
{
queryKey: ['gateWay', 'cluster', cluster],
queryFn: () => fetchDetail({ cluster }),
enabled: !!cluster,
},
{
queryKey: ['gateWay', 'namespace', cluster, namespace],
queryFn: () => fetchDetail({ cluster, namespace }),
enabled: !!cluster && !!namespace,
},
]);
const { data } = useBaseK8sList({
module: 'ingresses',
params: k8sParams,
autoFetch: gateWays[0].isSuccess && gateWays[1].isSuccess,
});
params: Record<string, string>;
};

function Ingresses({ detail, params }: Props): JSX.Element {
const { workspace, cluster, namespace } = params;
const prefix = workspace
? `/${workspace}/clusters/${cluster}/projects/${namespace}`
: `/clusters/${cluster}/projects/${namespace}`;
const [ingressList, setIngressList] = useState<any[]>([]);

const list = useMemo(
() =>
detail.map((item: any) => ({
...item,
module: item.kind,
...item.metadata,
})),
[detail],
);
useEffect(() => {
if (!list) return;
const ingressItems = list.filter((item: any) => item.kind === 'Ingress');
setIngressList(ingressItems);
}, [list]);
return (
<ResourceCard
title={title || t('ROUTE_PL')}
data={data}
title={t('ROUTE_PL')}
data={ingressList}
emptyPlaceholder={
<EmptyTips>{t('NO_AVAILABLE_RESOURCE_VALUE', { resource: t('ROUTE_PL') })}</EmptyTips>
}
itemRender={item => (
<IngressesItem
key={item.name}
prefix={prefix}
detail={item}
gateway={gateWays[0].data || gateWays[1].data}
/>
<IngressesItem params={params} key={item.name} prefix={prefix} ingress={item} />
)}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export const AccessButton = styled(Button)`
top: 50%;
right: 6px;
transform: translateY(-50%);
& span {
color: #242e42 !important;
}
`;

export const RulesWrapper = styled.ul`
Expand All @@ -28,3 +31,83 @@ export const RulesWrapper = styled.ul`
}
}
`;

export const EmptyTips = styled.div`
padding: 20px;
color: ${({ theme }) => theme.palette.accents_4};
font-size: 16px;
font-weight: 600;
line-height: 1.5;
background-color: ${({ theme }) => theme.palette.accents_0};
border-radius: 4px;
`;

export const CardWrapper = styled.div`
padding: 20px;
border-radius: 4px;
background-color: #f9fbfd;
transition: all 0.3s ease-in-out;

& + & {
margin-top: 8px;
}
`;

export const Content = styled.div`
position: relative;
margin-bottom: 12px;

& > svg {
vertical-align: middle;
}
`;

export const Title = styled.div`
display: inline-block;
margin-left: 20px;
margin-right: 20px;
font-weight: 600;
line-height: 1.43;
color: #242e42;
vertical-align: middle;

& > div {
font-size: 12px;
color: #79879c;
font-weight: 400;

span + span {
margin-left: 100px;
}
}
`;
export const Tip = styled.div`
position: absolute;
top: 24px;
right: 12px;
display: inline-flex;
align-items: center;
justify-content: center;
`;

export const Path = styled.div`
position: relative;
padding: 12px 20px;
border-radius: 22px;
background-color: #eff4f9;
border: solid 1px #ccd3db;

& + & {
margin-top: 8px;
}

span {
text-align: left;
color: #79879c;

strong {
line-height: 1.43;
color: #242e42;
}
}
`;
Loading
Loading