Skip to content

Commit

Permalink
Merge pull request #901 from bipuladh/ms-dashboard
Browse files Browse the repository at this point in the history
Adds dashboard for ocs client operator
  • Loading branch information
openshift-merge-robot authored Jun 28, 2023
2 parents 565168a + dc3a574 commit 5510f5e
Show file tree
Hide file tree
Showing 28 changed files with 571 additions and 65 deletions.
Empty file added Dockerfile.client
Empty file.
21 changes: 12 additions & 9 deletions locales/en/plugin__odf-console.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
{
"Upgrading Data Foundation Client Operator": "Upgrading Data Foundation Client Operator",
"Activity": "Activity",
"Data Foundation": "Data Foundation",
"Details": "Details",
"Service name": "Service name",
"Mode": "Mode",
"Client": "Client",
"Version": "Version",
"Inventory": "Inventory",
"Status": "Status",
"Storage Client": "Storage Client",
"Overview": "Overview",
"IP address": "IP address",
"Rest API IP address of IBM FlashSystem.": "Rest API IP address of IBM FlashSystem.",
"Username": "Username",
Expand All @@ -8,7 +20,6 @@
"Pool name": "Pool name",
"Volume mode": "Volume mode",
"Data policies": "Data policies",
"Overview": "Overview",
"Disaster recovery": "Disaster recovery",
"Create DRPolicy": "Create DRPolicy",
"Get a quick recovery in a remote or secondary cluster with a disaster recovery (DR) policy": "Get a quick recovery in a remote or secondary cluster with a disaster recovery (DR) policy",
Expand Down Expand Up @@ -42,7 +53,6 @@
"No disaster recovery policies yet": "No disaster recovery policies yet",
"Configure recovery to your failover cluster with a disaster recovery policy.<1></1>Click the <3>Create DRPolicy</3> button to get started.": "Configure recovery to your failover cluster with a disaster recovery policy.<1></1>Click the <3>Create DRPolicy</3> button to get started.",
"Name": "Name",
"Status": "Status",
"Clusters": "Clusters",
"Connected applications": "Connected applications",
"Cannot delete while connected to an application.": "Cannot delete while connected to an application.",
Expand All @@ -57,7 +67,6 @@
"Unknown": "Unknown",
"Protected PVCs": "Protected PVCs",
"{{ pvcsWithIssueCount }} with issues": "{{ pvcsWithIssueCount }} with issues",
"Activity": "Activity",
"Snapshot": "Snapshot",
"Last on: {{ lastSyncTime }}": "Last on: {{ lastSyncTime }}",
"Operator health": "Operator health",
Expand Down Expand Up @@ -88,7 +97,6 @@
"{{ issues }} with issues": "{{ issues }} with issues",
"{{ protected }} DR protected": "{{ protected }} DR protected",
"Systems": "Systems",
"Data Foundation": "Data Foundation",
"Storage System status": "Storage System status",
"StorageSystem is responsible for ensuring different types of file and block storage availability, storage capacity management and generic operations on storage.": "StorageSystem is responsible for ensuring different types of file and block storage availability, storage capacity management and generic operations on storage.",
"Storage System": "Storage System",
Expand Down Expand Up @@ -292,8 +300,6 @@
"{{capacityRatio, number}}:1": "{{capacityRatio, number}}:1",
"Compression ratio indicates the achieved compression on eligible data for this pool": "Compression ratio indicates the achieved compression on eligible data for this pool",
"Storage efficiency": "Storage efficiency",
"Details": "Details",
"Inventory": "Inventory",
"Not available": "Not available",
"Image states info": "Image states info",
"What does each state mean?": "What does each state mean?",
Expand Down Expand Up @@ -370,12 +376,10 @@
"GET {{GETLatestValue}}": "GET {{GETLatestValue}}",
"PUT {{PUTLatestValue}}": "PUT {{PUTLatestValue}}",
"OpenShift Container Storage": "OpenShift Container Storage",
"Service name": "Service name",
"System name": "System name",
"Multicloud Object Gateway": "Multicloud Object Gateway",
"RADOS Object Gateway": "RADOS Object Gateway",
"Provider": "Provider",
"Version": "Version",
"Resource providers": "Resource providers",
"A list of all Multicloud Object Gateway resources that are currently in use. Those resources are used to store data according to the buckets' policies and can be a cloud-based resource or a bare metal resource.": "A list of all Multicloud Object Gateway resources that are currently in use. Those resources are used to store data according to the buckets' policies and can be a cloud-based resource or a bare metal resource.",
"Object Service": "Object Service",
Expand All @@ -399,7 +403,6 @@
"Pods": "Pods",
"{{metricType}}": "{{metricType}}",
"Break by dropdown": "Break by dropdown",
"Mode": "Mode",
"In-transit encryption": "In-transit encryption",
"Storage Cluster": "Storage Cluster",
"Requested capacity": "Requested capacity",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"clean": "yarn clean-mco && yarn clean-odf",
"clean-mco": "cd plugins/mco && rm -rf ./dist",
"clean-odf": "cd plugins/odf && rm -rf ./dist",
"clean-client": "cd plugins/client && rm -rf ./dist",
"cypress-merge": "mochawesome-merge ./gui-test-screenshots/cypress_report*.json > ./gui-test-screenshots/cypress.json",
"cypress-generate": "marge -o ./gui-test-screenshots/ -f cypress-report -t 'OpenShift Console Cypress Test Results' -p 'OpenShift Cypress Test Results' --showPassed false --assetsDir ./gui-test-screenshots/cypress/assets ./gui-test-screenshots/cypress.json",
"cypress-postreport": "yarn cypress-merge && yarn cypress-generate",
Expand Down
Empty file added packages/client/Dockerfile
Empty file.
13 changes: 13 additions & 0 deletions packages/client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "@odf/client",
"description": "UI plugin for ODF client mode cluster",
"version": "0.0.0",
"dependencies": {
"@odf/ocs": "0.0.0",
"@odf/shared": "0.0.0"
},
"scripts": {
"build": "NODE_ENV=production PLUGIN=client I8N_NS=plugin__odf-client yarn --cwd ../.. build:plugin",
"dev": "PLUGIN=client I8N_NS=plugin__odf-client yarn --cwd ../.. server:plugin"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.odf-client-activity-card__body {
max-height: 48rem;
}
129 changes: 129 additions & 0 deletions packages/client/src/components/dashboards/cards/activity-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import * as React from 'react';
import { PVC_PROVISIONER_ANNOTATION } from '@odf/ocs/constants';
import {
eventsResource,
pvcResource,
} from '@odf/ocs/dashboards/persistent-internal/activity-card/activity-card';
import { isSubscriptionUpgradeActivity } from '@odf/ocs/dashboards/persistent-internal/activity-card/ocs-upgrade-activity';
import { isCephProvisioner, isPersistentStorageEvent } from '@odf/ocs/utils';
import { useDeepCompareMemoize } from '@odf/shared/hooks/deep-compare-memoize';
import { SubscriptionModel } from '@odf/shared/models';
import { getAnnotations, getName } from '@odf/shared/selectors';
import {
K8sResourceKind,
PersistentVolumeClaimKind,
SubscriptionKind,
} 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 {
ActivityBody,
ActivityItem,
OngoingActivityBody,
RecentEventsBody,
} from '@openshift-console/dynamic-plugin-sdk-internal';
import { EventKind } from '@openshift-console/dynamic-plugin-sdk/lib/api/internal-types';
import * as _ from 'lodash-es';
import { Card, CardHeader, CardTitle } from '@patternfly/react-core';
import { CLIENT_OPERATOR } from '../../../constants';
import './activity-card.scss';

const ClientOperatorUpgradeActivity: React.FC = () => {
const { t } = useCustomTranslation();

return (
<ActivityItem>
{t('Upgrading Data Foundation Client Operator')}
</ActivityItem>
);
};

const getClientOperatorSubscription = (
subscriptions: K8sResourceKind[]
): SubscriptionKind =>
_.find(
subscriptions,
(item) => item?.spec?.name === CLIENT_OPERATOR
) as SubscriptionKind;

const RecentEvent: React.FC = () => {
const [pvcs, pvcLoaded, pvcLoadError] =
useK8sWatchResource<PersistentVolumeClaimKind[]>(pvcResource);
const [events, eventsLoaded, eventsLoadError] =
useK8sWatchResource<EventKind[]>(eventsResource);

const validPVC = pvcs
.filter((obj) =>
isCephProvisioner(getAnnotations(obj)?.[PVC_PROVISIONER_ANNOTATION])
)
.map(getName);
const memoizedPVCNames = useDeepCompareMemoize(validPVC, true);

const clientEventsFilter = React.useCallback(
() => isPersistentStorageEvent(memoizedPVCNames),
[memoizedPVCNames]
);

const eventObject = {
data: events,
loaded: eventsLoaded && pvcLoaded,
kind: 'Event',
loadError: pvcLoadError || eventsLoadError,
};

return (
<RecentEventsBody events={eventObject} filter={clientEventsFilter()} />
);
};

export const subscriptionResource = {
isList: true,
kind: referenceForModel(SubscriptionModel),
namespaced: false,
};

const OngoingActivity = () => {
const [subscriptions, subLoaded] =
useK8sWatchResource<K8sResourceKind[]>(subscriptionResource);

const clientOperatorSubscription: SubscriptionKind =
getClientOperatorSubscription(subscriptions);

const resourceActivities = [];

if (isSubscriptionUpgradeActivity(clientOperatorSubscription)) {
resourceActivities.push({
resource: clientOperatorSubscription,
timestamp: clientOperatorSubscription?.status?.lastUpdated,
loader: () => Promise.resolve(ClientOperatorUpgradeActivity),
});
}

return (
<OngoingActivityBody
loaded={subLoaded}
resourceActivities={resourceActivities}
/>
);
};

export const ActivityCard: React.FC = React.memo(() => {
const { t } = useCustomTranslation();

return (
<Card className="co-overview-card--gradient">
<CardHeader>
<CardTitle>{t('Activity')}</CardTitle>
</CardHeader>
<ActivityBody className="odf-client-activity-card__body">
<OngoingActivity />
<RecentEvent />
</ActivityBody>
</Card>
);
});

ActivityCard.displayName = 'ActivityCard';

export default ActivityCard;
52 changes: 52 additions & 0 deletions packages/client/src/components/dashboards/cards/details-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from 'react';
import { useFetchCsv } from '@odf/shared/hooks/use-fetch-csv';
import { K8sResourceKind } from '@odf/shared/types';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { DetailsBody } from '@openshift-console/dynamic-plugin-sdk-internal';
import { OverviewDetailItem as DetailItem } from '@openshift-console/plugin-shared';
import { Card, CardHeader, CardTitle, CardBody } from '@patternfly/react-core';
import { CLIENT_OPERATOR } from '../../../constants';

const getOperatorVersion = (operator: K8sResourceKind): string =>
operator?.spec?.version || '';

export const DetailsCard: React.FC = () => {
const { t } = useCustomTranslation();

const [csv, csvLoaded, csvError] = useFetchCsv({
specName: CLIENT_OPERATOR,
});

const subscriptionVersion = getOperatorVersion(csv);

const serviceName = t('Data Foundation');

return (
<Card>
<CardHeader>
<CardTitle>{t('Details')}</CardTitle>
</CardHeader>
<CardBody>
<DetailsBody>
<DetailItem key="service_name" title={t('Service name')}>
{serviceName}
</DetailItem>
<DetailItem key="mode" title={t('Mode')}>
{t('Client')}
</DetailItem>
<DetailItem
key="version"
title={t('Version')}
isLoading={!csvLoaded}
error={csvError?.message}
data-test-id="cluster-subscription"
>
{subscriptionVersion}
</DetailItem>
</DetailsBody>
</CardBody>
</Card>
);
};

export default DetailsCard;
4 changes: 4 additions & 0 deletions packages/client/src/components/dashboards/cards/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './activity-card';
export * from './details-card';
export * from './inventory-card';
export * from './status-card';
77 changes: 77 additions & 0 deletions packages/client/src/components/dashboards/cards/inventory-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as React from 'react';
import { getCephPVCs, getCephPVs, getCephSC } from '@odf/ocs/utils';
import {
PersistentVolumeClaimModel,
PersistentVolumeModel,
StorageClassModel,
} from '@odf/shared/models';
import { getName } from '@odf/shared/selectors';
import {
getPVCStatusGroups,
getPVStatusGroups,
} from '@odf/shared/status/Inventory';
import { K8sResourceKind, StorageClassResourceKind } from '@odf/shared/types';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { useK8sWatchResources } from '@openshift-console/dynamic-plugin-sdk';
import { ResourceInventoryItem } from '@openshift-console/dynamic-plugin-sdk-internal';
import { Card, CardBody, CardHeader, CardTitle } from '@patternfly/react-core';

const watchResources = {
pvcs: {
isList: true,
kind: PersistentVolumeClaimModel.kind,
},
pvs: {
isList: true,
kind: PersistentVolumeModel.kind,
},
sc: {
isList: true,
kind: StorageClassModel.kind,
},
};
export const InventoryCard: React.FC = () => {
const { t } = useCustomTranslation();

const resources = useK8sWatchResources(watchResources);

const pvcsLoaded = resources?.pvcs?.loaded;
const pvcsLoadError = resources?.pvcs?.loadError;
const pvcsData = (resources?.pvcs?.data ?? []) as K8sResourceKind[];

const pvsLoaded = resources?.pvs?.loaded;
const pvsLoadError = resources?.pvs?.loadError;
const pvsData = (resources?.pvs?.data ?? []) as K8sResourceKind[];

const scData = (resources?.sc?.data ?? []) as StorageClassResourceKind[];
const filteredCephSC = getCephSC(scData);
const filteredSCNames = filteredCephSC.map(getName);

return (
<Card>
<CardHeader>
<CardTitle>{t('Inventory')}</CardTitle>
</CardHeader>
<CardBody>
<ResourceInventoryItem
dataTest="inventory-pvc"
isLoading={!pvcsLoaded}
error={!!pvcsLoadError}
kind={PersistentVolumeClaimModel as any}
resources={getCephPVCs(filteredSCNames, pvcsData, pvsData)}
mapper={getPVCStatusGroups}
showLink={false}
/>
<ResourceInventoryItem
dataTest="inventory-pv"
isLoading={!pvsLoaded}
error={!!pvsLoadError}
kind={PersistentVolumeModel as any}
resources={getCephPVs(pvsData)}
mapper={getPVStatusGroups}
showLink={false}
/>
</CardBody>
</Card>
);
};
Loading

0 comments on commit 5510f5e

Please sign in to comment.