Skip to content

Commit 9abced3

Browse files
committed
Refactor public/ Directory Components to useK8sWatchResource(s)
1 parent 759d8cc commit 9abced3

File tree

20 files changed

+606
-446
lines changed

20 files changed

+606
-446
lines changed

frontend/packages/console-app/src/actions/hooks/useBindingActions.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ export const useBindingActions = (
4545
const navigate = useNavigate();
4646
const [commonActions] = useCommonActions(model, obj, [CommonActionCreator.Delete] as const);
4747

48-
const { subjectIndex, subjects = [] } = obj;
48+
const { subjectIndex, subjects } = obj ?? {};
4949
const subject = subjects?.[subjectIndex];
5050
const deleteBindingSubject = useWarningModal({
5151
title: t('public~Delete {{label}} subject?', {
52-
label: model.kind,
52+
label: model?.kind,
5353
}),
5454
children: t('public~Are you sure you want to delete subject {{name}} of type {{kind}}?', {
5555
name: subject?.name,
@@ -146,9 +146,9 @@ export const useBindingActions = (
146146
: []),
147147
factory.DuplicateBinding(),
148148
factory.EditBindingSubject(),
149-
...(subjects.length === 1 ? [commonActions.Delete] : [factory.DeleteBindingSubject()]),
149+
...(subjects?.length === 1 ? [commonActions.Delete] : [factory.DeleteBindingSubject()]),
150150
];
151-
}, [memoizedFilterActions, subject?.kind, factory, subjects.length, commonActions.Delete]);
151+
}, [memoizedFilterActions, subject?.kind, factory, subjects?.length, commonActions.Delete]);
152152

153153
return actions;
154154
};

frontend/packages/console-app/src/components/nodes/NodeTerminal.tsx

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import type { ReactNode, FC } from 'react';
22
import { useState, useEffect } from 'react';
33
import { Alert } from '@patternfly/react-core';
44
import { useTranslation, Trans } from 'react-i18next';
5+
import { WatchK8sResource } from '@console/dynamic-plugin-sdk/src/extensions/console-types';
6+
import { useK8sWatchResource } from '@console/dynamic-plugin-sdk/src/utils/k8s/hooks/useK8sWatchResource';
57
import { PodConnectLoader } from '@console/internal/components/pod';
6-
import { Firehose } from '@console/internal/components/utils/firehose';
78
import { LoadingBox } from '@console/internal/components/utils/status-box';
8-
import type { FirehoseResource, FirehoseResult } from '@console/internal/components/utils/types';
99
import { ImageStreamTagModel, NamespaceModel, PodModel } from '@console/internal/models';
1010
import { NodeKind, PodKind, k8sCreate, k8sGet, k8sKillByName } from '@console/internal/module/k8s';
1111
import PaneBody from '@console/shared/src/components/layout/PaneBody';
@@ -15,7 +15,9 @@ type NodeTerminalErrorProps = {
1515
};
1616

1717
type NodeTerminalInnerProps = {
18-
obj?: FirehoseResult<PodKind>;
18+
pod: PodKind | undefined;
19+
loaded: boolean;
20+
loadError: any;
1921
};
2022

2123
type NodeTerminalProps = {
@@ -124,7 +126,7 @@ const NodeTerminalError: FC<NodeTerminalErrorProps> = ({ error }) => {
124126
);
125127
};
126128

127-
const NodeTerminalInner: FC<NodeTerminalInnerProps> = ({ obj }) => {
129+
const NodeTerminalInner: FC<NodeTerminalInnerProps> = ({ pod, loaded, loadError }) => {
128130
const { t } = useTranslation();
129131
const message = (
130132
<Trans t={t} ns="console-app">
@@ -133,32 +135,44 @@ const NodeTerminalInner: FC<NodeTerminalInnerProps> = ({ obj }) => {
133135
</p>
134136
</Trans>
135137
);
136-
switch (obj?.data?.status?.phase) {
138+
139+
if (loadError) {
140+
return <NodeTerminalError error={loadError.message || t('console-app~Failed to load pod')} />;
141+
}
142+
143+
if (!loaded || !pod) {
144+
return <LoadingBox />;
145+
}
146+
147+
switch (pod.status?.phase) {
137148
case 'Failed':
138149
return (
139150
<NodeTerminalError
140151
error={
141152
<>
142153
{t('console-app~The debug pod failed. ')}
143-
{obj?.data?.status?.containerStatuses?.[0]?.state?.terminated?.message ||
144-
obj?.data?.status?.message}
154+
{pod.status?.containerStatuses?.[0]?.state?.terminated?.message ||
155+
pod.status?.message}
145156
</>
146157
}
147158
/>
148159
);
149160
case 'Running':
150-
return <PodConnectLoader obj={obj.data} message={message} attach />;
161+
return <PodConnectLoader obj={pod} message={message} attach />;
151162
default:
152163
return <LoadingBox />;
153164
}
154165
};
155166

156167
const NodeTerminal: FC<NodeTerminalProps> = ({ obj: node }) => {
157-
const [resources, setResources] = useState<FirehoseResource[]>([]);
168+
const [isCreatingPod, setIsCreatingPod] = useState(true);
169+
const [podWatchResource, setPodWatchResource] = useState<WatchK8sResource | null>(null);
158170
const [errorMessage, setErrorMessage] = useState('');
159171
const nodeName = node.metadata.name;
160172
const isWindows = node.status?.nodeInfo?.operatingSystem === 'windows';
161173

174+
const [pod, loaded, loadError] = useK8sWatchResource<PodKind>(podWatchResource);
175+
162176
useEffect(() => {
163177
let namespace;
164178
const name = `${nodeName?.replace(/\./g, '-')}-debug`;
@@ -196,18 +210,17 @@ const NodeTerminal: FC<NodeTerminalProps> = ({ obj: node }) => {
196210
await new Promise((resolve) => setTimeout(resolve, 1000));
197211
const debugPod = await k8sCreate(PodModel, podToCreate);
198212
if (debugPod) {
199-
setResources([
200-
{
201-
isList: false,
202-
kind: 'Pod',
203-
name,
204-
namespace: namespace.metadata.name,
205-
prop: 'obj',
206-
},
207-
]);
213+
setPodWatchResource({
214+
kind: 'Pod',
215+
name,
216+
namespace: namespace.metadata.name,
217+
isList: false,
218+
});
219+
setIsCreatingPod(false);
208220
}
209221
} catch (e) {
210222
setErrorMessage(e.message);
223+
setIsCreatingPod(false);
211224
if (namespace) {
212225
deleteNamespace(namespace.metadata.name);
213226
}
@@ -221,13 +234,15 @@ const NodeTerminal: FC<NodeTerminalProps> = ({ obj: node }) => {
221234
};
222235
}, [nodeName, isWindows]);
223236

224-
return errorMessage ? (
225-
<NodeTerminalError error={errorMessage} />
226-
) : (
227-
<Firehose resources={resources}>
228-
<NodeTerminalInner />
229-
</Firehose>
230-
);
237+
if (errorMessage) {
238+
return <NodeTerminalError error={errorMessage} />;
239+
}
240+
241+
if (isCreatingPod) {
242+
return <LoadingBox />;
243+
}
244+
245+
return <NodeTerminalInner pod={pod} loaded={loaded} loadError={loadError} />;
231246
};
232247

233248
export default NodeTerminal;

frontend/public/components/RBAC/bindings.tsx

Lines changed: 78 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ import { TableColumn } from '@console/internal/module/k8s';
4747
import { GetDataViewRows, ResourceFilters } from '@console/app/src/components/data-view/types';
4848
import { tableFilters } from '../factory/table-filters';
4949
import { ButtonBar } from '../utils/button-bar';
50-
import { Firehose } from '../utils/firehose';
5150
import { getQueryArgument } from '../utils/router';
5251
import { kindObj } from '../utils/inject';
5352
import type { ListDropdownProps } from '../utils/list-dropdown';
@@ -57,7 +56,7 @@ import { ResourceName } from '../utils/resource-icon';
5756
import { StatusBox, LoadingBox } from '../utils/status-box';
5857
import { useAccessReview } from '../utils/rbac';
5958
import { flagPending } from '../../reducers/features';
60-
import { useK8sWatchResources } from '../utils/k8s-watch-hook';
59+
import { useK8sWatchResource, useK8sWatchResources } from '../utils/k8s-watch-hook';
6160

6261
// Split each binding into one row per subject
6362
export const flatten = (resources): BindingKind[] =>
@@ -185,18 +184,19 @@ const bindingType = (binding: BindingKind) => {
185184
if (!binding) {
186185
return undefined;
187186
}
188-
if (binding.roleRef.name.startsWith('system:')) {
187+
if (binding.roleRef?.name?.startsWith('system:')) {
189188
return 'system';
190189
}
191-
return binding.metadata.namespace ? 'namespace' : 'cluster';
190+
return binding.metadata?.namespace ? 'namespace' : 'cluster';
192191
};
193192

194193
const getDataViewRows: GetDataViewRows<BindingKind> = (data, columns) => {
195-
return data.map(({ obj: binding }) => {
194+
return data.map((row) => {
195+
const binding = row.obj;
196196
const rowCells = {
197197
[tableColumnInfo[0].id]: {
198198
cell: <BindingName binding={binding} />,
199-
props: getNameCellProps(binding.metadata.name),
199+
props: getNameCellProps(binding.metadata?.name),
200200
},
201201
[tableColumnInfo[1].id]: {
202202
cell: <RoleLink binding={binding} />,
@@ -208,7 +208,7 @@ const getDataViewRows: GetDataViewRows<BindingKind> = (data, columns) => {
208208
cell: binding.subject.name,
209209
},
210210
[tableColumnInfo[4].id]: {
211-
cell: binding.metadata.namespace ? (
211+
cell: binding.metadata?.namespace ? (
212212
<ResourceLink kind="Namespace" name={binding.metadata.namespace} />
213213
) : (
214214
i18next.t('public~All namespaces')
@@ -360,11 +360,18 @@ export const RoleBindingsPage: FC<RoleBindingsPageProps> = ({
360360
},
361361
});
362362

363-
const data = useMemo(() => flatten(resources), [resources]);
364-
365-
const loaded = Object.values(resources)
366-
.filter((r) => !r.loadError)
367-
.every((r) => r.loaded);
363+
const data = useMemo(() => flatten(resources), [
364+
resources.RoleBinding.data,
365+
resources.ClusterRoleBinding.data,
366+
]);
367+
368+
const loaded = useMemo(
369+
() =>
370+
Object.values(resources)
371+
.filter((r) => !r.loadError)
372+
.every((r) => r.loaded),
373+
[resources],
374+
);
368375

369376
return (
370377
<>
@@ -784,52 +791,79 @@ const getSubjectIndex = () => {
784791
};
785792

786793
const BindingLoadingWrapper: FC<BindingLoadingWrapperProps> = (props) => {
794+
const { obj, loaded, loadError, fixedKeys } = props;
787795
const [, setActiveNamespace] = useActiveNamespace();
796+
797+
if (!loaded) {
798+
return <LoadingBox />;
799+
}
800+
801+
if (loadError) {
802+
return <StatusBox data={obj} loaded={loaded} loadError={loadError} />;
803+
}
804+
805+
if (!obj || _.isEmpty(obj)) {
806+
return <StatusBox data={obj} loaded={loaded} loadError={loadError} />;
807+
}
808+
788809
const fixed: { [key: string]: any } = {};
789-
_.each(props.fixedKeys, (k) => (fixed[k] = _.get(props.obj.data, k)));
810+
fixedKeys.forEach((k) => (fixed[k] = obj?.[k]));
811+
790812
return (
791-
<StatusBox {...props.obj}>
792-
<BaseEditRoleBinding
793-
{...props}
794-
setActiveNamespace={setActiveNamespace}
795-
fixed={fixed}
796-
obj={props.obj.data}
797-
/>
798-
</StatusBox>
813+
<BaseEditRoleBinding
814+
{...props}
815+
setActiveNamespace={setActiveNamespace}
816+
fixed={fixed}
817+
obj={obj}
818+
/>
799819
);
800820
};
801821

802822
export const EditRoleBinding: FC<EditRoleBindingProps> = ({ kind }) => {
803823
const { t } = useTranslation();
804824
const params = useParams();
825+
826+
const [obj, loaded, loadError] = useK8sWatchResource<RoleBindingKind | ClusterRoleBindingKind>({
827+
kind,
828+
name: params.name,
829+
namespace: params.ns,
830+
isList: false,
831+
});
832+
805833
return (
806-
<Firehose
807-
resources={[{ kind, name: params.name, namespace: params.ns, isList: false, prop: 'obj' }]}
808-
>
809-
<BindingLoadingWrapper
810-
fixedKeys={['kind', 'metadata', 'roleRef']}
811-
subjectIndex={getSubjectIndex()}
812-
titleVerbAndKind={t('public~Edit RoleBinding')}
813-
saveButtonText={t('public~Save')}
814-
/>
815-
</Firehose>
834+
<BindingLoadingWrapper
835+
obj={obj}
836+
loaded={loaded}
837+
loadError={loadError}
838+
fixedKeys={['kind', 'metadata', 'roleRef']}
839+
subjectIndex={getSubjectIndex()}
840+
titleVerbAndKind={t('public~Edit RoleBinding')}
841+
saveButtonText={t('public~Save')}
842+
/>
816843
);
817844
};
818845

819846
export const CopyRoleBinding: FC<EditRoleBindingProps> = ({ kind }) => {
820847
const { t } = useTranslation();
821848
const params = useParams();
849+
850+
const [obj, loaded, loadError] = useK8sWatchResource<RoleBindingKind | ClusterRoleBindingKind>({
851+
kind,
852+
name: params.name,
853+
namespace: params.ns,
854+
isList: false,
855+
});
856+
822857
return (
823-
<Firehose
824-
resources={[{ kind, name: params.name, namespace: params.ns, isList: false, prop: 'obj' }]}
825-
>
826-
<BindingLoadingWrapper
827-
fixedKeys={['kind']}
828-
subjectIndex={getSubjectIndex()}
829-
isCreate={true}
830-
titleVerbAndKind={t('public~Duplicate RoleBinding')}
831-
/>
832-
</Firehose>
858+
<BindingLoadingWrapper
859+
obj={obj}
860+
loaded={loaded}
861+
loadError={loadError}
862+
fixedKeys={['kind']}
863+
subjectIndex={getSubjectIndex()}
864+
isCreate={true}
865+
titleVerbAndKind={t('public~Duplicate RoleBinding')}
866+
/>
833867
);
834868
};
835869

@@ -881,9 +915,9 @@ type BindingLoadingWrapperProps = {
881915
titleVerbAndKind: string;
882916
saveButtonText?: string;
883917
isCreate?: boolean;
884-
obj?: {
885-
data: RoleBindingKind | ClusterRoleBindingKind;
886-
};
918+
obj?: RoleBindingKind | ClusterRoleBindingKind;
919+
loaded: boolean;
920+
loadError: any;
887921
};
888922

889923
type EditRoleBindingProps = {

0 commit comments

Comments
 (0)