Skip to content
Open
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
1 change: 1 addition & 0 deletions frontend/packages/console-app/locales/en/console-app.json
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@
"Kubelet version": "Kubelet version",
"Kube-Proxy version": "Kube-Proxy version",
"Configuration": "Configuration",
"Workload": "Workload",
"Machine set": "Machine set",
"This count is based on your access permissions and might not include all virtual machines.": "This count is based on your access permissions and might not include all virtual machines.",
"{{formattedCores}} cores / {{totalCores}} cores": "{{formattedCores}} cores / {{totalCores}} cores",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import NodeDashboard from './node-dashboard/NodeDashboard';
import NodeDetails from './NodeDetails';
import NodeLogs from './NodeLogs';
import NodeTerminal from './NodeTerminal';
import { NodeWorkload } from './NodeWorkload';

const NodePodsPage: FC<PageComponentProps<NodeKind>> = ({ obj }) => (
<PodsPage
Expand Down Expand Up @@ -53,10 +54,15 @@ export const NodeDetailsPage: FC<ComponentProps<typeof DetailsPage>> = (props) =
nameKey: 'console-app~Configuration',
component: NodeConfiguration,
},
{
href: 'workload',
// t('console-app~Workload')
nameKey: 'console-app~Workload',
component: NodeWorkload,
},
navFactory.editYaml(),
]
: []),
navFactory.editYaml(),
navFactory.pods(NodePodsPage),
: [navFactory.editYaml(), navFactory.pods(NodePodsPage)]),
navFactory.logs(NodeLogs),
navFactory.events(ResourceEventStream),
...(!isWindowsNode(node) ? [navFactory.terminal(NodeTerminal)] : []),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { FC } from 'react';
import type { NodeKind } from '@console/dynamic-plugin-sdk/src/extensions/console-types';
import { PodsPage } from '@console/internal/components/pod-list';
import type { PageComponentProps } from '@console/internal/components/utils';
import { NodeSubNavPage } from './NodeSubNavPage';

const WORKLOADS_PAGE_ID = 'workloads';

const NodePodsPage: FC<PageComponentProps<NodeKind>> = ({ obj }) => (
<PodsPage
fieldSelector={`spec.nodeName=${obj.metadata.name}`}
showNamespaceOverride
hideFavoriteButton
/>
);

type NodeWorkloadProps = {
obj: NodeKind;
};

const standardPages = [
{
tabId: 'pods',
// t('console-app~Pods')
nameKey: 'console-app~Pods',
component: NodePodsPage,
priority: 30,
},
];

export const NodeWorkload: FC<NodeWorkloadProps> = ({ obj }) => (
<NodeSubNavPage obj={obj} pageId={WORKLOADS_PAGE_ID} standardPages={standardPages} />
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Assisted-by: Claude
import { render } from '@testing-library/react';
import type { NodeKind } from '@console/dynamic-plugin-sdk/src/extensions/console-types';
import { NodeSubNavPage } from '../NodeSubNavPage';
import { NodeWorkload } from '../NodeWorkload';

jest.mock('../NodeSubNavPage', () => ({
NodeSubNavPage: jest.fn(() => null),
}));

jest.mock('@console/internal/components/pod-list', () => ({
PodsPage: jest.fn(() => null),
}));

const mockNode: NodeKind = {
apiVersion: 'v1',
kind: 'Node',
metadata: {
name: 'test-node',
uid: 'test-node-uid',
},
spec: {},
status: {
conditions: [],
},
};

describe('NodeWorkload', () => {
afterEach(() => {
jest.clearAllMocks();
});

it('should render NodeSubNavPage component', () => {
render(<NodeWorkload obj={mockNode} />);

expect(NodeSubNavPage).toHaveBeenCalled();
});

it('should pass the node object to NodeSubNavPage', () => {
render(<NodeWorkload obj={mockNode} />);

expect(NodeSubNavPage).toHaveBeenCalledWith(
expect.objectContaining({
obj: mockNode,
}),
expect.any(Object),
);
});

it('should pass the workloads page ID to NodeSubNavPage', () => {
render(<NodeWorkload obj={mockNode} />);

expect(NodeSubNavPage).toHaveBeenCalledWith(
expect.objectContaining({
pageId: 'workloads',
}),
expect.any(Object),
);
});

it('should configure standard pages with pods tab', () => {
render(<NodeWorkload obj={mockNode} />);

const call = (NodeSubNavPage as jest.Mock).mock.calls[0][0];
expect(call.standardPages).toHaveLength(1);
expect(call.standardPages[0]).toMatchObject({
tabId: 'pods',
nameKey: 'console-app~Pods',
priority: 30,
});
expect(typeof call.standardPages[0].component).toBe('function');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ Use this extension to add custom sub-tabs to the Node details page.<br/><br/>Not
| Name | Value Type | Optional | Description |
| ---- | ---------- | -------- | ----------- |
| `parentTab` | `'configuration'` | no | Which detail tab to add the sub-tab to. Only the 'configuration' tab supports adding sub-tabs at this time. |
| `page` | `{ tabId: string; name: string; priority: number; }` | no | The page to be shown in node sub tabs. It takes tab name as name and priority of the tab.<br/><br/>Notes:<br/>The UI displays tabs in priority order from highest to lowest. Default built-in tab priorities include:<br/>- **configuration:**<br/> - storage/70<br/> - machine/50 |
| `page` | `{ tabId: string; name: string; priority: number; }` | no | The page to be shown in node sub-tabs. It takes tab name as name and priority of the tab.<br/><br/>Notes:<br/>The UI displays tabs in priority order from highest to lowest. Default built-in tab priorities include:<br/>- **configuration:**<br/> - storage/70<br/> - machine/50<br/>- **workloads:**<br/> - pods/30 |
| `component` | `CodeRef<ComponentType<SubPageComponentProps<NodeKind>>>` | no | The component that renders the sub-tab contents. It receives the Node resource as the obj prop. |

---
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ export type NodeSubNavTab = Extension<
/** Which detail tab to add the sub-tab to. Only the 'configuration' tab supports adding sub-tabs at this time. */
parentTab: 'configuration';
/**
* The page to be shown in node sub tabs. It takes tab name as name and priority of the tab.
* The page to be shown in node sub-tabs. It takes tab name as name and priority of the tab.
*
* Notes:
* The UI displays tabs in priority order from highest to lowest. Default built-in tab priorities include:
* - **configuration:**
* - storage/70
* - machine/50
* - **workloads:**
* - pods/30
*/
page: {
/**
Expand Down
7 changes: 6 additions & 1 deletion frontend/public/components/pod-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,7 @@ export const PodsPage: FC<PodPageProps> = ({
hideLabelFilter,
hideColumnManagement,
showNamespaceOverride,
hideFavoriteButton,
}) => {
const { t } = useTranslation();
const dispatch = useConsoleDispatch();
Expand Down Expand Up @@ -675,7 +676,10 @@ export const PodsPage: FC<PodPageProps> = ({

return (
<>
<ListPageHeader title={showTitle ? t('public~Pods') : ''}>
<ListPageHeader
title={showTitle ? t('public~Pods') : ''}
hideFavoriteButton={hideFavoriteButton}
>
{canCreate && !mock && (
<ListPageCreate groupVersionKind={resourceKind} createAccessReview={accessReview}>
{t('public~Create Pod')}
Expand Down Expand Up @@ -747,4 +751,5 @@ type PodPageProps = {
hideNameLabelFilters?: boolean;
hideColumnManagement?: boolean;
showNamespaceOverride?: boolean;
hideFavoriteButton?: boolean;
};