Skip to content

Commit 6be0760

Browse files
committed
frontend: add endpointslice support
* add support for resource map * add support for global search * add support for details and list * link in services Signed-off-by: farodin91 <[email protected]>
1 parent e3783d0 commit 6be0760

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2314
-51
lines changed

frontend/src/components/Sidebar/__snapshots__/Sidebar.InClusterSidebarClosed.stories.storyshot

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,29 @@
558558
/>
559559
</a>
560560
</li>
561+
<li
562+
class="css-1gktw5r"
563+
>
564+
<a
565+
class="MuiButtonBase-root MuiListItemButton-root MuiListItemButton-gutters MuiListItemButton-root MuiListItemButton-gutters css-1op30le-MuiButtonBase-root-MuiListItemButton-root"
566+
href="/"
567+
role="button"
568+
tabindex="0"
569+
>
570+
<div
571+
class="MuiListItemText-root css-tlelie-MuiListItemText-root"
572+
>
573+
<span
574+
class="MuiTypography-root MuiTypography-body1 MuiListItemText-primary css-nqgwvn-MuiTypography-root"
575+
>
576+
Endpoint Slices
577+
</span>
578+
</div>
579+
<span
580+
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
581+
/>
582+
</a>
583+
</li>
561584
<li
562585
class="css-1gktw5r"
563586
>

frontend/src/components/Sidebar/__snapshots__/Sidebar.InClusterSidebarOpen.stories.storyshot

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,29 @@
600600
/>
601601
</a>
602602
</li>
603+
<li
604+
class="css-1gktw5r"
605+
>
606+
<a
607+
class="MuiButtonBase-root MuiListItemButton-root MuiListItemButton-gutters MuiListItemButton-root MuiListItemButton-gutters css-1op30le-MuiButtonBase-root-MuiListItemButton-root"
608+
href="/"
609+
role="button"
610+
tabindex="0"
611+
>
612+
<div
613+
class="MuiListItemText-root css-tlelie-MuiListItemText-root"
614+
>
615+
<span
616+
class="MuiTypography-root MuiTypography-body1 MuiListItemText-primary css-nqgwvn-MuiTypography-root"
617+
>
618+
Endpoint Slices
619+
</span>
620+
</div>
621+
<span
622+
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
623+
/>
624+
</a>
625+
</li>
603626
<li
604627
class="css-1gktw5r"
605628
>

frontend/src/components/Sidebar/__snapshots__/Sidebar.SelectedItemWithSidebarOmitted.stories.storyshot

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,29 @@
600600
/>
601601
</a>
602602
</li>
603+
<li
604+
class="css-1gktw5r"
605+
>
606+
<a
607+
class="MuiButtonBase-root MuiListItemButton-root MuiListItemButton-gutters MuiListItemButton-root MuiListItemButton-gutters css-1op30le-MuiButtonBase-root-MuiListItemButton-root"
608+
href="/"
609+
role="button"
610+
tabindex="0"
611+
>
612+
<div
613+
class="MuiListItemText-root css-tlelie-MuiListItemText-root"
614+
>
615+
<span
616+
class="MuiTypography-root MuiTypography-body1 MuiListItemText-primary css-nqgwvn-MuiTypography-root"
617+
>
618+
Endpoint Slices
619+
</span>
620+
</div>
621+
<span
622+
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
623+
/>
624+
</a>
625+
</li>
603626
<li
604627
class="css-1gktw5r"
605628
>

frontend/src/components/Sidebar/useSidebarItems.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ export const useSidebarItems = (sidebarName: string = DefaultSidebars.IN_CLUSTER
247247
name: 'endpoints',
248248
label: t('glossary|Endpoints'),
249249
},
250+
{
251+
name: 'endpointslices',
252+
label: t('glossary|Endpoint Slices'),
253+
},
250254
{
251255
name: 'ingresses',
252256
label: t('glossary|Ingresses'),
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright 2025 The Kubernetes Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import Box from '@mui/material/Box';
18+
import { useTranslation } from 'react-i18next';
19+
import { useParams } from 'react-router-dom';
20+
import EndpointSlice from '../../lib/k8s/endpointSlices';
21+
import { SectionBox, SimpleTable, StatusLabel } from '../common';
22+
import { DetailsGrid } from '../common/Resource';
23+
24+
export default function EndpointSliceDetails(props: {
25+
name?: string;
26+
namespace?: string;
27+
cluster?: string;
28+
}) {
29+
const params = useParams<{ namespace: string; name: string }>();
30+
const { name = params.name, namespace = params.namespace, cluster } = props;
31+
const { t } = useTranslation(['glossary', 'translation']);
32+
33+
return (
34+
<DetailsGrid
35+
resourceType={EndpointSlice}
36+
name={name}
37+
namespace={namespace}
38+
cluster={cluster}
39+
title={t('Endpoint Slice')}
40+
withEvents
41+
extraInfo={item =>
42+
item && [
43+
{
44+
name: t('translation|Address Type'),
45+
value: item.spec.addressType,
46+
},
47+
]
48+
}
49+
extraSections={(item: EndpointSlice) =>
50+
item && [
51+
{
52+
id: 'headlamp.endpoint-slice-endpoints',
53+
section: (
54+
<SectionBox title={t('Endpoints')}>
55+
<SimpleTable
56+
data={item?.spec.endpoints || []}
57+
columns={[
58+
{
59+
label: t('translation|Hostname'),
60+
datum: 'hostname',
61+
sort: true,
62+
},
63+
{
64+
label: t('translation|Node Name'),
65+
datum: 'nodeName',
66+
sort: true,
67+
},
68+
{
69+
label: t('translation|Zone'),
70+
datum: 'zone',
71+
sort: true,
72+
},
73+
{
74+
label: t('Addresses'),
75+
getter: endpoint => endpoint.addresses?.join(','),
76+
},
77+
{
78+
label: t('Conditions'),
79+
getter: endpoint => (
80+
<>
81+
<Box display="inline-block">
82+
<StatusLabel status={endpoint.conditions.ready ? 'success' : 'error'}>
83+
{t('Ready')}
84+
</StatusLabel>
85+
</Box>
86+
<Box display="inline-block">
87+
<StatusLabel status={endpoint.conditions.serving ? 'success' : 'error'}>
88+
{t('Serving')}
89+
</StatusLabel>
90+
</Box>
91+
<Box display="inline-block">
92+
<StatusLabel
93+
status={endpoint.conditions.terminating ? 'success' : 'error'}
94+
>
95+
{t('Terminating')}
96+
</StatusLabel>
97+
</Box>
98+
</>
99+
),
100+
},
101+
]}
102+
defaultSortingColumn={1}
103+
reflectInURL="endpoints"
104+
/>
105+
</SectionBox>
106+
),
107+
},
108+
{
109+
id: 'headlamp.endpoint-slice-ports',
110+
section: (
111+
<SectionBox title={t('Ports')}>
112+
<SimpleTable
113+
data={item?.spec.ports || []}
114+
columns={[
115+
{
116+
label: t('translation|Name'),
117+
datum: 'name',
118+
sort: true,
119+
},
120+
{
121+
label: t('Port'),
122+
datum: 'port',
123+
sort: true,
124+
},
125+
{
126+
label: t('Protocol'),
127+
datum: 'protocol',
128+
sort: true,
129+
},
130+
]}
131+
defaultSortingColumn={1}
132+
reflectInURL="ports"
133+
/>
134+
</SectionBox>
135+
),
136+
},
137+
]
138+
}
139+
/>
140+
);
141+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
* Copyright 2025 The Kubernetes Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { Meta, StoryFn } from '@storybook/react';
18+
import { http, HttpResponse } from 'msw';
19+
import { TestContext } from '../../test';
20+
import EndpointSliceDetails from './Details';
21+
22+
export default {
23+
title: 'endpointslice/EndpointSliceDetailsView',
24+
component: EndpointSliceDetails,
25+
argTypes: {},
26+
parameters: {
27+
msw: {
28+
handlers: {
29+
storyBase: [
30+
http.get('http://localhost:4466/apis/discovery.k8s.io/v1/endpointslices', () =>
31+
HttpResponse.error()
32+
),
33+
http.get('http://localhost:4466/api/v1/namespaces/my-namespace/events', () =>
34+
HttpResponse.error()
35+
),
36+
],
37+
},
38+
},
39+
},
40+
} as Meta;
41+
42+
const Template: StoryFn = () => {
43+
return (
44+
<TestContext routerMap={{ namespace: 'my-namespace', name: 'my-endpoint' }}>
45+
<EndpointSliceDetails />
46+
</TestContext>
47+
);
48+
};
49+
50+
export const Default = Template.bind({});
51+
Default.parameters = {
52+
msw: {
53+
handlers: {
54+
story: [
55+
http.get(
56+
'http://localhost:4466/apis/discovery.k8s.io/v1/namespaces/my-namespace/endpointslices/my-endpoint',
57+
() =>
58+
HttpResponse.json({
59+
kind: 'EndpointSlice',
60+
apiVersion: 'discovery.k8s.io/v1',
61+
metadata: {
62+
name: 'my-endpoint',
63+
namespace: 'my-namespace',
64+
uid: 'phony',
65+
creationTimestamp: new Date('2020-04-25').toISOString(),
66+
resourceVersion: '1',
67+
selfLink: '0',
68+
},
69+
endpoints: [
70+
{
71+
addresses: ['127.0.0.1'],
72+
nodeName: 'mynode',
73+
targetRef: {
74+
kind: 'Pod',
75+
namespace: 'MyNamespace',
76+
name: 'mypod',
77+
uid: 'phony-pod',
78+
resourceVersion: '1',
79+
apiVersion: 'v1',
80+
},
81+
},
82+
{
83+
addresses: ['127.0.0.2'],
84+
nodeName: 'mynode',
85+
targetRef: {
86+
kind: 'Pod',
87+
namespace: 'MyNamespace',
88+
name: 'mypod-1',
89+
uid: 'phony-pod-1',
90+
resourceVersion: '1',
91+
apiVersion: 'v1',
92+
},
93+
},
94+
],
95+
ports: [
96+
{
97+
name: 'myport',
98+
port: 8080,
99+
protocol: 'TCP',
100+
},
101+
],
102+
})
103+
),
104+
],
105+
},
106+
},
107+
};
108+
109+
export const Error = Template.bind({});
110+
Error.parameters = {
111+
msw: {
112+
handlers: {
113+
story: [
114+
http.get(
115+
'http://localhost:4466/apis/discovery.k8s.io/v1/namespaces/my-namespace/endpointslices/my-endpoint',
116+
() => HttpResponse.error()
117+
),
118+
],
119+
},
120+
},
121+
};

0 commit comments

Comments
 (0)