fix(kube-tables): update table accessor fns [EE-5464] (#8920)

* fix(services): update accessor fns [EE-5464]

* small fixes

---------

Co-authored-by: testa113 <testa113>
pull/8720/head
Ali 2023-05-11 12:55:15 +12:00 committed by GitHub
parent 22f4c5d650
commit 42fce1ec57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 148 additions and 108 deletions

View File

@ -21,6 +21,7 @@ import { useTableState } from '@@/datatables/useTableState';
import { useMutationDeleteServices, useServices } from '../service';
import { Service } from '../types';
import { DefaultDatatableSettings } from '../../datatables/DefaultDatatableSettings';
import { isSystemNamespace } from '../../namespaces/utils';
import { columns } from './columns';
import { createStore } from './datatable-store';
@ -40,7 +41,7 @@ export function ServicesDatatable() {
const filteredServices = servicesQuery.data?.filter(
(service) =>
(isAdmin && tableState.showSystemResources) ||
!KubernetesNamespaceHelper.isSystemNamespace(service.Namespace)
!isSystemNamespace(service.Namespace)
);
return (

View File

@ -1,38 +1,41 @@
import { columnHelper } from './helper';
export const clusterIP = columnHelper.accessor('ClusterIPs', {
header: 'Cluster IP',
id: 'clusterIP',
cell: ({ getValue }) => {
const clusterIPs = getValue();
export const clusterIP = columnHelper.accessor(
(row) => row.ClusterIPs?.join(','),
{
header: 'Cluster IP',
id: 'clusterIP',
cell: ({ row }) => {
const clusterIPs = row.original.ClusterIPs;
if (!clusterIPs?.length) {
return '-';
}
return clusterIPs.map((ip) => <div key={ip}>{ip}</div>);
},
sortingFn: (rowA, rowB) => {
const a = rowA.original.ClusterIPs;
const b = rowB.original.ClusterIPs;
const ipA = a?.[0];
const ipB = b?.[0];
// no ip's at top, followed by 'None', then ordered by ip
if (!ipA) return 1;
if (!ipB) return -1;
if (ipA === ipB) return 0;
if (ipA === 'None') return 1;
if (ipB === 'None') return -1;
// natural sort of the ip
return ipA.localeCompare(
ipB,
navigator.languages[0] || navigator.language,
{
numeric: true,
ignorePunctuation: true,
if (!clusterIPs?.length) {
return '-';
}
);
},
});
return clusterIPs.map((ip) => <div key={ip}>{ip}</div>);
},
sortingFn: (rowA, rowB) => {
const a = rowA.original.ClusterIPs;
const b = rowB.original.ClusterIPs;
const ipA = a?.[0];
const ipB = b?.[0];
// no ip's at top, followed by 'None', then ordered by ip
if (!ipA) return 1;
if (!ipB) return -1;
if (ipA === ipB) return 0;
if (ipA === 'None') return 1;
if (ipB === 'None') return -1;
// natural sort of the ip
return ipA.localeCompare(
ipB,
navigator.languages[0] || navigator.language,
{
numeric: true,
ignorePunctuation: true,
}
);
},
}
);

View File

@ -2,19 +2,22 @@ import { formatDate } from '@/portainer/filters/filters';
import { columnHelper } from './helper';
export const created = columnHelper.accessor('CreationTimestamp', {
header: 'Created',
id: 'created',
cell: ({ row, getValue }) => {
const date = formatDate(getValue());
const owner =
row.original.Labels?.['io.portainer.kubernetes.application.owner'];
if (owner) {
return `${date} by ${owner}`;
}
return date;
export const created = columnHelper.accessor(
(row) => {
const owner = row.Labels?.['io.portainer.kubernetes.application.owner'];
const date = formatDate(row.CreationTimestamp);
return owner ? `${date} by ${owner}` : date;
},
});
{
header: 'Created',
id: 'created',
cell: ({ row }) => {
const date = formatDate(row.original.CreationTimestamp);
const owner =
row.original.Labels?.['io.portainer.kubernetes.application.owner'];
return owner ? `${date} by ${owner}` : date;
},
}
);

View File

@ -8,14 +8,14 @@ import { columnHelper } from './helper';
export const externalIP = columnHelper.accessor(
(row) => {
if (row.Type === 'ExternalName') {
return row.ExternalName;
return row.ExternalName || '';
}
if (row.ExternalIPs?.length) {
return row.ExternalIPs?.slice(0);
return row.ExternalIPs?.join(',') || '';
}
return row.IngressStatus?.slice(0);
return row.IngressStatus?.map((status) => status.IP).join(',') || '';
},
{
header: 'External IP',

View File

@ -1,37 +1,53 @@
import { Authorized } from '@/react/hooks/useUser';
import KubernetesNamespaceHelper from '@/kubernetes/helpers/namespaceHelper';
import { isSystemNamespace } from '@/react/kubernetes/namespaces/utils';
import { columnHelper } from './helper';
export const name = columnHelper.accessor('Name', {
header: 'Name',
id: 'name',
cell: ({ row, getValue }) => {
const name = getValue();
const isSystem = KubernetesNamespaceHelper.isSystemNamespace(
row.original.Namespace
);
export const name = columnHelper.accessor(
(row) => {
let name = row.Name;
const isExternal =
!row.original.Labels ||
!row.original.Labels['io.portainer.kubernetes.application.owner'];
!row.Labels || !row.Labels['io.portainer.kubernetes.application.owner'];
const isSystem = isSystemNamespace(row.Namespace);
return (
<Authorized authorizations="K8sServiceW" childrenUnauthorized={name}>
{name}
if (isExternal && !isSystem) {
name = `${name} external`;
}
{isSystem && (
<span className="label label-info image-tag label-margins">
system
</span>
)}
{isExternal && !isSystem && (
<span className="label label-primary image-tag label-margins">
external
</span>
)}
</Authorized>
);
if (isSystem) {
name = `${name} system`;
}
return name;
},
});
{
header: 'Name',
id: 'Name',
cell: ({ row }) => {
const name = row.original.Name;
const isSystem = isSystemNamespace(row.original.Namespace);
const isExternal =
!row.original.Labels ||
!row.original.Labels['io.portainer.kubernetes.application.owner'];
return (
<Authorized authorizations="K8sServiceW" childrenUnauthorized={name}>
{name}
{isSystem && (
<span className="label label-info image-tag label-margins">
system
</span>
)}
{isExternal && !isSystem && (
<span className="label label-primary image-tag label-margins">
external
</span>
)}
</Authorized>
);
},
}
);

View File

@ -4,7 +4,12 @@ import { columnHelper } from './helper';
export const ports = columnHelper.accessor(
(row) =>
row.Ports.map((port) => `${port.Port}:${port.NodePort}/${port.Protocol}`),
row.Ports.map(
(port) =>
`${port.Port}${port.NodePort !== 0 ? `:${port.NodePort}` : ''}/${
port.Protocol
}`
).join(',') || '-',
{
header: () => (
<>

View File

@ -1,13 +1,12 @@
import { columnHelper } from './helper';
export const targetPorts = columnHelper.accessor(
(row) => row.Ports.map((port) => `${port.TargetPort}`),
(row) => row.Ports.map((port) => port.TargetPort).join(','),
{
header: 'Target Ports',
id: 'targetPorts',
cell: ({ getValue }) => {
const ports = getValue();
cell: ({ row }) => {
const ports = row.original.Ports.map((port) => port.TargetPort);
if (!ports.length) {
return '-';
}

View File

@ -2,18 +2,21 @@ import { formatDate } from '@/portainer/filters/filters';
import { columnHelper } from './helper';
export const created = columnHelper.accessor('CreationDate', {
header: 'Created',
cell: ({ row, getValue }) => {
const date = formatDate(getValue());
const owner =
row.original.Labels?.['io.portainer.kubernetes.ingress.owner'];
if (owner) {
return `${date} by ${owner}`;
}
return date;
export const created = columnHelper.accessor(
(row) => {
const owner = row.Labels?.['io.portainer.kubernetes.ingress.owner'];
const date = formatDate(row.CreationDate);
return owner ? `${date} by ${owner}` : date;
},
id: 'created',
});
{
header: 'Created',
cell: ({ row, getValue }) => {
const date = formatDate(getValue());
const owner =
row.original.Labels?.['io.portainer.kubernetes.ingress.owner'];
return owner ? `${date} by ${owner}` : date;
},
id: 'created',
}
);

View File

@ -4,18 +4,28 @@ import { AlertTriangle, ArrowRight } from 'lucide-react';
import { Icon } from '@@/Icon';
import { Badge } from '@@/Badge';
import { Ingress, TLS, Path } from '../../types';
import { Ingress, TLS } from '../../types';
import { columnHelper } from './helper';
export const ingressRules = columnHelper.accessor('Paths', {
header: 'Rules and Paths',
id: 'ingressRules',
cell: Cell,
});
export const ingressRules = columnHelper.accessor(
({ Paths, TLS }) =>
// return an accessor function with all the useful text to search for
Paths.map((path) => {
const isHttp = isHTTP(TLS || [], path.Host);
return `${isHttp ? 'http' : 'https'}://${path.Host}${path.Path}${
path.ServiceName
}:${path.Port} ${!path.HasService && "Service doesn't exist"}`;
}).join(','),
{
header: 'Rules and Paths',
id: 'ingressRules',
cell: Cell,
}
);
function Cell({ row, getValue }: CellContext<Ingress, Path[] | undefined>) {
const paths = getValue();
function Cell({ row }: CellContext<Ingress, string>) {
const paths = row.original.Paths;
if (!paths) {
return <div />;