Skip to content

Commit

Permalink
Add parser for subscription application
Browse files Browse the repository at this point in the history
Signed-off-by: Timothy Asir Jeyasingh <[email protected]>
  • Loading branch information
TimothyAsirJeyasing committed Dec 5, 2023
1 parent 9b55fef commit a2a16cb
Show file tree
Hide file tree
Showing 15 changed files with 596 additions and 225 deletions.
4 changes: 2 additions & 2 deletions locales/en/plugin__odf-console.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@
"Peer connection": "Peer connection",
" {{ peerConnectedCount }} Connected": " {{ peerConnectedCount }} Connected",
"Total applications (ApplicationSet)": "Total applications (ApplicationSet)",
" {{ protectedAppSetsCount }} protected apps": " {{ protectedAppSetsCount }} protected apps",
" {{ appsWithIssues }} of {{ protectedAppSetsCount }} apps with issues": " {{ appsWithIssues }} of {{ protectedAppSetsCount }} apps with issues",
" {{ protectedAppCount }} protected apps": " {{ protectedAppCount }} protected apps",
" {{ appsWithIssues }} of {{ protectedAppCount }} apps with issues": " {{ appsWithIssues }} of {{ protectedAppCount }} apps with issues",
"Current value: ": "Current value: ",
"Max value: ": "Max value: ",
"Min value: ": "Min value: ",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import * as React from 'react';
import { APPLICATION_TYPE, DRPC_STATUS } from '@odf/mco/constants';
import {
DisasterRecoveryResourceKind,
useArgoApplicationSetResourceWatch,
} from '@odf/mco/hooks';
import {
ACMManagedClusterKind,
DRClusterAppsMap,
DRClusterKind,
} from '@odf/mco/types';
import {
findDRType,
findDeploymentClusters,
getProtectedPVCsFromDRPC,
getRemoteNamespaceFromAppSet,
} from '@odf/mco/utils';
import { getName, getNamespace } from '@odf/shared/selectors';
import * as _ from 'lodash-es';

export const useApplicationSetParser = (
drResources: DisasterRecoveryResourceKind,
drLoaded: boolean,
drLoadError: any
): DRClusterAppsMap => {
const [argoApplicationSetResources, loaded, loadError] =
useArgoApplicationSetResourceWatch({
drResources: {
data: drResources,
loaded: drLoaded,
loadError: drLoadError,
},
});

const drClusters: DRClusterKind[] = drResources?.drClusters;
const managedClusters: ACMManagedClusterKind[] =
argoApplicationSetResources?.managedClusters;
const formattedArgoAppSetResources =
argoApplicationSetResources?.formattedResources;

const drClusterAppsMap: DRClusterAppsMap = React.useMemo(() => {
if (loaded && !loadError) {
// DRCluster to its ManagedCluster mapping
const drClusterAppsMap: DRClusterAppsMap = drClusters.reduce(
(acc, drCluster) => {
acc[getName(drCluster)] = {
managedCluster: managedClusters.find(
(managedCluster) => getName(managedCluster) === getName(drCluster)
),
totalAppCount: 0,
protectedApps: [],
};
return acc;
},
{} as DRClusterAppsMap
);

// DRCluster to its ApplicationSets (total and protected) mapping
formattedArgoAppSetResources.forEach((argoApplicationSetResource) => {
const { application } = argoApplicationSetResource || {};
const {
drClusters: currentDrClusters,
drPlacementControl,
drPolicy,
placementDecision,
} = argoApplicationSetResource?.placements?.[0] || {};
const deploymentClusters = findDeploymentClusters(
placementDecision,
drPlacementControl
);
deploymentClusters.forEach((decisionCluster) => {
if (drClusterAppsMap.hasOwnProperty(decisionCluster)) {
drClusterAppsMap[decisionCluster].totalAppCount =
drClusterAppsMap[decisionCluster].totalAppCount + 1;
if (!_.isEmpty(drPlacementControl)) {
drClusterAppsMap[decisionCluster].protectedApps.push({
appName: getName(application),
appNamespace: getNamespace(application),
appKind: application?.kind,
appAPIVersion: application?.apiVersion,
appType: APPLICATION_TYPE.APPSET,
placementInfo: [
{
deploymentClusterName: decisionCluster,
drpcName: getName(drPlacementControl),
drpcNamespace: getNamespace(drPlacementControl),
protectedPVCs: getProtectedPVCsFromDRPC(drPlacementControl),
replicationType: findDRType(currentDrClusters),
syncInterval: drPolicy?.spec?.schedulingInterval,
workloadNamespace:
getRemoteNamespaceFromAppSet(application),
failoverCluster: drPlacementControl?.spec?.failoverCluster,
preferredCluster:
drPlacementControl?.spec?.preferredCluster,
lastGroupSyncTime:
drPlacementControl?.status?.lastGroupSyncTime,
status: drPlacementControl?.status?.phase as DRPC_STATUS,
},
],
});
}
}
});
});
return drClusterAppsMap;
}
return {};
}, [
drClusters,
managedClusters,
formattedArgoAppSetResources,
loaded,
loadError,
]);

return drClusterAppsMap;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { useMemo } from 'react';
import { APPLICATION_TYPE, DRPC_STATUS } from '@odf/mco/constants';
import {
DisasterRecoveryResourceKind,
useSubscriptionResourceWatch,
} from '@odf/mco/hooks';
import { ACMManagedClusterKind, DRClusterAppsMap } from '@odf/mco/types';
import {
findDeploymentClusters,
getProtectedPVCsFromDRPC,
} from '@odf/mco/utils';
import { getName, getNamespace } from '@odf/shared/selectors';
import * as _ from 'lodash-es';

export const useSubscriptionParser = (
drResources: DisasterRecoveryResourceKind,
drLoaded: boolean,
drLoadError: any
): DRClusterAppsMap => {
const [subscriptionResources, loaded, loadError] =
useSubscriptionResourceWatch({
drResources: {
data: drResources,
loaded: drLoaded,
loadError: drLoadError,
},
});

const drClusterAppsMap: DRClusterAppsMap = useMemo(() => {
const drClusters = drResources?.drClusters || [];

const managedClusters: ACMManagedClusterKind[] =
subscriptionResources.reduce((result, subscriptionResource) => {
const clusters = subscriptionResource?.managedClusters || [];
result.push(...clusters);
return result;
}, []);

if (loaded && !loadError) {
// DRCluster to its ManagedCluster mapping
const drClusterAppsMap: DRClusterAppsMap = drClusters.reduce(
(acc, drCluster) => {
acc[getName(drCluster)] = {
managedCluster: managedClusters.find(
(managedCluster) => getName(managedCluster) === getName(drCluster)
),
totalAppCount: subscriptionResources.reduce(
(count, { subscriptionGroupInfo }) => {
return (
count +
(subscriptionGroupInfo?.some(
(subscriptionGroup) =>
subscriptionGroup?.placementDecision ===
getName(drCluster)
)
? 1
: 0)
);
},
0
),
protectedApps: [],
};
return acc;
},
{} as DRClusterAppsMap
);

// DRCluster to its Subscriptions (total and protected) mapping
subscriptionResources.forEach((subscriptionResource) => {
const { application, subscriptionGroupInfo } =
subscriptionResource || {};
subscriptionGroupInfo?.forEach((subscriptionGroup) => {
const { placementDecision, drInfo } = subscriptionGroup || {};
const deploymentClusters = findDeploymentClusters(
placementDecision,
drInfo?.drPlacementControl
);

deploymentClusters?.forEach((decisionCluster) => {
if (drClusterAppsMap.hasOwnProperty(decisionCluster)) {
drClusterAppsMap[decisionCluster].totalAppCount += 1;
if (
drInfo?.drPlacementControl &&
!Array.isArray(drInfo.drPlacementControl) &&
!_.isEmpty(drInfo.drPlacementControl)
) {
drClusterAppsMap[decisionCluster].protectedApps.push({
appName: getName(application),
appNamespace: getNamespace(application),
appKind: application?.kind,
appAPIVersion: application?.apiVersion,
appType: APPLICATION_TYPE.SUBSCRIPTION,
placementInfo: [
{
deploymentClusterName: decisionCluster,
drpcName: getName(drInfo.drPlacementControl),
drpcNamespace: getNamespace(drInfo.drPlacementControl),
protectedPVCs: getProtectedPVCsFromDRPC(
drInfo.drPlacementControl
),
replicationType: null,
syncInterval: drInfo.drPolicy?.spec?.schedulingInterval,
workloadNamespace: null,
failoverCluster:
drInfo.drPlacementControl?.spec?.failoverCluster ||
null,
preferredCluster:
drInfo.drPlacementControl?.spec?.preferredCluster ||
null,
lastGroupSyncTime:
drInfo.drPlacementControl?.status?.lastGroupSyncTime ||
null,
status:
(drInfo.drPlacementControl?.status
?.phase as DRPC_STATUS) || null,
},
],
});
}
}
});
});
});

return drClusterAppsMap;
}

return {};
}, [drResources?.drClusters, subscriptionResources, loaded, loadError]);

return drClusterAppsMap;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import * as React from 'react';
import { DRPC_STATUS } from '@odf/mco/constants';
import { PlacementInfo, ProtectedAppSetsMap } from '@odf/mco/types';
import { PlacementInfo, ProtectedAppMap } from '@odf/mco/types';
import { getDRStatus } from '@odf/mco/utils';
import { utcDateTimeFormatter } from '@odf/shared/details-page/datetime';
import { fromNow } from '@odf/shared/details-page/datetime';
Expand Down Expand Up @@ -108,6 +108,6 @@ export const SnapshotSection: React.FC<CommonProps> = ({ selectedAppSet }) => {
};

type CommonProps = {
selectedAppSet: ProtectedAppSetsMap;
selectedAppSet: ProtectedAppMap;
lastSyncTimeData?: PrometheusResponse;
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
applicationDetails,
} from '@odf/mco/constants';
import {
DrClusterAppsMap,
DRClusterAppsMap,
AppSetObj,
ProtectedAppSetsMap,
ProtectedAppMap,
ACMManagedClusterViewKind,
ProtectedPVCData,
MirrorPeerKind,
Expand Down Expand Up @@ -170,10 +170,10 @@ export const ClusterAppCard: React.FC = () => {
const allLoaded = loaded && !csvLoading && !lastSyncTimeLoading && mcvsLoaded;
const anyError = lastSyncTimeError || csvError || loadError || mcvsLoadError;

const selectedAppSet: ProtectedAppSetsMap = React.useMemo(() => {
const selectedAppSet: ProtectedAppMap = React.useMemo(() => {
const { name, namespace } = appSet || {};
return !!namespace && name !== ALL_APPS
? drClusterAppsMap[cluster]?.protectedAppSets?.find(
? drClusterAppsMap[cluster]?.protectedApps?.find(
(protectedAppSet) =>
protectedAppSet?.appName === name &&
protectedAppSet?.appNamespace === namespace
Expand All @@ -184,10 +184,10 @@ export const ClusterAppCard: React.FC = () => {
const protectedPVCData: ProtectedPVCData[] = React.useMemo(() => {
const pvcsData =
(mcvsLoaded && !mcvsLoadError && getProtectedPVCFromVRG(mcvs)) || [];
const protectedAppSets = !!selectedAppSet
const protectedApps = !!selectedAppSet
? [selectedAppSet]
: drClusterAppsMap[cluster]?.protectedAppSets;
return filterPVCDataUsingAppsets(pvcsData, protectedAppSets);
: drClusterAppsMap[cluster]?.protectedApps;
return filterPVCDataUsingAppsets(pvcsData, protectedApps);
}, [
drClusterAppsMap,
selectedAppSet,
Expand Down Expand Up @@ -268,10 +268,10 @@ type ClusterWiseCardProps = {
lastSyncTimeData: PrometheusResponse;
protectedPVCData: ProtectedPVCData[];
csvData: PrometheusResponse;
clusterResources: DrClusterAppsMap;
clusterResources: DRClusterAppsMap;
};

type AppWiseCardProps = {
protectedPVCData: ProtectedPVCData[];
selectedAppSet: ProtectedAppSetsMap;
selectedAppSet: ProtectedAppMap;
};
Loading

0 comments on commit a2a16cb

Please sign in to comment.