@stolostron/multicluster-sdk
Version:
Provides extensions and APIs that dynamic plugins can use to leverage multicluster capabilities provided by Red Hat Advanced Cluster Management.
102 lines • 6.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useFleetK8sWatchResource = useFleetK8sWatchResource;
/* Copyright Contributors to the Open Cluster Management project */
const useHubClusterName_1 = require("./useHubClusterName");
const dynamic_plugin_sdk_1 = require("@openshift-console/dynamic-plugin-sdk");
const useIsFleetAvailable_1 = require("./useIsFleetAvailable");
const react_1 = require("react");
const useDeepCompareMemoize_1 = require("../internal/hooks/useDeepCompareMemoize");
const useFleetK8sAPIPath_1 = require("./useFleetK8sAPIPath");
const fleetK8sWatchResource_1 = require("../internal/fleetK8sWatchResource");
/**
* A hook for watching Kubernetes resources with support for multi-cluster environments.
* It is equivalent to the [`useK8sWatchResource`](https://github.com/openshift/console/blob/main/frontend/packages/console-dynamic-plugin-sdk/docs/api.md#usek8swatchresource)
* hook from the [OpenShift Console Dynamic Plugin SDK](https://www.npmjs.com/package/@openshift-console/dynamic-plugin-sdk)
* but allows you to retrieve data from any cluster managed by Red Hat Advanced Cluster Management.
*
* It automatically detects the hub cluster and handles resource watching on both hub
* and remote clusters using WebSocket connections for real-time updates.
*
* @param initResource - The resource to watch. Can be null to disable the watch.
* @param initResource.cluster - The managed cluster on which the resource resides; null or undefined for the hub cluster
* @param initResource.groupVersionKind - The group, version, and kind of the resource (e.g., `{ group: 'apps', version: 'v1', kind: 'Deployment' }`)
* @param initResource.name - The name of the resource (for watching a specific resource)
* @param initResource.namespace - The namespace of the resource
* @param initResource.isList - Whether to watch a list of resources (true) or a single resource (false)
* @param initResource.selector - Label selector to filter resources (e.g., `{ matchLabels: { app: 'myapp' } }`)
* @param initResource.fieldSelector - Field selector to filter resources (e.g., `status.phase=Running`)
* @param initResource.limit - Maximum number of resources to return (not supported yet)
* @param initResource.namespaced - Whether the resource is namespaced (not supported yet)
* @param initResource.optional - If true, errors will not be thrown when the resource is not found (not supported yet)
* @param initResource.partialMetadata - If true, only fetch metadata for the resources (not supported yet)
* @returns A tuple containing the watched resource data, a boolean indicating if the data is loaded,
* and any error that occurred. The hook returns live-updating data.
*
* @example
* ```typescript
* // Watch pods on a remote cluster
* const [pods, loaded, error] = useFleetK8sWatchResource({
* groupVersionKind: { version: 'v1', kind: 'Pod' },
* isList: true,
* cluster: 'remote-cluster',
* namespace: 'default'
* })
*
* // Watch a specific deployment on hub cluster
* const [deployment, loaded, error] = useFleetK8sWatchResource({
* groupVersionKind: { group: 'apps', version: 'v1', kind: 'Deployment' },
* name: 'my-app',
* namespace: 'default'
* })
*
* // Watch pods with label selector on remote cluster
* const [filteredPods, loaded, error] = useFleetK8sWatchResource({
* groupVersionKind: { version: 'v1', kind: 'Pod' },
* isList: true,
* cluster: 'remote-cluster',
* namespace: 'default',
* selector: { matchLabels: { app: 'myapp' } }
* })
* ```
*/
function useFleetK8sWatchResource(initResource) {
const isFleetAvailable = (0, useIsFleetAvailable_1.useIsFleetAvailable)();
const [hubClusterName, hubClusterNameLoaded] = (0, useHubClusterName_1.useHubClusterName)();
const [memoizedResource, memoizedResourceChanged] = (0, useDeepCompareMemoize_1.useDeepCompareMemoize)(initResource, true);
const { cluster, ...resource } = memoizedResource ?? {};
const { groupVersionKind } = resource;
const [model, modelLoading] = (0, dynamic_plugin_sdk_1.useK8sModel)(groupVersionKind);
const [backendAPIPath, backendPathLoaded] = (0, useFleetK8sAPIPath_1.useFleetK8sAPIPath)(cluster);
const waitingForHubClusterName = !!cluster && !hubClusterNameLoaded;
const isProbablyFleetQuery = !!cluster && cluster !== hubClusterName;
// avoid using the fleet query if it is not available
// avoid using either query if we are still waiting for the hub name to compare against the supplied cluster name
const useFleet = isProbablyFleetQuery && isFleetAvailable && !waitingForHubClusterName;
const useLocal = !isProbablyFleetQuery && !waitingForHubClusterName;
const isResourceNull = !memoizedResource || !groupVersionKind;
const getInitialResult = (0, fleetK8sWatchResource_1.useGetInitialResult)();
const initialResult = getInitialResult(memoizedResource, model, backendAPIPath);
const [fleetResult, setFleetResult] = (0, react_1.useState)(initialResult);
if (memoizedResourceChanged) {
setFleetResult(initialResult);
}
const fleetResultTuple = (0, react_1.useMemo)(() => {
const { data, loaded, loadError } = fleetResult;
return [data, loaded, loadError];
}, [fleetResult]);
const localResult = (0, dynamic_plugin_sdk_1.useK8sWatchResource)(useLocal && !isResourceNull ? resource : null);
(0, react_1.useEffect)(() => {
if (useFleet && !isResourceNull && backendPathLoaded && backendAPIPath && !modelLoading && model) {
const requestPath = (0, fleetK8sWatchResource_1.getRequestPathFromResource)(memoizedResource, model, backendAPIPath);
const unsubscribe = (0, fleetK8sWatchResource_1.subscribe)(memoizedResource, requestPath, setFleetResult);
(0, fleetK8sWatchResource_1.startWatch)(memoizedResource, model, backendAPIPath);
return () => {
unsubscribe();
(0, fleetK8sWatchResource_1.stopWatch)(memoizedResource, model, backendAPIPath);
};
}
}, [backendAPIPath, backendPathLoaded, isResourceNull, memoizedResource, model, modelLoading, useFleet]);
return useLocal ? localResult : fleetResultTuple;
}
//# sourceMappingURL=useFleetK8sWatchResource.js.map