diff --git a/frontend/packages/dev-console/src/components/health-checks/HealthChecksPage.tsx b/frontend/packages/dev-console/src/components/health-checks/HealthChecksPage.tsx
index 84410d8a944..60e00bf96f0 100644
--- a/frontend/packages/dev-console/src/components/health-checks/HealthChecksPage.tsx
+++ b/frontend/packages/dev-console/src/components/health-checks/HealthChecksPage.tsx
@@ -1,25 +1,26 @@
import type { FC } from 'react';
import { useParams } from 'react-router-dom-v5-compat';
-import { FirehoseResource, Firehose } from '@console/internal/components/utils';
+import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
+import { K8sResourceKind } from '@console/internal/module/k8s';
import AddHealthChecksForm from './AddHealthChecksForm';
const HealthChecksPage: FC = () => {
const { ns, kind, name, containerName } = useParams();
- const resource: FirehoseResource[] = [
- {
- kind,
- namespace: ns,
- isList: false,
- name,
- prop: 'resource',
- },
- ];
- return (
-
-
-
- );
+ const [resourceData, loaded, loadError] = useK8sWatchResource({
+ kind,
+ namespace: ns,
+ isList: false,
+ name,
+ });
+
+ const resource = {
+ data: resourceData,
+ loaded,
+ loadError,
+ };
+
+ return ;
};
export default HealthChecksPage;
diff --git a/frontend/packages/dev-console/src/components/import/DeployImage.tsx b/frontend/packages/dev-console/src/components/import/DeployImage.tsx
index dbf91d95e50..79105c04119 100644
--- a/frontend/packages/dev-console/src/components/import/DeployImage.tsx
+++ b/frontend/packages/dev-console/src/components/import/DeployImage.tsx
@@ -15,12 +15,16 @@ import { createOrUpdateDeployImageResources } from './deployImage-submit-utils';
import { deployValidationSchema } from './deployImage-validation-utils';
import DeployImageForm from './DeployImageForm';
import { filterDeployedResources } from './import-submit-utils';
-import { DeployImageFormData, FirehoseList, Resources } from './import-types';
+import { DeployImageFormData, Resources } from './import-types';
import { useUpdateKnScalingDefaultValues } from './serverless/useUpdateKnScalingDefaultValues';
export interface DeployImageProps {
namespace: string;
- projects?: FirehoseList;
+ projects?: {
+ data: K8sResourceKind[];
+ loaded: boolean;
+ loadError?: any;
+ };
contextualSource?: string;
}
diff --git a/frontend/packages/dev-console/src/components/import/DeployImagePage.tsx b/frontend/packages/dev-console/src/components/import/DeployImagePage.tsx
index f539f7dde55..bcd97e9723e 100644
--- a/frontend/packages/dev-console/src/components/import/DeployImagePage.tsx
+++ b/frontend/packages/dev-console/src/components/import/DeployImagePage.tsx
@@ -1,7 +1,8 @@
import type { FunctionComponent } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams, useLocation } from 'react-router-dom-v5-compat';
-import { Firehose } from '@console/internal/components/utils';
+import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
+import { K8sResourceKind } from '@console/internal/module/k8s';
import { DocumentTitle } from '@console/shared/src/components/document-title/DocumentTitle';
import { PageHeading } from '@console/shared/src/components/heading/PageHeading';
import { QUERY_PROPERTIES } from '../../const';
@@ -15,19 +16,29 @@ const DeployImagePage: FunctionComponent = () => {
const location = useLocation();
const params = new URLSearchParams(location.search);
+ const [projectsData, loaded, loadError] = useK8sWatchResource({
+ kind: 'Project',
+ isList: true,
+ });
+
+ const projects = {
+ data: projectsData,
+ loaded,
+ loadError,
+ };
+
return (
{t('devconsole~Deploy Image')}
{(desiredApplication) => (
-
-
-
+
)}
diff --git a/frontend/packages/dev-console/src/components/import/ImportForm.tsx b/frontend/packages/dev-console/src/components/import/ImportForm.tsx
index bede633f593..d2aad11a3a0 100644
--- a/frontend/packages/dev-console/src/components/import/ImportForm.tsx
+++ b/frontend/packages/dev-console/src/components/import/ImportForm.tsx
@@ -8,7 +8,7 @@ import { useActivePerspective } from '@console/dynamic-plugin-sdk';
import { GitProvider, ImportStrategy } from '@console/git-service/src';
import { history, AsyncComponent, StatusBox } from '@console/internal/components/utils';
import { RouteModel } from '@console/internal/models';
-import { RouteKind } from '@console/internal/module/k8s';
+import { RouteKind, K8sResourceKind } from '@console/internal/module/k8s';
import { getActiveApplication } from '@console/internal/reducers/ui';
import { RootState } from '@console/internal/redux';
import { ALL_APPLICATIONS_KEY, usePerspectives, useTelemetry } from '@console/shared';
@@ -38,7 +38,6 @@ import {
} from './import-submit-utils';
import {
GitImportFormData,
- FirehoseList,
ImportData,
Resources,
BaseFormData,
@@ -55,10 +54,15 @@ export interface ImportFormProps {
namespace: string;
importData: ImportData;
contextualSource?: string;
- imageStreams?: FirehoseList;
+ imageStreams?: {
+ data: K8sResourceKind | K8sResourceKind[];
+ loaded: boolean;
+ loadError?: any;
+ };
projects?: {
+ data: K8sResourceKind[];
loaded: boolean;
- data: [];
+ loadError?: any;
};
}
@@ -153,7 +157,11 @@ const ImportForm: FC = ({
const initialVals = useUpdateKnScalingDefaultValues(initialValues);
const builderImages: NormalizedBuilderImages =
- imageStreams && imageStreams.loaded && normalizeBuilderImages(imageStreams.data);
+ imageStreams &&
+ imageStreams.loaded &&
+ normalizeBuilderImages(
+ Array.isArray(imageStreams.data) ? imageStreams.data : [imageStreams.data],
+ );
const handleSubmit = (values: GitImportFormData, actions) => {
const imageStream = builderImages && builderImages[values.image.selected]?.obj;
diff --git a/frontend/packages/dev-console/src/components/import/ImportPage.tsx b/frontend/packages/dev-console/src/components/import/ImportPage.tsx
index e988c3d2e76..a27f8057e1e 100644
--- a/frontend/packages/dev-console/src/components/import/ImportPage.tsx
+++ b/frontend/packages/dev-console/src/components/import/ImportPage.tsx
@@ -1,9 +1,11 @@
import type { FunctionComponent } from 'react';
+import { useMemo } from 'react';
import { TFunction } from 'i18next';
import { useTranslation } from 'react-i18next';
import { useParams, useLocation } from 'react-router-dom-v5-compat';
-import { Firehose, FirehoseResource } from '@console/internal/components/utils';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import { ImageStreamModel, ProjectModel } from '@console/internal/models';
+import { K8sResourceKind } from '@console/internal/module/k8s';
import DevPreviewBadge from '@console/shared/src/components/badges/DevPreviewBadge';
import { DocumentTitle } from '@console/shared/src/components/document-title/DocumentTitle';
import { PageHeading } from '@console/shared/src/components/heading/PageHeading';
@@ -44,40 +46,47 @@ const ImportPage: FunctionComponent = () => {
const preselectedNamespace = searchParams.get('preselected-ns');
const importType = searchParams.get('importType');
- let importData: ImportData;
- let resources: FirehoseResource[];
- if (imageStreamName && imageStreamNamespace) {
- importData = ImportFlows(t).s2i;
- resources = [
- {
- kind: ImageStreamModel.kind,
- prop: 'imageStreams',
- isList: false,
- name: imageStreamName,
- namespace: imageStreamNamespace,
- },
- {
- kind: ProjectModel.kind,
- prop: 'projects',
- isList: true,
- },
- ];
- } else {
- importData = ImportFlows(t).git;
- resources = [
- {
- kind: ImageStreamModel.kind,
- prop: 'imageStreams',
- isList: true,
- namespace: 'openshift',
- },
- {
+ const isS2i = !!(imageStreamName && imageStreamNamespace);
+ const importData: ImportData = isS2i ? ImportFlows(t).s2i : ImportFlows(t).git;
+
+ const watchResources = useMemo(
+ () => ({
+ imageStreams: isS2i
+ ? {
+ kind: ImageStreamModel.kind,
+ isList: false,
+ name: imageStreamName,
+ namespace: imageStreamNamespace,
+ }
+ : {
+ kind: ImageStreamModel.kind,
+ isList: true,
+ namespace: 'openshift',
+ },
+ projects: {
kind: ProjectModel.kind,
- prop: 'projects',
isList: true,
},
- ];
- }
+ }),
+ [isS2i, imageStreamName, imageStreamNamespace],
+ );
+
+ const resources = useK8sWatchResources<{
+ imageStreams: K8sResourceKind | K8sResourceKind[];
+ projects: K8sResourceKind[];
+ }>(watchResources);
+
+ const imageStreams = {
+ data: resources.imageStreams.data,
+ loaded: resources.imageStreams.loaded,
+ loadError: resources.imageStreams.loadError,
+ };
+
+ const projects = {
+ data: resources.projects.data,
+ loaded: resources.projects.loaded,
+ loadError: resources.projects.loadError,
+ };
return (
@@ -88,14 +97,14 @@ const ImportPage: FunctionComponent = () => {
title={importData.title}
badge={importType === ImportTypes.devfile ? : null}
/>
-
-
-
+
)}
diff --git a/frontend/packages/dev-console/src/components/import/ImportSamplePage.tsx b/frontend/packages/dev-console/src/components/import/ImportSamplePage.tsx
index c24d1c45c26..5ecee003dbe 100644
--- a/frontend/packages/dev-console/src/components/import/ImportSamplePage.tsx
+++ b/frontend/packages/dev-console/src/components/import/ImportSamplePage.tsx
@@ -3,7 +3,7 @@ import { useMemo } from 'react';
import { Formik } from 'formik';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom-v5-compat';
-import { FirehoseResource, LoadingBox, history } from '@console/internal/components/utils';
+import { LoadingBox, history } from '@console/internal/components/utils';
import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
import { ImageStreamModel } from '@console/internal/models';
import { K8sResourceKind } from '@console/internal/module/k8s';
@@ -30,7 +30,7 @@ const ImportSamplePage: FC = () => {
const { t } = useTranslation();
const { ns: namespace, is: imageStreamName, isNs: imageStreamNamespace } = useParams();
- const imageStreamResource: FirehoseResource = useMemo(
+ const imageStreamResource = useMemo(
() => ({
kind: ImageStreamModel.kind,
prop: 'imageStreams',
diff --git a/frontend/packages/dev-console/src/components/import/__tests__/DeployImage.spec.tsx b/frontend/packages/dev-console/src/components/import/__tests__/DeployImage.spec.tsx
index 8cb27d35ac1..4e5820db88c 100644
--- a/frontend/packages/dev-console/src/components/import/__tests__/DeployImage.spec.tsx
+++ b/frontend/packages/dev-console/src/components/import/__tests__/DeployImage.spec.tsx
@@ -62,16 +62,12 @@ jest.mock('../../QueryFocusApplication', () => ({
},
}));
+jest.mock('@console/internal/components/utils/k8s-watch-hook', () => ({
+ useK8sWatchResource: () => [[], true, null],
+}));
+
jest.mock('@console/internal/components/utils', () => ({
...jest.requireActual('@console/internal/components/utils'),
- Firehose: (props) => {
- const mockProps = {
- projects: { data: [], loaded: true },
- };
- return props.children && typeof props.children === 'function'
- ? props.children(mockProps)
- : 'Firehose Component';
- },
usePreventDataLossLock: jest.fn(),
}));
diff --git a/frontend/packages/dev-console/src/components/import/import-types.ts b/frontend/packages/dev-console/src/components/import/import-types.ts
index 691f1745423..8a69738ba9e 100644
--- a/frontend/packages/dev-console/src/components/import/import-types.ts
+++ b/frontend/packages/dev-console/src/components/import/import-types.ts
@@ -13,7 +13,13 @@ import { PipelineData } from '../pipeline-section/import-types';
export interface DeployImageFormProps {
builderImages?: NormalizedBuilderImages;
- projects?: FirehoseList | WatchK8sResultsObject;
+ projects?:
+ | {
+ data: K8sResourceKind[];
+ loaded: boolean;
+ loadError?: any;
+ }
+ | WatchK8sResultsObject;
}
export type ImageStreamPayload = boolean | K8sResourceKind;
@@ -38,31 +44,34 @@ export interface ImageStreamContextProps {
export interface SourceToImageFormProps {
builderImages?: NormalizedBuilderImages;
projects?: {
- data: [];
+ data: K8sResourceKind[];
loaded: boolean;
+ loadError?: any;
};
}
export interface GitImportFormProps {
builderImages?: NormalizedBuilderImages;
+ imageStreams?: {
+ data: K8sResourceKind | K8sResourceKind[];
+ loaded: boolean;
+ loadError?: any;
+ };
projects?: {
- data: [];
+ data: K8sResourceKind[];
loaded: boolean;
+ loadError?: any;
};
}
export interface DevfileImportFormProps {
builderImages?: NormalizedBuilderImages;
projects?: {
- data: [];
+ data: K8sResourceKind[];
loaded: boolean;
+ loadError?: any;
};
}
-export interface FirehoseList {
- data?: K8sResourceKind[];
- [key: string]: any;
-}
-
export interface DeployImageFormData {
formType?: string;
project: ProjectData;
diff --git a/frontend/packages/dev-console/src/components/monitoring/overview/MonitoringOverview.tsx b/frontend/packages/dev-console/src/components/monitoring/overview/MonitoringOverview.tsx
index 0713a040c22..fa9b501ba9c 100644
--- a/frontend/packages/dev-console/src/components/monitoring/overview/MonitoringOverview.tsx
+++ b/frontend/packages/dev-console/src/components/monitoring/overview/MonitoringOverview.tsx
@@ -16,7 +16,7 @@ import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom-v5-compat';
import { Alert } from '@console/dynamic-plugin-sdk';
import { sortEvents } from '@console/internal/components/events';
-import { FirehoseResult, LoadingBox } from '@console/internal/components/utils';
+import { LoadingBox } from '@console/internal/components/utils';
import { DeploymentConfigModel } from '@console/internal/models';
import { K8sResourceKind, EventKind, PodKind } from '@console/internal/module/k8s';
import { getFiringAlerts } from '@console/shared';
@@ -28,7 +28,11 @@ import './MonitoringOverview.scss';
type MonitoringOverviewProps = {
resource: K8sResourceKind;
pods?: PodKind[];
- resourceEvents?: FirehoseResult;
+ resourceEvents?: {
+ data: EventKind[];
+ loaded: boolean;
+ loadError?: Error;
+ };
monitoringAlerts: Alert[];
};
diff --git a/frontend/packages/dev-console/src/components/monitoring/overview/MonitoringTab.tsx b/frontend/packages/dev-console/src/components/monitoring/overview/MonitoringTab.tsx
index 27fa99af571..28a8697282b 100644
--- a/frontend/packages/dev-console/src/components/monitoring/overview/MonitoringTab.tsx
+++ b/frontend/packages/dev-console/src/components/monitoring/overview/MonitoringTab.tsx
@@ -1,8 +1,8 @@
import type { FC } from 'react';
import { useMemo } from 'react';
-import { Firehose } from '@console/internal/components/utils';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import { PodModel } from '@console/internal/models';
-import { PodKind } from '@console/internal/module/k8s';
+import { EventKind, PodKind } from '@console/internal/module/k8s';
import { OverviewItem, usePodsWatcher } from '@console/shared';
import MonitoringOverview from './MonitoringOverview';
@@ -18,40 +18,66 @@ const MonitoringTab: FC = ({ item }) => {
} = item.obj;
const { podData, loadError, loaded } = usePodsWatcher(item.obj, item.obj.kind, namespace);
- const resources = useMemo(() => {
- const res = [
- {
+ const watchResources = useMemo(() => {
+ const res: Record<
+ string,
+ { isList: boolean; kind: string; namespace: string; fieldSelector: string }
+ > = {
+ resourceEvents: {
isList: true,
kind: 'Event',
namespace,
- prop: 'resourceEvents',
fieldSelector: `involvedObject.uid=${uid},involvedObject.name=${name},involvedObject.kind=${kind}`,
},
- ];
+ };
if (loaded && !loadError && podData?.pods) {
podData.pods.forEach((pod) => {
const fieldSelector = `involvedObject.uid=${pod.metadata.uid},involvedObject.name=${pod.metadata.name},involvedObject.kind=${PodModel.kind}`;
- res.push({
+ res[pod.metadata.uid] = {
isList: true,
kind: 'Event',
namespace: pod.metadata.namespace,
- prop: pod.metadata.uid,
fieldSelector,
- });
+ };
});
}
return res;
}, [kind, uid, name, namespace, loaded, loadError, podData]);
+ const resources = useK8sWatchResources>(watchResources);
+
+ // Transform resources to the expected format for MonitoringOverview
+ const resourceEvents = resources.resourceEvents
+ ? {
+ data: resources.resourceEvents.data || [],
+ loaded: resources.resourceEvents.loaded,
+ loadError: resources.resourceEvents.loadError,
+ }
+ : undefined;
+
+ // Build the props object with pod events
+ const podEventProps: Record = {};
+ if (podData?.pods) {
+ podData.pods.forEach((pod) => {
+ const podEvents = resources[pod.metadata.uid];
+ if (podEvents) {
+ podEventProps[pod.metadata.uid] = {
+ data: podEvents.data || [],
+ loaded: podEvents.loaded,
+ };
+ }
+ });
+ }
+
return (
-
-
-
+
);
};
diff --git a/frontend/packages/dev-console/src/components/monitoring/overview/__tests__/MonitoringTab.spec.tsx b/frontend/packages/dev-console/src/components/monitoring/overview/__tests__/MonitoringTab.spec.tsx
index ac748500c63..f62d2b64cee 100644
--- a/frontend/packages/dev-console/src/components/monitoring/overview/__tests__/MonitoringTab.spec.tsx
+++ b/frontend/packages/dev-console/src/components/monitoring/overview/__tests__/MonitoringTab.spec.tsx
@@ -1,8 +1,10 @@
import { render, screen } from '@testing-library/react';
import MonitoringTab from '../MonitoringTab';
-jest.mock('@console/internal/components/utils', () => ({
- Firehose: (props) => props.children,
+jest.mock('@console/internal/components/utils/k8s-watch-hook', () => ({
+ useK8sWatchResources: jest.fn(() => ({
+ resourceEvents: { data: [], loaded: true, loadError: null },
+ })),
}));
jest.mock('@console/internal/models', () => ({
diff --git a/frontend/packages/dev-console/src/components/monitoring/overview/__tests__/mockData.ts b/frontend/packages/dev-console/src/components/monitoring/overview/__tests__/mockData.ts
index ef11babc608..a6657e0657a 100644
--- a/frontend/packages/dev-console/src/components/monitoring/overview/__tests__/mockData.ts
+++ b/frontend/packages/dev-console/src/components/monitoring/overview/__tests__/mockData.ts
@@ -99,7 +99,7 @@ export const mockPodEvents = {
},
],
filters: {},
- loadError: '',
+ loadError: undefined,
loaded: true,
selected: null,
},
@@ -255,7 +255,7 @@ export const mockPodEvents = {
},
],
filters: {},
- loadError: '',
+ loadError: undefined,
loaded: true,
selected: null,
},
@@ -319,7 +319,7 @@ export const mockResourceEvents = {
},
],
filters: {},
- loadError: '',
+ loadError: undefined,
loaded: true,
selected: null,
};
diff --git a/frontend/packages/dev-console/src/components/project-access/ProjectAccess.tsx b/frontend/packages/dev-console/src/components/project-access/ProjectAccess.tsx
index e373d02fa2f..e2b54ed5a74 100644
--- a/frontend/packages/dev-console/src/components/project-access/ProjectAccess.tsx
+++ b/frontend/packages/dev-console/src/components/project-access/ProjectAccess.tsx
@@ -1,7 +1,6 @@
import type { FC } from 'react';
import { Content, ContentVariants } from '@patternfly/react-core';
import { Formik } from 'formik';
-import * as _ from 'lodash';
import { useTranslation, Trans } from 'react-i18next';
import { Link } from 'react-router-dom-v5-compat';
import {
@@ -13,6 +12,7 @@ import {
StatusBox,
} from '@console/internal/components/utils';
import { RoleBindingModel, RoleModel } from '@console/internal/models';
+import type { K8sResourceKind } from '@console/internal/module/k8s';
import { DocumentTitle } from '@console/shared/src/components/document-title/DocumentTitle';
import { PageHeading } from '@console/shared/src/components/heading/PageHeading';
import { ExternalLink } from '@console/shared/src/components/links/ExternalLink';
@@ -25,13 +25,13 @@ import {
getRolesToUpdate,
} from './project-access-form-submit-utils';
import { getUserRoleBindings, Roles } from './project-access-form-utils';
-import { Verb, UserRoleBinding } from './project-access-form-utils-types';
+import { Verb, UserRoleBinding, RoleBinding } from './project-access-form-utils-types';
import { validationSchema } from './project-access-form-validation-utils';
import ProjectAccessForm from './ProjectAccessForm';
export interface ProjectAccessProps {
namespace: string;
- roleBindings?: { data: []; loaded: boolean; loadError: {} };
+ roleBindings?: { data: K8sResourceKind[]; loaded: boolean; loadError?: Error };
roles: { data: Roles; loaded: boolean };
fullFormView?: boolean;
}
@@ -43,12 +43,12 @@ const ProjectAccess: FC = ({
fullFormView,
}) => {
const { t } = useTranslation();
- if ((!roleBindings.loaded && _.isEmpty(roleBindings.loadError)) || !roles.loaded) {
+ if ((!roleBindings.loaded && !roleBindings.loadError) || !roles.loaded) {
return ;
}
const userRoleBindings: UserRoleBinding[] = getUserRoleBindings(
- roleBindings.data,
+ roleBindings.data as RoleBinding[],
Object.keys(roles.data),
namespace,
);
diff --git a/frontend/packages/dev-console/src/components/project-access/ProjectAccessPage.tsx b/frontend/packages/dev-console/src/components/project-access/ProjectAccessPage.tsx
index 3a671885f2b..fda9ae134d6 100644
--- a/frontend/packages/dev-console/src/components/project-access/ProjectAccessPage.tsx
+++ b/frontend/packages/dev-console/src/components/project-access/ProjectAccessPage.tsx
@@ -1,7 +1,8 @@
import type { FC } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams, useLocation } from 'react-router-dom-v5-compat';
-import { Firehose } from '@console/internal/components/utils';
+import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
+import { K8sResourceKind } from '@console/internal/module/k8s';
import { DocumentTitle } from '@console/shared/src/components/document-title/DocumentTitle';
import { useProjectAccessRoles } from './hooks';
import ProjectAccess from './ProjectAccess';
@@ -13,22 +14,30 @@ const ProjectAccessPage: FC = (props) => {
const namespace = params.ns;
const roles = useProjectAccessRoles();
const showFullForm = location.pathname.includes('project-access');
+
+ const [roleBindingsData, loaded, loadError] = useK8sWatchResource({
+ namespace,
+ kind: 'RoleBinding',
+ isList: true,
+ optional: true,
+ });
+
+ const roleBindings = {
+ data: roleBindingsData || [],
+ loaded,
+ loadError,
+ };
+
return (
<>
{t('devconsole~Project access')}
-
-
-
+
>
);
};
diff --git a/frontend/packages/dev-console/src/components/project-access/__tests__/ProjectAccess.spec.tsx b/frontend/packages/dev-console/src/components/project-access/__tests__/ProjectAccess.spec.tsx
index ee4417b167f..ec0e8f400d1 100644
--- a/frontend/packages/dev-console/src/components/project-access/__tests__/ProjectAccess.spec.tsx
+++ b/frontend/packages/dev-console/src/components/project-access/__tests__/ProjectAccess.spec.tsx
@@ -94,7 +94,7 @@ describe('Project Access', () => {
roleBindings: {
data: [],
loaded: false,
- loadError: {},
+ loadError: undefined,
},
roles: {
data: defaultAccessRoles,
@@ -111,7 +111,7 @@ describe('Project Access', () => {
});
it('should show the StatusBox when there is error loading the role bindings', () => {
- projectAccessProps.roleBindings.loadError = { error: 'user has no access to role bindigs' };
+ projectAccessProps.roleBindings.loadError = new Error('user has no access to role bindigs');
render();
expect(screen.getByText(/StatusBox/)).toBeInTheDocument();
diff --git a/frontend/packages/dev-console/src/components/project-access/__tests__/ProjectAccessPage.spec.tsx b/frontend/packages/dev-console/src/components/project-access/__tests__/ProjectAccessPage.spec.tsx
index 234924b1023..02fc23e2ddf 100644
--- a/frontend/packages/dev-console/src/components/project-access/__tests__/ProjectAccessPage.spec.tsx
+++ b/frontend/packages/dev-console/src/components/project-access/__tests__/ProjectAccessPage.spec.tsx
@@ -2,8 +2,8 @@ import { render, screen } from '@testing-library/react';
import { useParams, useLocation } from 'react-router-dom-v5-compat';
import ProjectAccessPage from '../ProjectAccessPage';
-jest.mock('@console/internal/components/utils', () => ({
- Firehose: (props) => props.children,
+jest.mock('@console/internal/components/utils/k8s-watch-hook', () => ({
+ useK8sWatchResource: jest.fn(() => [[], true, null]),
}));
jest.mock('@console/shared/src/components/document-title/DocumentTitle', () => ({
diff --git a/frontend/packages/knative-plugin/src/components/knatify/CreateKnatifyPage.tsx b/frontend/packages/knative-plugin/src/components/knatify/CreateKnatifyPage.tsx
index ec2adeefce0..260953d6dab 100644
--- a/frontend/packages/knative-plugin/src/components/knatify/CreateKnatifyPage.tsx
+++ b/frontend/packages/knative-plugin/src/components/knatify/CreateKnatifyPage.tsx
@@ -139,7 +139,7 @@ const CreateKnatifyPage: FunctionComponent = () => {
{(formikProps) => (
) ?? {}}
+ projects={resources?.projects as WatchK8sResultsObject}
/>
)}
diff --git a/frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx b/frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx
index 98caedffc1e..1d4dada6a79 100644
--- a/frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx
+++ b/frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx
@@ -1,5 +1,5 @@
import type { FC } from 'react';
-import { useCallback } from 'react';
+import { useCallback, useMemo } from 'react';
import { ActionGroup, Button } from '@patternfly/react-core';
import { Formik, FormikHelpers, FormikValues } from 'formik';
import { useTranslation } from 'react-i18next';
@@ -12,12 +12,8 @@ import {
ModalTitle,
ModalWrapper,
} from '@console/internal/components/factory';
-import {
- Firehose,
- FirehoseResult,
- history,
- resourceListPathFromModel,
-} from '@console/internal/components/utils';
+import { history, resourceListPathFromModel } from '@console/internal/components/utils';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
import {
k8sKill,
k8sPatch,
@@ -26,34 +22,64 @@ import {
} from '@console/internal/module/k8s';
import { RedExclamationCircleIcon } from '@console/shared';
import { KNATIVE_SERVING_LABEL } from '../../const';
-import { RevisionModel, ServiceModel } from '../../models';
+import { ConfigurationModel, RevisionModel, ServiceModel } from '../../models';
import { getKnativeRevisionsData } from '../../topology/knative-topology-utils';
import { Traffic } from '../../types';
-import {
- knativeServingResourcesTrafficSplitting,
- getRevisionItems,
- trafficDataForPatch,
-} from '../../utils/traffic-splitting-utils';
+import { getRevisionItems, trafficDataForPatch } from '../../utils/traffic-splitting-utils';
import { TrafficSplittingType } from '../traffic-splitting/TrafficSplitting';
import DeleteRevisionModal from './DeleteRevisionModal';
-type ControllerProps = {
- loaded?: boolean;
- revision?: K8sResourceKind;
- resources?: {
- configurations: FirehoseResult;
- revisions: FirehoseResult;
- services: FirehoseResult;
- };
+type DeleteRevisionModalControllerProps = {
+ revision: K8sResourceKind;
cancel?: () => void;
close?: () => void;
};
-const Controller: FC = ({ loaded, resources, revision, cancel, close }) => {
+const DeleteRevisionModalController: FC = ({
+ revision,
+ cancel,
+ close,
+}) => {
const { t } = useTranslation();
+ const { namespace } = revision.metadata;
+
+ const watchResources = useMemo(
+ () => ({
+ revisions: {
+ isList: true,
+ kind: referenceForModel(RevisionModel),
+ namespace,
+ optional: true,
+ },
+ configurations: {
+ isList: true,
+ kind: referenceForModel(ConfigurationModel),
+ namespace,
+ optional: true,
+ },
+ services: {
+ isList: true,
+ kind: referenceForModel(ServiceModel),
+ namespace,
+ },
+ }),
+ [namespace],
+ );
+
+ const resources = useK8sWatchResources<{
+ revisions: K8sResourceKind[];
+ configurations: K8sResourceKind[];
+ services: K8sResourceKind[];
+ }>(watchResources);
+
+ const loaded =
+ Object.keys(resources).length > 0 &&
+ Object.keys(resources).every((key) => resources[key].loaded);
+
if (!loaded) {
return null;
}
+
const service = resources.services.data.find((s: K8sResourceKind) => {
return revision.metadata.labels[KNATIVE_SERVING_LABEL] === s.metadata.name;
});
@@ -124,7 +150,7 @@ const Controller: FC = ({ loaded, resources, revision, cancel,
});
}
- const deleteRevision = (action: FormikHelpers) => {
+ const deleteRevisionAction = (action: FormikHelpers) => {
return k8sKill(RevisionModel, revision)
.then(() => {
close();
@@ -143,12 +169,12 @@ const Controller: FC = ({ loaded, resources, revision, cancel,
const handleSubmit = (values: FormikValues, action: FormikHelpers) => {
const ksvcPatch = trafficDataForPatch(values.trafficSplitting, service);
if (!deleteTraffic || deleteTraffic.percent === 0) {
- return deleteRevision(action);
+ return deleteRevisionAction(action);
}
return k8sPatch(ServiceModel, service, ksvcPatch)
.then(() => {
- deleteRevision(action);
+ deleteRevisionAction(action);
})
.catch((err) => {
const errMessage = err.message || t('knative-plugin~An error occurred. Please try again');
@@ -176,29 +202,6 @@ const Controller: FC = ({ loaded, resources, revision, cancel,
);
};
-type DeleteRevisionModalControllerProps = {
- revision: K8sResourceKind;
-};
-
-const DeleteRevisionModalController: FC = (props) => {
- const {
- metadata: { namespace },
- } = props.revision;
- const resources = knativeServingResourcesTrafficSplitting(namespace);
- resources.push({
- isList: true,
- kind: referenceForModel(ServiceModel),
- namespace,
- prop: 'services',
- });
-
- return (
-
-
-
- );
-};
-
type Props = DeleteRevisionModalControllerProps & ModalComponentProps;
const DeleteRevisionModalProvider: OverlayComponent = (props) => {
diff --git a/frontend/packages/knative-plugin/src/components/test-function/TestFunctionController.tsx b/frontend/packages/knative-plugin/src/components/test-function/TestFunctionController.tsx
index 3ba75ea5978..7ca5c7867d0 100644
--- a/frontend/packages/knative-plugin/src/components/test-function/TestFunctionController.tsx
+++ b/frontend/packages/knative-plugin/src/components/test-function/TestFunctionController.tsx
@@ -3,21 +3,12 @@ import { useCallback } from 'react';
import { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { ModalComponentProps, ModalWrapper } from '@console/internal/components/factory';
-import { Firehose } from '@console/internal/components/utils';
+import { useK8sWatchResource } from '@console/internal/components/utils/k8s-watch-hook';
+import { referenceForModel } from '@console/internal/module/k8s';
import { ServiceModel } from '../../models';
import { ServiceKind } from '../../types';
import TestFunction from './TestFunction';
-type ControllerProps = {
- loaded?: boolean;
- obj: ServiceKind;
-};
-
-const Controller: FC = (props) => {
- const { loaded, obj } = props;
- return loaded ? : null;
-};
-
type TestFunctionControllerProps = {
obj: ServiceKind;
};
@@ -25,21 +16,22 @@ type TestFunctionControllerProps = {
const TestFunctionController: FC = (props) => {
const { obj } = props;
- const serverlessResources = [
- {
- kind: ServiceModel.kind,
- isList: false,
- prop: `obj`,
- namespace: obj.metadata.namespace,
- name: obj.metadata.name,
- },
- ];
+ const [service, loaded, loadError] = useK8sWatchResource({
+ kind: referenceForModel(ServiceModel),
+ isList: false,
+ namespace: obj.metadata.namespace,
+ name: obj.metadata.name,
+ });
- return (
-
-
-
- );
+ if (!loaded) {
+ return null;
+ }
+
+ if (loadError || !service) {
+ return null;
+ }
+
+ return ;
};
type Props = TestFunctionControllerProps & ModalComponentProps;
diff --git a/frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx b/frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx
index 8408f8267f9..e0bce257db5 100644
--- a/frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx
+++ b/frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx
@@ -1,29 +1,14 @@
import type { FC } from 'react';
-import { useCallback } from 'react';
+import { useCallback, useMemo } from 'react';
import { OverlayComponent } from '@console/dynamic-plugin-sdk/src/app/modal-support/OverlayProvider';
import { useOverlay } from '@console/dynamic-plugin-sdk/src/app/modal-support/useOverlay';
import { ModalComponentProps, ModalWrapper } from '@console/internal/components/factory';
-import { Firehose, FirehoseResult } from '@console/internal/components/utils';
-import { K8sResourceKind } from '@console/internal/module/k8s';
+import { useK8sWatchResources } from '@console/internal/components/utils/k8s-watch-hook';
+import { K8sResourceKind, referenceForModel } from '@console/internal/module/k8s';
+import { ConfigurationModel, RevisionModel } from '../../models';
import { getKnativeRevisionsData } from '../../topology/knative-topology-utils';
-import { knativeServingResourcesTrafficSplitting } from '../../utils/traffic-splitting-utils';
import TrafficSplitting from './TrafficSplitting';
-type ControllerProps = {
- loaded?: boolean;
- obj: K8sResourceKind;
- resources?: {
- configurations: FirehoseResult;
- revisions: FirehoseResult;
- };
-};
-
-const Controller: FC = (props) => {
- const { loaded, obj, resources } = props;
- const revisions = getKnativeRevisionsData(obj, resources);
- return loaded ? : null;
-};
-
type TrafficSplittingControllerProps = {
obj: K8sResourceKind;
};
@@ -32,13 +17,37 @@ const TrafficSplittingController: FC = (props)
const {
metadata: { namespace },
} = props.obj;
- const resources = knativeServingResourcesTrafficSplitting(namespace);
- return (
-
-
-
+ const watchResources = useMemo(
+ () => ({
+ revisions: {
+ isList: true,
+ kind: referenceForModel(RevisionModel),
+ namespace,
+ optional: true,
+ },
+ configurations: {
+ isList: true,
+ kind: referenceForModel(ConfigurationModel),
+ namespace,
+ optional: true,
+ },
+ }),
+ [namespace],
);
+
+ const resources = useK8sWatchResources<{
+ revisions: K8sResourceKind[];
+ configurations: K8sResourceKind[];
+ }>(watchResources);
+
+ const loaded =
+ Object.keys(resources).length > 0 &&
+ Object.keys(resources).every((key) => resources[key].loaded);
+
+ const revisions = getKnativeRevisionsData(props.obj, resources);
+
+ return loaded ? : null;
};
type Props = TrafficSplittingControllerProps & ModalComponentProps;