diff --git a/frontend/packages/console-shared/src/components/index.ts b/frontend/packages/console-shared/src/components/index.ts
new file mode 100644
index 00000000000..04bca77e0de
--- /dev/null
+++ b/frontend/packages/console-shared/src/components/index.ts
@@ -0,0 +1 @@
+export * from './utils';
diff --git a/frontend/packages/console-shared/src/components/utils/index.ts b/frontend/packages/console-shared/src/components/utils/index.ts
new file mode 100644
index 00000000000..b7a9b77869f
--- /dev/null
+++ b/frontend/packages/console-shared/src/components/utils/index.ts
@@ -0,0 +1 @@
+export * from './with-resources';
diff --git a/frontend/packages/console-shared/src/components/utils/with-resources.tsx b/frontend/packages/console-shared/src/components/utils/with-resources.tsx
new file mode 100644
index 00000000000..8fce426da3d
--- /dev/null
+++ b/frontend/packages/console-shared/src/components/utils/with-resources.tsx
@@ -0,0 +1,129 @@
+import * as React from 'react';
+import * as _ from 'lodash-es';
+import { connect } from 'react-redux';
+import { Map as ImmutableMap } from 'immutable';
+
+import { Firehose, inject } from '@console/internal/components/utils';
+import { K8sKind, K8sResourceKindReference } from '@console/internal/module/k8s';
+
+type ResourceToPropsResult = {
+ value: {
+ [key: string]: any;
+ };
+};
+
+type ResourcesProps = {
+ loaderComponent?: React.ComponentType;
+ onError?(): void;
+ resourceMap: any;
+ resources?: any;
+ resourceToProps?(): ResourceToPropsResult;
+ children: React.ReactNode;
+};
+
+type ResourcesState = {
+ childrenProps: any;
+ errors: any[];
+ loaded: boolean;
+};
+
+function checkErrors(resources, onError): void {
+ if (resources.length > 0) {
+ if (onError) {
+ onError(resources);
+ }
+ resources.forEach(resource => {
+ const errorMessage = _.get(
+ resource.error,
+ 'json.message',
+ `Error occured while loading ${resource.resourceConfig.resource.kind}`
+ );
+ const errorCode = _.get(resource.error, 'json.code', '');
+ const error = errorCode ? `${errorCode}: ${errorMessage}` : errorMessage;
+ console.warn(error); // eslint-disable-line
+ });
+ }
+}
+
+function getResourcesState({ resourceMap, resources = {}, resourceToProps = null }): ResourcesState {
+ const childrenProps = {};
+ const errors = [];
+ let loaded = true;
+
+ Object.keys(resourceMap).forEach(resourceKey => {
+ const resourceConfig = resourceMap[resourceKey];
+ const configResource = resourceConfig.resource;
+ const resource = _.get(resources, resourceKey);
+
+ if (resource) {
+ if (resource.loaded) {
+ childrenProps[resourceKey] = resource.data;
+ } else if (resourceConfig.required) {
+ loaded = false;
+ }
+
+ if (!resourceConfig.ignoreErrors && resource.loadError) {
+ childrenProps[resourceKey] = configResource.isList ? [] : {};
+ errors.push({ error: resource.loadError, resourceConfig });
+ }
+ } else {
+ // unknown resources (CRD not created in opeshift, etc..)
+ childrenProps[resourceKey] = configResource.isList ? [] : {};
+ }
+ });
+
+ return {
+ childrenProps: {
+ ...childrenProps,
+ ...(resourceToProps && loaded ? resourceToProps(childrenProps) : {}),
+ },
+ errors,
+ loaded,
+ };
+}
+
+const Resources = (props: ResourcesProps) => {
+ const [{ errors, loaded, childrenProps }, setResourcesState] = React.useState(getResourcesState(props));
+ const { onError, loaderComponent, children } = props;
+
+ React.useEffect(() => checkErrors(errors, onError), [errors]);
+ React.useEffect(() => setResourcesState(getResourcesState(props)), [props]);
+
+ const LoaderComponent: React.ComponentType = loaderComponent;
+
+ if (!loaded) {
+ return LoaderComponent ? : null;
+ }
+
+ return {inject(children, childrenProps)};
+};
+
+const mapStateToProps = ({ k8s }, { resourceMap }) => {
+ const resources = Object.keys(resourceMap).map(k => resourceMap[k].resource);
+ return {
+ k8sModels: resources.reduce(
+ (models, { kind }) => models.set(kind, k8s.getIn(['RESOURCES', 'models', kind])),
+ ImmutableMap()
+ ),
+ };
+};
+
+export type WithResourcesProps = {
+ k8sModels: ImmutableMap;
+} & ResourcesProps;
+
+export const WithResources = connect(mapStateToProps)(({ resourceMap, k8sModels, ...rest }: WithResourcesProps) => {
+ const kindExists = Object.keys(resourceMap).some(key => !!k8sModels.get(resourceMap[key].resource.kind));
+
+ const resourceComponent = ;
+
+ // firehose renders null if kind does not exist
+ // We can have more queries for the same kind so lets set resource.prop to key to make sure its unique
+ return kindExists ? (
+ ({ ...resourceMap[k].resource, prop: k }))}>
+ {resourceComponent}
+
+ ) : (
+ resourceComponent
+ );
+});
diff --git a/frontend/packages/console-shared/src/index.ts b/frontend/packages/console-shared/src/index.ts
index ff8b4c56321..07635cbbc8e 100644
--- a/frontend/packages/console-shared/src/index.ts
+++ b/frontend/packages/console-shared/src/index.ts
@@ -1 +1 @@
-export default {};
+export * from './components';