Skip to content

Commit

Permalink
Merge pull request #1438 from TimothyAsirJeyasing/update-sync-status-…
Browse files Browse the repository at this point in the history
…bz-2282834

Fix sync status update issue in Protected Application page
  • Loading branch information
openshift-merge-bot[bot] authored Jun 14, 2024
2 parents 10266e8 + 3373ec9 commit 8e5eb13
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 55 deletions.
1 change: 1 addition & 0 deletions locales/en/plugin__odf-console.json
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
"Unknown": "Unknown",
"Namespaces": "Namespaces",
"Volume snapshot": "Volume snapshot",
"Kubernetes object snapshot": "Kubernetes object snapshot",
"Last on: {{ syncTime }}": "Last on: {{ syncTime }}",
"Subscription": "Subscription",
"Last snapshot synced": "Last snapshot synced",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,16 @@ export const NamespaceSection: React.FC<CommonProps> = ({
);
};

export const SnapshotSection: React.FC<CommonProps> = ({
export const SnapshotSection: React.FC<SnapshotSectionProps> = ({
selectedApplication,
isVolumeSnapshot,
}) => {
const { t } = useCustomTranslation();
const [syncTime, setSyncTime] = React.useState('N/A');
const lastSyncTime =
selectedApplication?.placementControlInfo?.[0]?.lastVolumeGroupSyncTime;
const lastSyncTime = isVolumeSnapshot
? selectedApplication?.placementControlInfo?.[0]?.lastVolumeGroupSyncTime
: selectedApplication?.placementControlInfo?.[0]
?.kubeObjectLastProtectionTime;

const updateSyncTime = React.useCallback(() => {
setSyncTime(
Expand All @@ -203,9 +206,13 @@ export const SnapshotSection: React.FC<CommonProps> = ({

useScheduler(updateSyncTime);

const title = isVolumeSnapshot
? t('Volume snapshot')
: t('Kubernetes object snapshot');

return (
<div className="mco-dashboard__contentColumn">
<StatusText>{t('Volume snapshot')}</StatusText>
<StatusText>{title}</StatusText>
<Text className="text-muted">
{t('Last on: {{ syncTime }}', {
syncTime: syncTime,
Expand Down Expand Up @@ -391,3 +398,7 @@ type SubscriptionRowProps = {
type SubscriptionWiseRPOMap = {
[subscriptionName: string]: string;
};

type SnapshotSectionProps = CommonProps & {
isVolumeSnapshot?: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,14 @@ const DiscoveredAppCard: React.FC<AppWiseCardProps> = ({
<ActivitySection selectedApplication={selectedApplication} />
</GridItem>
<GridItem lg={3} rowSpan={8} sm={12}>
<SnapshotSection selectedApplication={selectedApplication} />
<SnapshotSection
selectedApplication={selectedApplication}
isVolumeSnapshot
/>
</GridItem>

{
// ToDo: Enable snapshot card for kube object last sync time once the DRPC has the status.
/*<GridItem lg={6} rowSpan={8} sm={12}>
<GridItem lg={6} rowSpan={8} sm={12}>
<SnapshotSection selectedApplication={selectedApplication} />
</GridItem>*/
}
</GridItem>
<GridItem lg={12} rowSpan={8} sm={12}>
<VolumeSummarySection
protectedPVCData={protectedPVCData}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
MANAGED_CLUSTER_CONDITION_AVAILABLE,
APPLICATION_TYPE,
LEAST_SECONDS_IN_PROMETHEUS,
REPLICATION_TYPE,
} from '@odf/mco/constants';
import { DRClusterAppsMap, ProtectedAppsMap } from '@odf/mco/types';
import {
Expand Down Expand Up @@ -76,14 +77,15 @@ const checkVolumeReplicationHealth = (
const checkKubeObjBackupHealth = (
protectedAppMap: ProtectedAppsMap
): boolean => {
const kubeObjectLastTransitionTime =
protectedAppMap.placementControlInfo[0].kubeObjectLastTransitionTime;
const { kubeObjectLastProtectionTime, replicationType } =
protectedAppMap.placementControlInfo[0];
const objCaptureInterval =
protectedAppMap.placementControlInfo[0].kubeObjSyncInterval;
return protectedAppMap.appType === APPLICATION_TYPE.DISCOVERED
return protectedAppMap.appType === APPLICATION_TYPE.DISCOVERED &&
replicationType === REPLICATION_TYPE.ASYNC
? getVolumeReplicationHealth(
!!kubeObjectLastTransitionTime
? getTimeDifferenceInSeconds(kubeObjectLastTransitionTime)
!!kubeObjectLastProtectionTime
? getTimeDifferenceInSeconds(kubeObjectLastProtectionTime)
: LEAST_SECONDS_IN_PROMETHEUS,
objCaptureInterval
)[0] !== VOLUME_REPLICATION_HEALTH.HEALTHY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
filerDRClustersUsingDRPolicy,
findDRPolicyUsingDRPC,
findDRType,
getKubeObjectLastTransitionTime,
getLastAppDeploymentClusterName,
getProtectedPVCsFromDRPC,
} from '@odf/mco/utils';
Expand Down Expand Up @@ -122,10 +121,8 @@ export const useDiscoveredParser: UseDiscoveredParser = (
kubeObjSyncInterval:
drPlacementControl.spec?.kubeObjectProtection
?.captureInterval,
// lastTransitionTime just to decide the status, it can't be considered as last synced on.
kubeObjectLastTransitionTime: getKubeObjectLastTransitionTime(
drPlacementControl?.status?.resourceConditions?.conditions
),
kubeObjectLastProtectionTime:
drPlacementControl?.status?.lastKubeObjectProtectionTime,
},
],
});
Expand Down
6 changes: 3 additions & 3 deletions packages/mco/components/protected-applications/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,9 @@ export const StatusDetails: React.FC<ExpandableComponentProps> = ({
syncStatusInfo.volumeLastGroupSyncTime || (
<Text className="text-muted"> {t('No data available')}</Text>
),
// For kube object, it is always no data available message.
// lastTransitionTime just to decide the status, it can't be considered as last synced on.
<Text className="text-muted"> {t('No data available')}</Text>,
syncStatusInfo.kubeObjectLastProtectionTime || (
<Text className="text-muted"> {t('No data available')}</Text>
),
];
return (
<DescriptionList_ columnModifier={'3Col'}>
Expand Down
19 changes: 12 additions & 7 deletions packages/mco/components/protected-applications/list-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { DRPlacementControlKind, DRPolicyKind } from '../../types';
import {
getLastAppDeploymentClusterName,
getDRPolicyName,
getKubeObjectLastTransitionTime,
getReplicationType,
} from '../../utils';
import {
EmptyRowMessage,
Expand Down Expand Up @@ -261,21 +261,26 @@ export const ProtectedApplicationsListPage: React.FC = () => {
const volumesSchedulingInterval = drPolicies.find(
(policy) => getName(policy) === app.spec?.drPolicyRef?.name
)?.spec?.schedulingInterval;
const replicationType = getReplicationType(volumesSchedulingInterval);
const volumesLastSyncTime = app?.status?.lastGroupSyncTime;
const kubeObjectsSchedulingInterval =
app.spec?.kubeObjectProtection?.captureInterval;
const kubeObjectLastTransitionTime = getKubeObjectLastTransitionTime(
app?.status?.resourceConditions?.conditions
);
const kubeObjectLastProtectionTime =
app?.status?.lastKubeObjectProtectionTime;
acc[getName(app)] = {
volumeReplicationStatus: getReplicationHealth(
volumesLastSyncTime,
volumesSchedulingInterval
volumesSchedulingInterval,
replicationType
),
volumeLastGroupSyncTime: formatTime(volumesLastSyncTime),
kubeObjectReplicationStatus: getReplicationHealth(
kubeObjectLastTransitionTime,
kubeObjectsSchedulingInterval
kubeObjectLastProtectionTime,
kubeObjectsSchedulingInterval,
replicationType
),
kubeObjectLastProtectionTime: formatTime(
kubeObjectLastProtectionTime
),
};

Expand Down
8 changes: 7 additions & 1 deletion packages/mco/components/protected-applications/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
LEAST_SECONDS_IN_PROMETHEUS,
DR_BASE_ROUTE,
DRActionType,
REPLICATION_TYPE,
} from '../../constants';
import { DRPlacementControlModel } from '../../models';
import { DRPlacementControlKind } from '../../types';
Expand Down Expand Up @@ -88,8 +89,12 @@ export const isCleanupPending = (drpc: DRPlacementControlKind): boolean =>

export const getReplicationHealth = (
lastSyncTime: string,
schedulingInterval: string
schedulingInterval: string,
replicationType: REPLICATION_TYPE
): VOLUME_REPLICATION_HEALTH => {
if (replicationType === REPLICATION_TYPE.SYNC) {
return VOLUME_REPLICATION_HEALTH.HEALTHY;
}
const seconds = !!lastSyncTime
? getTimeDifferenceInSeconds(lastSyncTime)
: LEAST_SECONDS_IN_PROMETHEUS;
Expand Down Expand Up @@ -138,6 +143,7 @@ export type SyncStatusInfo = {
volumeReplicationStatus: VOLUME_REPLICATION_HEALTH;
volumeLastGroupSyncTime: string;
kubeObjectReplicationStatus: VOLUME_REPLICATION_HEALTH;
kubeObjectLastProtectionTime: string;
};

export const getAppWorstSyncStatus = (
Expand Down
3 changes: 0 additions & 3 deletions packages/mco/constants/disaster-recovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,3 @@ export const EnrollDiscoveredApplicationStepNames = (t: TFunction) => ({
[EnrollDiscoveredApplicationSteps.Replication]: t('Replication'),
[EnrollDiscoveredApplicationSteps.Review]: t('Review'),
});

// DRPC status condition types
export const KUBE_OBJECT_SYNC_CONDITION_TYPE = 'ClusterDataProtected';
4 changes: 2 additions & 2 deletions packages/mco/types/dashboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export type PlacementControlInfo = Partial<{
// Subscription name(Only for display purpose)
subscriptions?: string[];
// Only applicable for Discovered type
// ClusterDataProtected condition transition time
kubeObjectLastTransitionTime?: string;
// Recent successful kube object protection Time
kubeObjectLastProtectionTime?: string;
// Kube resources backup interval(interval + unit(m, h, d))
kubeObjSyncInterval?: string;
}>;
Expand Down
2 changes: 2 additions & 0 deletions packages/mco/types/ramen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export type DRPlacementControlKind = K8sResourceCommon & {
protectedNamespaces?: string[];
};
status?: {
// The time of the most recent successful kube object protection
lastKubeObjectProtectionTime?: string;
conditions?: K8sResourceCondition[];
resourceConditions?: {
conditions?: K8sResourceCondition[];
Expand Down
18 changes: 0 additions & 18 deletions packages/mco/utils/disaster-recovery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
GreenCheckCircleIcon,
Alert,
AlertStates,
K8sResourceCondition,
} from '@openshift-console/dynamic-plugin-sdk';
import {
Operator,
Expand All @@ -34,7 +33,6 @@ import {
LABEL_SPLIT_CHAR,
LABELS_SPLIT_CHAR,
DR_BLOCK_LISTED_LABELS,
KUBE_OBJECT_SYNC_CONDITION_TYPE,
} from '../constants';
import {
DRPC_NAMESPACE_ANNOTATION,
Expand Down Expand Up @@ -639,19 +637,3 @@ export const getLabelsFromSearchResult = (
return acc;
}, {});
};

export const getKubeObjectLastTransitionTime = (
conditions: K8sResourceCondition[]
): string => {
const condition = conditions?.find(
(condition) => condition.type === KUBE_OBJECT_SYNC_CONDITION_TYPE
);
if (condition?.status === 'True') {
// For "True", checking the lastTransitionTime to ensure there is no reconcile problem on ramen.
// If there is any reconcile problem, And if status stuck in "True"
// then status will be displayed based on lastTransitionTime (critical/warning).
return condition.lastTransitionTime;
}
// Returning empty to show critical status immediately.
return '';
};

0 comments on commit 8e5eb13

Please sign in to comment.