Skip to content

Commit

Permalink
Use ManagedClusterView for ODF info - DRPolicy creation
Browse files Browse the repository at this point in the history
  • Loading branch information
SanjalKatiyar committed Jul 24, 2024
1 parent e4d70c8 commit 28f357d
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 51 deletions.
155 changes: 104 additions & 51 deletions packages/mco/components/create-dr-policy/select-cluster-list.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
import * as React from 'react';
import { getManagedClusterResourceObj } from '@odf/mco/hooks';
import { ODFInfoYamlObject } from '@odf/mco/types';
import {
getMajorVersion,
ValidateManagedClusterCondition,
getValueFromClusterClaim,
isMinimumSupportedODFVersion,
getManagedClusterViewName,
} from '@odf/mco/utils';
import { StatusBox } from '@odf/shared/generic/status-box';
import { getName, getNamespace } from '@odf/shared/selectors';
import { ConfigMapKind } from '@odf/shared/types';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { referenceForModel } from '@odf/shared/utils';
import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk';
import { Select, SelectOption } from '@patternfly/react-core/deprecated';
import { safeLoad } from 'js-yaml';
import {
DataList,
DataListItem,
Expand All @@ -33,9 +38,9 @@ import {
MANAGED_CLUSTER_REGION_CLAIM,
MANAGED_CLUSTER_JOINED,
MANAGED_CLUSTER_CONDITION_AVAILABLE,
ClusterClaimTypes,
} from '../../constants';
import { ACMManagedClusterKind } from '../../types';
import { ACMManagedClusterViewModel } from '../../models';
import { ACMManagedClusterKind, ACMManagedClusterViewKind } from '../../types';
import {
DRPolicyAction,
DRPolicyActionType,
Expand All @@ -59,43 +64,61 @@ const getFilteredClusters = (
};

const getODFInfo = (
managedCluster: ACMManagedClusterKind,
requiredODFVersion: string
requiredODFVersion: string,
odfInfoConfigData: { [key: string]: string }
): ODFConfigInfoType => {
const clusterClaims = managedCluster?.status?.clusterClaims;
const odfVersion = getValueFromClusterClaim(
clusterClaims,
ClusterClaimTypes.ODF_VERSION
);
const storageClusterNamespacedName = getValueFromClusterClaim(
clusterClaims,
ClusterClaimTypes.STORAGE_CLUSTER_NAME
);
const storageSystemNamespacedName = getValueFromClusterClaim(
clusterClaims,
ClusterClaimTypes.STORAGE_SYSTEM_NAME
);
const cephFsid = getValueFromClusterClaim(
clusterClaims,
ClusterClaimTypes.CEPH_FSID
);
const storageClusterCount = getValueFromClusterClaim(
clusterClaims,
ClusterClaimTypes.STORAGE_CLUSTER_COUNT
);
return {
odfVersion: odfVersion,
isValidODFVersion: isMinimumSupportedODFVersion(
getMajorVersion(odfVersion),
requiredODFVersion
),
storageClusterCount: Number(storageClusterCount || '0'),
storageClusterInfo: {
storageClusterNamespacedName: storageClusterNamespacedName,
storageSystemNamespacedName: storageSystemNamespacedName,
cephFSID: cephFsid,
},
};
try {
// Managed cluster with multiple StorageSystems is not currently supported for DR
// ToDo: Update this once we add support for multiple clusters
const odfInfoKey = Object.keys(odfInfoConfigData)[0];
const odfInfoYaml = odfInfoConfigData[odfInfoKey];
const odfInfo: ODFInfoYamlObject = safeLoad(odfInfoYaml);

const storageClusterName = odfInfo?.storageCluster?.namespacedName?.name;
const storageClusterNamespace =
odfInfo?.storageCluster?.namespacedName?.namespace;
const storageSystemNamespace = odfInfo?.storageSystemName;

const odfVersion = odfInfo?.version;
const storageClusterCount = Object.keys(odfInfoConfigData).length;
const storageClusterNamespacedName =
!!storageClusterName && !!storageClusterNamespace
? storageClusterName + '/' + storageClusterNamespace
: '';
const storageSystemNamespacedName =
!!storageSystemNamespace && !!storageClusterNamespace
? storageSystemNamespace + '/' + storageClusterNamespace
: '';
const cephFSID = odfInfo?.storageCluster?.cephClusterFSID;

return {
odfVersion,
isValidODFVersion: isMinimumSupportedODFVersion(
getMajorVersion(odfVersion),
requiredODFVersion
),
storageClusterCount,
storageClusterInfo: {
storageClusterNamespacedName,
storageSystemNamespacedName,
cephFSID,
},
};
} catch (err) {
// eslint-disable-next-line no-console
console.error(err);

return {
odfVersion: '',
isValidODFVersion: false,
storageClusterCount: 0,
storageClusterInfo: {
storageClusterNamespacedName: '',
storageSystemNamespacedName: '',
cephFSID: '',
},
};
}
};

const filterRegions = (filteredClusters: ManagedClusterInfoType[]) =>
Expand All @@ -108,7 +131,8 @@ const filterRegions = (filteredClusters: ManagedClusterInfoType[]) =>

const getManagedClusterInfo = (
cluster: ACMManagedClusterKind,
requiredODFVersion: string
requiredODFVersion: string,
odfInfoConfigData: { [key: string]: string }
): ManagedClusterInfoType => ({
name: getName(cluster),
namesapce: getNamespace(cluster),
Expand All @@ -120,7 +144,7 @@ const getManagedClusterInfo = (
cluster,
MANAGED_CLUSTER_CONDITION_AVAILABLE
),
odfInfo: getODFInfo(cluster, requiredODFVersion),
odfInfo: getODFInfo(requiredODFVersion, odfInfoConfigData),
});

const isChecked = (clusters: ManagedClusterInfoType[], clusterName: string) =>
Expand Down Expand Up @@ -149,18 +173,47 @@ export const SelectClusterList: React.FC<SelectClusterListProps> = ({
ACMManagedClusterKind[]
>(getManagedClusterResourceObj());

const [mcvs, mcvsLoaded, mcvsLoadError] = useK8sWatchResource<
ACMManagedClusterViewKind[]
>({
kind: referenceForModel(ACMManagedClusterViewModel),
isList: true,
});

const allLoaded = loaded && mcvsLoaded;
const anyError = loadError || mcvsLoadError;

const clusters: ManagedClusterInfoType[] = React.useMemo(() => {
if (!!requiredODFVersion && loaded && !loadError) {
return managedClusters?.reduce(
(acc, cluster) =>
ValidateManagedClusterCondition(cluster, MANAGED_CLUSTER_JOINED)
? [...acc, getManagedClusterInfo(cluster, requiredODFVersion)]
: acc,
[]
);
if (!!requiredODFVersion && allLoaded && !anyError) {
return managedClusters?.reduce((acc, cluster) => {
if (ValidateManagedClusterCondition(cluster, MANAGED_CLUSTER_JOINED)) {
// OCS creates a ConfigMap on the managed clusters, with details about StorageClusters, Clients.
// MCO creates ManagedClusterView on the hub cluster, referencing that ConfigMap.
const managedClusterName = getName(cluster);
const mcv =
mcvs.find(
(obj: ACMManagedClusterViewKind) =>
getName(obj) ===
getManagedClusterViewName(managedClusterName) &&
getNamespace(obj) === managedClusterName
) || {};
const odfInfoConfigData =
(mcv.status?.result as ConfigMapKind)?.data || {};
return [
...acc,
getManagedClusterInfo(
cluster,
requiredODFVersion,
odfInfoConfigData
),
];
}

return acc;
}, []);
}
return [];
}, [requiredODFVersion, managedClusters, loaded, loadError]);
}, [requiredODFVersion, managedClusters, mcvs, allLoaded, anyError]);

const filteredClusters: ManagedClusterInfoType[] = React.useMemo(
() => getFilteredClusters(clusters, region, nameSearch),
Expand Down Expand Up @@ -245,8 +298,8 @@ export const SelectClusterList: React.FC<SelectClusterListProps> = ({
</Toolbar>
<StatusBox
data={!!nameSearch ? filteredClusters : managedClusters}
loadError={loadError}
loaded={loaded && !!clusters.length}
loadError={anyError}
loaded={allLoaded && !!clusters.length}
>
<DataList
aria-label={t('Select cluster list')}
Expand Down
2 changes: 2 additions & 0 deletions packages/mco/constants/disaster-recovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,5 @@ export const EnrollDiscoveredApplicationStepNames = (t: TFunction) => ({
[EnrollDiscoveredApplicationSteps.Replication]: t('Replication'),
[EnrollDiscoveredApplicationSteps.Review]: t('Review'),
});

export const MCV_NAME_TEMPLATE = 'odf-multicluster-mcv-';
22 changes: 22 additions & 0 deletions packages/mco/types/odf-mco.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,25 @@ export type MirrorPeerKind = K8sResourceCommon & {
type: string;
};
};

export type ConnectedClient = {
name: string;
clusterId: string;
};

export type InfoStorageCluster = {
namespacedName: {
name: string;
namespace: string;
};
storageProviderEndpoint: string;
cephClusterFSID: string;
};

export type ODFInfoYamlObject = {
version: string;
deploymentType: string;
clients: ConnectedClient[];
storageCluster: InfoStorageCluster;
storageSystemName: string;
};
4 changes: 4 additions & 0 deletions packages/mco/utils/disaster-recovery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
LABELS_SPLIT_CHAR,
DR_BLOCK_LISTED_LABELS,
PLACEMENT_RULE_REF_LABEL,
MCV_NAME_TEMPLATE,
} from '../constants';
import {
DRPC_NAMESPACE_ANNOTATION,
Expand Down Expand Up @@ -643,3 +644,6 @@ export const getLabelsFromSearchResult = (
return acc;
}, {});
};

export const getManagedClusterViewName = (managedClusterName: string): string =>
MCV_NAME_TEMPLATE + managedClusterName;

0 comments on commit 28f357d

Please sign in to comment.