Skip to content

Commit

Permalink
Added /crs page to display a list of all instantiated custom resources.
Browse files Browse the repository at this point in the history
Fixes: #1962
Signed-off-by: guilhane <guilhane.bourgoin@orange.com>
  • Loading branch information
Guilamb committed Aug 1, 2024
1 parent 8dee67d commit 2a0b428
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
6 changes: 6 additions & 0 deletions frontend/src/components/Sidebar/prepareRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ function prepareRoutes(
{
name: 'crds',
label: t('glossary|Custom Resources'),
subList: [
{
name: 'crs',
label: t('glossary|CR Instances'),
},
],
},
],
},
Expand Down
128 changes: 128 additions & 0 deletions frontend/src/components/crd/CustomResourceInstancesList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import CRD, { KubeCRD } from '../../lib/k8s/crd';
import { Link, Loader, SectionBox } from '../common/';
import Empty from '../common/EmptyContent';
import { ResourceListView } from '../common/Resource';

interface State {
crList: KubeCRD[];
loading: boolean;
crDictionary: Map<string, KubeCRD>;
}

export function CrInstanceList() {
const { t } = useTranslation(['glossary', 'translation']);
const [crds, crdsError] = CRD.useList();
const [state, setState] = useState<State>({
crList: [],
loading: true,
crDictionary: new Map<string, KubeCRD>(),
});

useEffect(() => {
const fetchCRs = async () => {
const allCrs: KubeCRD[] = [];
const newCrDictionary = new Map<string, KubeCRD>();

for (const crd of crds) {
const crClass = crd.makeCRClass();
const [crItems, crError] = await new Promise<[KubeCRD[] | null, any | null]>(resolve => {
crClass.apiList(
(items: KubeCRD[]) => resolve([items, null]),
(err: any) => resolve([null, err])
)();
});

if (crError) {
console.error('Error fetching CRs:', crError);
continue;
}

if (crItems && crItems.length > 0) {
allCrs.push(...crItems);
for (const item of crItems) {
newCrDictionary.set(item.metadata.name, crd);
}
}
}

setState({
crList: allCrs,
loading: false,
crDictionary: newCrDictionary,
});
};

if (crds) {
fetchCRs();
}
}, [crds]);

if (crdsError) {
return (
<Empty color="error">
{t('translation|Error getting custom resource definitions: {{ errorMessage }}', {
errorMessage: crdsError,
})}
</Empty>
);
}

if (state.loading) {
return <Loader title={t('translation|Loading custom resource instances')} />;
}

if (state.crList.length === 0) {
return <Empty>{t('translation|No custom resources found.')}</Empty>;
}

return (
<SectionBox backLink>
<ResourceListView
title="Custom Resource Instances"
headerProps={{
noNamespaceFilter: false,
}}
data={state.crList}
columns={[
{
label: 'Instance name',
getValue: cr => {
return cr.metadata.name;
},
},
{
label: 'CRD',
getValue: cr => {
return cr.metadata.name;
},
render: cr => {
return (
<Link
routeName="/plugin/crd/:name"
params={{
name: `${state.crDictionary.get(cr.metadata.name)?.metadata.name}`,
}}
>
{cr.kind} {/*crd.metadata.name*/}
</Link>
);
},
},
{
label: 'Categories',
getValue: cr => {
const categories = state.crDictionary.get(cr.metadata.name)?.jsonData!.status
.acceptedNames.categories;
return categories !== undefined ? categories.toString().split(',').join(', ') : '';
},
},
'namespace',

'age',
]}
/>
</SectionBox>
);
}
10 changes: 10 additions & 0 deletions frontend/src/lib/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import { PageGrid } from '../components/common/Resource/Resource';
import ConfigDetails from '../components/configmap/Details';
import ConfigMapList from '../components/configmap/List';
import CustomResourceDetails from '../components/crd/CustomResourceDetails';
import {
CrInstanceList,
} from '../components/crd/CustomResourceInstancesList';
import CustomResourceList from '../components/crd/CustomResourceList';
import CustomResourceDefinitionDetails from '../components/crd/Details';
import CustomResourceDefinitionList from '../components/crd/List';
Expand Down Expand Up @@ -652,6 +655,13 @@ const defaultRoutes: {
sidebar: 'crds',
component: () => <CustomResourceList />,
},
crs: {
path: '/crs',
exact: true,
name: 'CRInstances',
sidebar: 'crs',
component: () => <CrInstanceList />,
},
notifications: {
path: '/notifications',
exact: true,
Expand Down

0 comments on commit 2a0b428

Please sign in to comment.