feat(ws): use workspace counts from API response (#508)
Signed-off-by: Guilherme Caponetto <638737+caponetto@users.noreply.github.com>
This commit is contained in:
parent
7a6bb30e76
commit
77c69c5aa3
|
@ -38,7 +38,7 @@ export const NamespaceContextProvider: React.FC<NamespaceContextProviderProps> =
|
|||
const namespaceNames = namespacesData.map((ns) => ns.name);
|
||||
setNamespaces(namespaceNames);
|
||||
setSelectedNamespace(lastUsedNamespace.length ? lastUsedNamespace : namespaceNames[0]);
|
||||
if (!lastUsedNamespace.length) {
|
||||
if (!lastUsedNamespace.length || !namespaceNames.includes(lastUsedNamespace)) {
|
||||
setLastUsedNamespace(storageKey, namespaceNames[0]);
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,341 @@
|
|||
import { waitFor } from '@testing-library/react';
|
||||
import { renderHook } from '~/__tests__/unit/testUtils/hooks';
|
||||
import { useNotebookAPI } from '~/app/hooks/useNotebookAPI';
|
||||
import { useWorkspaceCountPerKind } from '~/app/hooks/useWorkspaceCountPerKind';
|
||||
import {
|
||||
Workspace,
|
||||
WorkspaceImageConfigValue,
|
||||
WorkspaceKind,
|
||||
WorkspaceKindInfo,
|
||||
WorkspacePodConfigValue,
|
||||
} from '~/shared/api/backendApiTypes';
|
||||
import { NotebookAPIs } from '~/shared/api/notebookApi';
|
||||
import { buildMockWorkspace, buildMockWorkspaceKind } from '~/shared/mock/mockBuilder';
|
||||
|
||||
jest.mock('~/app/hooks/useNotebookAPI', () => ({
|
||||
useNotebookAPI: jest.fn(),
|
||||
}));
|
||||
|
||||
const mockUseNotebookAPI = useNotebookAPI as jest.MockedFunction<typeof useNotebookAPI>;
|
||||
|
||||
const baseWorkspaceKindInfoTest: WorkspaceKindInfo = {
|
||||
name: 'jupyter',
|
||||
missing: false,
|
||||
icon: { url: '' },
|
||||
logo: { url: '' },
|
||||
};
|
||||
|
||||
const baseWorkspaceTest = buildMockWorkspace({
|
||||
name: 'workspace',
|
||||
namespace: 'namespace',
|
||||
workspaceKind: baseWorkspaceKindInfoTest,
|
||||
});
|
||||
|
||||
const baseImageConfigTest: WorkspaceImageConfigValue = {
|
||||
id: 'image',
|
||||
displayName: 'Image',
|
||||
description: 'Test image',
|
||||
labels: [],
|
||||
hidden: false,
|
||||
clusterMetrics: undefined,
|
||||
};
|
||||
|
||||
const basePodConfigTest: WorkspacePodConfigValue = {
|
||||
id: 'podConfig',
|
||||
displayName: 'Pod Config',
|
||||
description: 'Test pod config',
|
||||
labels: [],
|
||||
hidden: false,
|
||||
clusterMetrics: undefined,
|
||||
};
|
||||
|
||||
describe('useWorkspaceCountPerKind', () => {
|
||||
const mockListAllWorkspaces = jest.fn();
|
||||
const mockListWorkspaceKinds = jest.fn();
|
||||
|
||||
const mockApi: Partial<NotebookAPIs> = {
|
||||
listAllWorkspaces: mockListAllWorkspaces,
|
||||
listWorkspaceKinds: mockListWorkspaceKinds,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
mockUseNotebookAPI.mockReturnValue({
|
||||
api: mockApi as NotebookAPIs,
|
||||
apiAvailable: true,
|
||||
refreshAllAPI: jest.fn(),
|
||||
});
|
||||
});
|
||||
|
||||
it('should return empty object initially', () => {
|
||||
mockListAllWorkspaces.mockResolvedValue([]);
|
||||
mockListWorkspaceKinds.mockResolvedValue([]);
|
||||
|
||||
const { result } = renderHook(() => useWorkspaceCountPerKind());
|
||||
|
||||
waitFor(() => {
|
||||
expect(result.current).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch and calculate workspace counts on mount', async () => {
|
||||
const mockWorkspaces: Workspace[] = [
|
||||
{
|
||||
...baseWorkspaceTest,
|
||||
name: 'workspace1',
|
||||
namespace: 'namespace1',
|
||||
workspaceKind: { ...baseWorkspaceKindInfoTest, name: 'jupyter1' },
|
||||
},
|
||||
{
|
||||
...baseWorkspaceTest,
|
||||
name: 'workspace2',
|
||||
namespace: 'namespace1',
|
||||
workspaceKind: { ...baseWorkspaceKindInfoTest, name: 'jupyter1' },
|
||||
},
|
||||
{
|
||||
...baseWorkspaceTest,
|
||||
name: 'workspace3',
|
||||
namespace: 'namespace2',
|
||||
workspaceKind: { ...baseWorkspaceKindInfoTest, name: 'jupyter2' },
|
||||
},
|
||||
];
|
||||
|
||||
const mockWorkspaceKinds: WorkspaceKind[] = [
|
||||
buildMockWorkspaceKind({
|
||||
name: 'jupyter1',
|
||||
clusterMetrics: { workspacesCount: 10 },
|
||||
podTemplate: {
|
||||
podMetadata: { labels: {}, annotations: {} },
|
||||
volumeMounts: { home: '/home' },
|
||||
options: {
|
||||
imageConfig: {
|
||||
default: 'image1',
|
||||
values: [
|
||||
{
|
||||
...baseImageConfigTest,
|
||||
id: 'image1',
|
||||
clusterMetrics: { workspacesCount: 1 },
|
||||
},
|
||||
{
|
||||
...baseImageConfigTest,
|
||||
id: 'image2',
|
||||
clusterMetrics: { workspacesCount: 2 },
|
||||
},
|
||||
],
|
||||
},
|
||||
podConfig: {
|
||||
default: 'podConfig1',
|
||||
values: [
|
||||
{
|
||||
...basePodConfigTest,
|
||||
id: 'podConfig1',
|
||||
clusterMetrics: { workspacesCount: 3 },
|
||||
},
|
||||
{
|
||||
...basePodConfigTest,
|
||||
id: 'podConfig2',
|
||||
clusterMetrics: { workspacesCount: 4 },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
buildMockWorkspaceKind({
|
||||
name: 'jupyter2',
|
||||
clusterMetrics: { workspacesCount: 20 },
|
||||
podTemplate: {
|
||||
podMetadata: { labels: {}, annotations: {} },
|
||||
volumeMounts: { home: '/home' },
|
||||
options: {
|
||||
imageConfig: {
|
||||
default: 'image1',
|
||||
values: [
|
||||
{
|
||||
...baseImageConfigTest,
|
||||
id: 'image1',
|
||||
clusterMetrics: { workspacesCount: 11 },
|
||||
},
|
||||
],
|
||||
},
|
||||
podConfig: {
|
||||
default: 'podConfig1',
|
||||
values: [
|
||||
{
|
||||
...basePodConfigTest,
|
||||
id: 'podConfig1',
|
||||
clusterMetrics: { workspacesCount: 12 },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
mockListAllWorkspaces.mockResolvedValue(mockWorkspaces);
|
||||
mockListWorkspaceKinds.mockResolvedValue(mockWorkspaceKinds);
|
||||
|
||||
const { result } = renderHook(() => useWorkspaceCountPerKind());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toEqual({
|
||||
jupyter1: {
|
||||
count: 10,
|
||||
countByImage: {
|
||||
image1: 1,
|
||||
image2: 2,
|
||||
},
|
||||
countByPodConfig: {
|
||||
podConfig1: 3,
|
||||
podConfig2: 4,
|
||||
},
|
||||
countByNamespace: {
|
||||
namespace1: 2,
|
||||
},
|
||||
},
|
||||
jupyter2: {
|
||||
count: 20,
|
||||
countByImage: {
|
||||
image1: 11,
|
||||
},
|
||||
countByPodConfig: {
|
||||
podConfig1: 12,
|
||||
},
|
||||
countByNamespace: {
|
||||
namespace2: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle missing cluster metrics gracefully', async () => {
|
||||
const mockEmptyWorkspaces: Workspace[] = [];
|
||||
const mockWorkspaceKinds: WorkspaceKind[] = [
|
||||
buildMockWorkspaceKind({
|
||||
name: 'no-metrics',
|
||||
clusterMetrics: undefined,
|
||||
podTemplate: {
|
||||
podMetadata: { labels: {}, annotations: {} },
|
||||
volumeMounts: { home: '/home' },
|
||||
options: {
|
||||
imageConfig: {
|
||||
default: baseImageConfigTest.id,
|
||||
values: [{ ...baseImageConfigTest }],
|
||||
},
|
||||
podConfig: {
|
||||
default: basePodConfigTest.id,
|
||||
values: [{ ...basePodConfigTest }],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
buildMockWorkspaceKind({
|
||||
name: 'no-metrics-2',
|
||||
clusterMetrics: undefined,
|
||||
podTemplate: {
|
||||
podMetadata: { labels: {}, annotations: {} },
|
||||
volumeMounts: { home: '/home' },
|
||||
options: {
|
||||
imageConfig: {
|
||||
default: 'empty',
|
||||
values: [],
|
||||
},
|
||||
podConfig: {
|
||||
default: 'empty',
|
||||
values: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
mockListAllWorkspaces.mockResolvedValue(mockEmptyWorkspaces);
|
||||
mockListWorkspaceKinds.mockResolvedValue(mockWorkspaceKinds);
|
||||
|
||||
const { result } = renderHook(() => useWorkspaceCountPerKind());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toEqual({
|
||||
'no-metrics': {
|
||||
count: 0,
|
||||
countByImage: {
|
||||
image: 0,
|
||||
},
|
||||
countByPodConfig: {
|
||||
podConfig: 0,
|
||||
},
|
||||
countByNamespace: {},
|
||||
},
|
||||
'no-metrics-2': {
|
||||
count: 0,
|
||||
countByImage: {},
|
||||
countByPodConfig: {},
|
||||
countByNamespace: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should return empty object in case of API errors rather than propagating them', async () => {
|
||||
mockListAllWorkspaces.mockRejectedValue(new Error('API Error'));
|
||||
mockListWorkspaceKinds.mockRejectedValue(new Error('API Error'));
|
||||
|
||||
const { result } = renderHook(() => useWorkspaceCountPerKind());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle empty workspace kinds array', async () => {
|
||||
mockListWorkspaceKinds.mockResolvedValue([]);
|
||||
|
||||
const { result } = renderHook(() => useWorkspaceCountPerKind());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle workspaces with no matching kinds', async () => {
|
||||
const mockWorkspaces: Workspace[] = [baseWorkspaceTest];
|
||||
const workspaceKind = buildMockWorkspaceKind({
|
||||
name: 'nomatch',
|
||||
clusterMetrics: { workspacesCount: 0 },
|
||||
podTemplate: {
|
||||
podMetadata: { labels: {}, annotations: {} },
|
||||
volumeMounts: { home: '/home' },
|
||||
options: {
|
||||
imageConfig: {
|
||||
default: baseImageConfigTest.id,
|
||||
values: [{ ...baseImageConfigTest }],
|
||||
},
|
||||
podConfig: {
|
||||
default: basePodConfigTest.id,
|
||||
values: [{ ...basePodConfigTest }],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const mockWorkspaceKinds: WorkspaceKind[] = [workspaceKind];
|
||||
|
||||
mockListAllWorkspaces.mockResolvedValue(mockWorkspaces);
|
||||
mockListWorkspaceKinds.mockResolvedValue(mockWorkspaceKinds);
|
||||
|
||||
const { result } = renderHook(() => useWorkspaceCountPerKind());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current).toEqual({
|
||||
[workspaceKind.name]: {
|
||||
count: 0,
|
||||
countByImage: { [baseImageConfigTest.id]: 0 },
|
||||
countByPodConfig: { [basePodConfigTest.id]: 0 },
|
||||
countByNamespace: {},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -2,45 +2,96 @@ import { useEffect, useState } from 'react';
|
|||
import { useNotebookAPI } from '~/app/hooks/useNotebookAPI';
|
||||
import { Workspace, WorkspaceKind } from '~/shared/api/backendApiTypes';
|
||||
import { WorkspaceCountPerOption } from '~/app/types';
|
||||
import { NotebookAPIs } from '~/shared/api/notebookApi';
|
||||
|
||||
export type WorkspaceCountPerKind = Record<WorkspaceKind['name'], WorkspaceCountPerOption>;
|
||||
|
||||
// TODO: This hook is temporary; we should get counts from the API directly
|
||||
export const useWorkspaceCountPerKind = (): WorkspaceCountPerKind => {
|
||||
const { api } = useNotebookAPI();
|
||||
|
||||
const [workspaceCountPerKind, setWorkspaceCountPerKind] = useState<WorkspaceCountPerKind>({});
|
||||
|
||||
useEffect(() => {
|
||||
api.listAllWorkspaces({}).then((workspaces) => {
|
||||
const countPerKind = workspaces.reduce((acc: WorkspaceCountPerKind, workspace: Workspace) => {
|
||||
acc[workspace.workspaceKind.name] = acc[workspace.workspaceKind.name] ?? {
|
||||
count: 0,
|
||||
countByImage: {},
|
||||
countByPodConfig: {},
|
||||
countByNamespace: {},
|
||||
};
|
||||
acc[workspace.workspaceKind.name].count =
|
||||
(acc[workspace.workspaceKind.name].count || 0) + 1;
|
||||
acc[workspace.workspaceKind.name].countByImage[
|
||||
workspace.podTemplate.options.imageConfig.current.id
|
||||
] =
|
||||
(acc[workspace.workspaceKind.name].countByImage[
|
||||
workspace.podTemplate.options.imageConfig.current.id
|
||||
] || 0) + 1;
|
||||
acc[workspace.workspaceKind.name].countByPodConfig[
|
||||
workspace.podTemplate.options.podConfig.current.id
|
||||
] =
|
||||
(acc[workspace.workspaceKind.name].countByPodConfig[
|
||||
workspace.podTemplate.options.podConfig.current.id
|
||||
] || 0) + 1;
|
||||
acc[workspace.workspaceKind.name].countByNamespace[workspace.namespace] =
|
||||
(acc[workspace.workspaceKind.name].countByNamespace[workspace.namespace] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
setWorkspaceCountPerKind(countPerKind);
|
||||
});
|
||||
const fetchAndSetCounts = async () => {
|
||||
try {
|
||||
const countPerKind = await loadWorkspaceCounts(api);
|
||||
setWorkspaceCountPerKind(countPerKind);
|
||||
} catch (err) {
|
||||
// TODO: alert user about error
|
||||
console.error('Failed to fetch workspace counts:', err);
|
||||
}
|
||||
};
|
||||
|
||||
fetchAndSetCounts();
|
||||
}, [api]);
|
||||
|
||||
return workspaceCountPerKind;
|
||||
};
|
||||
|
||||
async function loadWorkspaceCounts(api: NotebookAPIs): Promise<WorkspaceCountPerKind> {
|
||||
const [workspaces, workspaceKinds] = await Promise.all([
|
||||
api.listAllWorkspaces({}),
|
||||
api.listWorkspaceKinds({}),
|
||||
]);
|
||||
|
||||
return extractCountPerKind({ workspaceKinds, workspaces });
|
||||
}
|
||||
|
||||
function extractCountByNamespace(args: {
|
||||
kind: WorkspaceKind;
|
||||
workspaces: Workspace[];
|
||||
}): WorkspaceCountPerOption['countByNamespace'] {
|
||||
const { kind, workspaces } = args;
|
||||
return workspaces.reduce<WorkspaceCountPerOption['countByNamespace']>(
|
||||
(acc, { namespace, workspaceKind }) => {
|
||||
if (kind.name === workspaceKind.name) {
|
||||
acc[namespace] = (acc[namespace] ?? 0) + 1;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
function extractCountByImage(
|
||||
workspaceKind: WorkspaceKind,
|
||||
): WorkspaceCountPerOption['countByImage'] {
|
||||
return workspaceKind.podTemplate.options.imageConfig.values.reduce<
|
||||
WorkspaceCountPerOption['countByImage']
|
||||
>((acc, { id, clusterMetrics }) => {
|
||||
acc[id] = clusterMetrics?.workspacesCount ?? 0;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function extractCountByPodConfig(
|
||||
workspaceKind: WorkspaceKind,
|
||||
): WorkspaceCountPerOption['countByPodConfig'] {
|
||||
return workspaceKind.podTemplate.options.podConfig.values.reduce<
|
||||
WorkspaceCountPerOption['countByPodConfig']
|
||||
>((acc, { id, clusterMetrics }) => {
|
||||
acc[id] = clusterMetrics?.workspacesCount ?? 0;
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function extractTotalCount(workspaceKind: WorkspaceKind): number {
|
||||
return workspaceKind.clusterMetrics?.workspacesCount ?? 0;
|
||||
}
|
||||
|
||||
function extractCountPerKind(args: {
|
||||
workspaceKinds: WorkspaceKind[];
|
||||
workspaces: Workspace[];
|
||||
}): WorkspaceCountPerKind {
|
||||
const { workspaceKinds, workspaces } = args;
|
||||
|
||||
return workspaceKinds.reduce<WorkspaceCountPerKind>((acc, kind) => {
|
||||
acc[kind.name] = {
|
||||
count: extractTotalCount(kind),
|
||||
countByImage: extractCountByImage(kind),
|
||||
countByPodConfig: extractCountByPodConfig(kind),
|
||||
countByNamespace: extractCountByNamespace({ kind, workspaces }),
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ export const WorkspaceKindDetailsTable: React.FC<WorkspaceKindDetailsTableProps>
|
|||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{rowPages[page - 1].map((row) => (
|
||||
{rowPages[page - 1]?.map((row) => (
|
||||
<Tr key={row.id}>
|
||||
<Td>{row.displayName}</Td>
|
||||
<Td>
|
||||
|
|
|
@ -27,6 +27,7 @@ export interface WorkspacePodConfigValue {
|
|||
labels: WorkspaceOptionLabel[];
|
||||
hidden: boolean;
|
||||
redirect?: WorkspaceOptionRedirect;
|
||||
clusterMetrics?: WorkspaceKindClusterMetrics;
|
||||
}
|
||||
|
||||
export interface WorkspaceKindPodConfig {
|
||||
|
@ -71,6 +72,7 @@ export interface WorkspaceImageConfigValue {
|
|||
labels: WorkspaceOptionLabel[];
|
||||
hidden: boolean;
|
||||
redirect?: WorkspaceOptionRedirect;
|
||||
clusterMetrics?: WorkspaceKindClusterMetrics;
|
||||
}
|
||||
|
||||
export interface WorkspaceKindImageConfig {
|
||||
|
@ -107,9 +109,14 @@ export interface WorkspaceKind {
|
|||
hidden: boolean;
|
||||
icon: WorkspaceImageRef;
|
||||
logo: WorkspaceImageRef;
|
||||
clusterMetrics?: WorkspaceKindClusterMetrics;
|
||||
podTemplate: WorkspaceKindPodTemplate;
|
||||
}
|
||||
|
||||
export interface WorkspaceKindClusterMetrics {
|
||||
workspacesCount: number;
|
||||
}
|
||||
|
||||
export enum WorkspaceState {
|
||||
WorkspaceStateRunning = 'Running',
|
||||
WorkspaceStateTerminating = 'Terminating',
|
||||
|
|
|
@ -147,6 +147,9 @@ export const buildMockWorkspaceKind = (workspaceKind?: Partial<WorkspaceKind>):
|
|||
logo: {
|
||||
url: 'https://upload.wikimedia.org/wikipedia/commons/3/38/Jupyter_logo.svg',
|
||||
},
|
||||
clusterMetrics: {
|
||||
workspacesCount: 10,
|
||||
},
|
||||
podTemplate: {
|
||||
podMetadata: {
|
||||
labels: {
|
||||
|
@ -172,6 +175,9 @@ export const buildMockWorkspaceKind = (workspaceKind?: Partial<WorkspaceKind>):
|
|||
{ key: 'jupyterlabVersion', value: '1.8.0' },
|
||||
],
|
||||
hidden: true,
|
||||
clusterMetrics: {
|
||||
workspacesCount: 0,
|
||||
},
|
||||
redirect: {
|
||||
to: 'jupyterlab_scipy_190',
|
||||
message: {
|
||||
|
@ -196,6 +202,9 @@ export const buildMockWorkspaceKind = (workspaceKind?: Partial<WorkspaceKind>):
|
|||
level: WorkspaceRedirectMessageLevel.RedirectMessageLevelWarning,
|
||||
},
|
||||
},
|
||||
clusterMetrics: {
|
||||
workspacesCount: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'jupyterlab_scipy_200',
|
||||
|
@ -213,6 +222,9 @@ export const buildMockWorkspaceKind = (workspaceKind?: Partial<WorkspaceKind>):
|
|||
level: WorkspaceRedirectMessageLevel.RedirectMessageLevelWarning,
|
||||
},
|
||||
},
|
||||
clusterMetrics: {
|
||||
workspacesCount: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'jupyterlab_scipy_210',
|
||||
|
@ -230,6 +242,9 @@ export const buildMockWorkspaceKind = (workspaceKind?: Partial<WorkspaceKind>):
|
|||
level: WorkspaceRedirectMessageLevel.RedirectMessageLevelWarning,
|
||||
},
|
||||
},
|
||||
clusterMetrics: {
|
||||
workspacesCount: 3,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -252,6 +267,9 @@ export const buildMockWorkspaceKind = (workspaceKind?: Partial<WorkspaceKind>):
|
|||
level: WorkspaceRedirectMessageLevel.RedirectMessageLevelDanger,
|
||||
},
|
||||
},
|
||||
clusterMetrics: {
|
||||
workspacesCount: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'large_cpu',
|
||||
|
@ -270,6 +288,9 @@ export const buildMockWorkspaceKind = (workspaceKind?: Partial<WorkspaceKind>):
|
|||
level: WorkspaceRedirectMessageLevel.RedirectMessageLevelDanger,
|
||||
},
|
||||
},
|
||||
clusterMetrics: {
|
||||
workspacesCount: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -27,16 +27,25 @@ export const mockNamespaces = [mockNamespace1, mockNamespace2, mockNamespace3];
|
|||
export const mockWorkspaceKind1: WorkspaceKind = buildMockWorkspaceKind({
|
||||
name: 'jupyterlab1',
|
||||
displayName: 'JupyterLab Notebook 1',
|
||||
clusterMetrics: {
|
||||
workspacesCount: 18,
|
||||
},
|
||||
});
|
||||
|
||||
export const mockWorkspaceKind2: WorkspaceKind = buildMockWorkspaceKind({
|
||||
name: 'jupyterlab2',
|
||||
displayName: 'JupyterLab Notebook 2',
|
||||
clusterMetrics: {
|
||||
workspacesCount: 2,
|
||||
},
|
||||
});
|
||||
|
||||
export const mockWorkspaceKind3: WorkspaceKind = buildMockWorkspaceKind({
|
||||
name: 'jupyterlab3',
|
||||
displayName: 'JupyterLab Notebook 3',
|
||||
clusterMetrics: {
|
||||
workspacesCount: 0,
|
||||
},
|
||||
});
|
||||
|
||||
export const mockWorkspaceKinds = [mockWorkspaceKind1, mockWorkspaceKind2, mockWorkspaceKind3];
|
||||
|
|
Loading…
Reference in New Issue