Skip to content

Commit

Permalink
Merge pull request #1307 from sgratch/handle-non-all-ns-users-fetchin…
Browse files Browse the repository at this point in the history
…g-from-inventory

🐞 Handle fetching from inventory for users without a full namespaces access role
  • Loading branch information
yaacov committed Sep 3, 2024
2 parents d966985 + cc5f48d commit 7e85021
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { useEffect, useRef, useState } from 'react';

import { ProviderInventory, ProvidersInventoryList } from '@kubev2v/types';
import { consoleFetchJSON } from '@openshift-console/dynamic-plugin-sdk';
import {
ProviderInventory,
ProviderModel,
ProvidersInventoryList,
V1beta1Provider,
} from '@kubev2v/types';
import { consoleFetchJSON, k8sGet, useFlag } from '@openshift-console/dynamic-plugin-sdk';

import { getInventoryApiUrl, hasObjectChangedInGivenFields } from '../utils/helpers';

Expand All @@ -12,9 +17,11 @@ const INVENTORY_TYPES: string[] = ['openshift', 'openstack', 'ovirt', 'vsphere',
/**
* Configuration parameters for useProvidersInventoryList hook.
* @interface
* @property {string} namespace - namespace for fetching inventory's providers data for. Used only for users with limited namespaces privileges.
* @property {number} interval - Polling interval in milliseconds.
*/
interface UseInventoryParams {
namespace?: string;
interval?: number; // Polling interval in milliseconds
}

Expand All @@ -32,29 +39,34 @@ interface UseInventoryResult {
}

/**
* A React hook to fetch and maintain an up-to-date list of providers' inventory data.
* A React hook to fetch and maintain an up-to-date list of providers' inventory data, belongs to a given namespace or to all namespaces
* (based on the namespace parameter).
* For users with limited namespaces privileges, only the given namespace's providers inventory data are fetched.
* It fetches data on mount and then at the specified interval.
*
* @param {UseInventoryParams} params - Configuration parameters for the hook.
* @param {string} namespace - namespace to fetch providers' inventory data for. if set to null, then fetch for all namespaces.
* @param {number} [params.interval=10000] - Interval (in milliseconds) to fetch new data at.
*
* @returns {UseInventoryResult} result - Contains the inventory data, the loading state, and the error state.
*/
export const useProvidersInventoryList = ({
namespace = null,
interval = 20000,
}: UseInventoryParams): UseInventoryResult => {
const [inventory, setInventory] = useState<ProvidersInventoryList | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<Error | null>(null);
const oldDataRef = useRef(null);
const oldErrorRef = useRef(null);
const canList: boolean = useFlag('CAN_LIST_NS');

useEffect(() => {
const fetchData = async () => {
try {
const newInventory: ProvidersInventoryList = await consoleFetchJSON(
getInventoryApiUrl(`providers?detail=1`),
);
const newInventory: ProvidersInventoryList = canList
? await consoleFetchJSON(getInventoryApiUrl(`providers?detail=1`)) // Fetch all providers
: await getInventoryByNamespace(namespace); // Fetch single namespace's providers

updateInventoryIfChanged(newInventory, DEFAULT_FIELDS_TO_COMPARE);
handleError(null);
Expand All @@ -67,7 +79,66 @@ export const useProvidersInventoryList = ({

const intervalId = setInterval(fetchData, interval);
return () => clearInterval(intervalId);
}, [interval]);
}, [interval, namespace]);

/**
* Fetching providers list by namespace.
*
* @param {string} namespace to fetch providers by.
* @returns {Promise<V1beta1Provider[]>} providers list by namespace.
*/
const k8sGetProviders = async (namespace: string): Promise<V1beta1Provider[]> => {
type K8sListResponse<T> = {
items: T[];
};
const providersList = await k8sGet({ model: ProviderModel, ns: namespace });

return (providersList as K8sListResponse<V1beta1Provider>)?.items;
};

/**
* For users with limited namespaces privileges, fetch only the given namespace's providers.
*
* @param {string} namespace namespace to fetch providers' inventory data for.
* @returns {void}
*/
const getInventoryByNamespace = async (namespace: string): Promise<ProvidersInventoryList> => {
const newInventory: ProvidersInventoryList = {
openshift: [],
openstack: [],
ovirt: [],
vsphere: [],
ova: [],
};

const providers = await k8sGetProviders(namespace);

const readyProviders = providers?.filter(
(provider: V1beta1Provider) => provider.status.phase === 'Ready',
);

const inventoryProviderURL = (provider: V1beta1Provider) =>
`providers/${provider.spec.type}/${provider.metadata.uid}`;

const allPromises = Promise.all(
readyProviders.map(async (provider) => {
return await consoleFetchJSON(getInventoryApiUrl(inventoryProviderURL(provider)));
}),
)
.then((newInventoryProviders) => {
newInventoryProviders.map((newInventoryProvider) =>
newInventory[newInventoryProvider.type].push(newInventoryProvider),
);

return newInventory;
})
.catch(() => {
// throw error;
return null;
});

return allPromises;
};

/**
* Handles any errors thrown when trying to fetch the inventory.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ const ProvidersListPage: React.FC<{
inventory,
loading: inventoryLoading,
error: inventoryError,
} = useProvidersInventoryList({});
} = useProvidersInventoryList({ namespace });

const permissions = useGetDeleteAndEditAccessReview({
model: ProviderModel,
Expand Down

0 comments on commit 7e85021

Please sign in to comment.