Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added the options to select via pvc and namespace for the breakdown card #905

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions locales/en/plugin__odf-console.json
Original file line number Diff line number Diff line change
Expand Up @@ -409,8 +409,10 @@
"Utilization": "Utilization",
"Expanding StorageCluster": "Expanding StorageCluster",
"Upgrading Data Foundation's Operator": "Upgrading Data Foundation's Operator",
"Used capacity breakdown": "Used capacity breakdown",
"PersistentVolumeClaims": "PersistentVolumeClaims",
"This card shows the used capacity for different Kubernetes resources. The figures shown represent the Usable storage, meaning that data replication is not taken into consideration.": "This card shows the used capacity for different Kubernetes resources. The figures shown represent the Usable storage, meaning that data replication is not taken into consideration.",
"Select a namespace:": "Select a namespace:",
"Only showing PVCs that are being mounted on an active pod": "Only showing PVCs that are being mounted on an active pod",
"Internal": "Internal",
"Raw capacity is the absolute total disk space available to the array subsystem.": "Raw capacity is the absolute total disk space available to the array subsystem.",
"Troubleshoot": "Troubleshoot",
Expand Down Expand Up @@ -957,6 +959,7 @@
"Only lowercase letters, numbers, non-consecutive periods, or hyphens": "Only lowercase letters, numbers, non-consecutive periods, or hyphens",
"Cannot be used before": "Cannot be used before",
"Not enough usage data": "Not enough usage data",
"Total requests: ": "Total requests: ",
"used": "used",
"available": "available",
"Other": "Other",
Expand Down Expand Up @@ -1041,7 +1044,6 @@
"PersistentVolume": "PersistentVolume",
"PersistentVolumes": "PersistentVolumes",
"PersistentVolumeClaim": "PersistentVolumeClaim",
"PersistentVolumeClaims": "PersistentVolumeClaims",
"Namespaces": "Namespaces",
"ConfigMap": "ConfigMap",
"ConfigMaps": "ConfigMaps",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,43 @@
}

.ceph-capacity-breakdown-card__header {
border-bottom: var(--pf-global--BorderWidth--sm) solid var(--pf-global--BorderColor--100);
display: flex;
align-items: center;
justify-content: space-between;
}

.ceph-capacity-breakdown-card-header__dropdown {
max-width: 12em;
max-width: 30em;
@media screen and (min-width: $pf-global--breakpoint--lg) {
min-width: 12em;
}
}

.odf-capacity-breakdown-card-pvc-namespace {
&__header {
display: flex;
align-items: center;
justify-content: end;
padding: var(--pf-global--spacer--md) var(--pf-global--spacer--lg) 0;
}
&__dropdown {
width: -webkit-fill-available;
max-width: 30em;
}
&__dropdown > div {
max-height: 300px;
@media screen and (min-width: $pf-global--breakpoint--lg) {
min-width: 12em;
}
max-width: 30em;
overflow: auto;
}
&__title {
padding-right: var(--pf-global--spacer--lg);
}
}

.odf-capacity-breakdown-card-pvc-description {
debjyoti-pandit marked this conversation as resolved.
Show resolved Hide resolved
font-size: var(--pf-global--FontSize--xs);
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import * as React from 'react';
import { namespaceResource } from '@odf/core/resources';
import { BreakdownCardBody } from '@odf/shared/dashboards/breakdown-card/breakdown-body';
import { getSelectOptions } from '@odf/shared/dashboards/breakdown-card/breakdown-dropdown';
import ResourceDropdown from '@odf/shared/dropdown/ResourceDropdown';
import { FieldLevelHelp } from '@odf/shared/generic/FieldLevelHelp';
import {
useCustomPrometheusPoll,
usePrometheusBasePath,
} from '@odf/shared/hooks/custom-prometheus-poll';
import { BreakdownCardFields } from '@odf/shared/queries';
import { NamespaceModel } from '@odf/shared/models';
import {
BreakdownCardFields,
BreakdownCardFieldsWithParams,
} from '@odf/shared/queries';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import {
getInstantVectorStats,
humanizeBinaryBytes,
sortInstantVectorStats,
} from '@odf/shared/utils';
import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk';
import {
Select,
SelectProps,
Expand All @@ -22,7 +29,7 @@ import {
CardTitle,
} from '@patternfly/react-core';
import {
breakdownQueryMapCEPH,
getBreakdownMetricsQuery,
CEPH_CAPACITY_BREAKDOWN_QUERIES,
StorageDashboardQuery,
} from '../../../queries/ceph-storage';
Expand All @@ -34,23 +41,42 @@ const modelByUsedQueryMap = {
[BreakdownCardFields.PODS]: StorageDashboardQuery.PODS_BY_USED,
[BreakdownCardFields.STORAGE_CLASSES]:
StorageDashboardQuery.STORAGE_CLASSES_BY_USED,
[BreakdownCardFieldsWithParams.PVCS]:
StorageDashboardQuery.PVC_NAMESPACES_BY_USED,
};

const modelByTotalQueryMap = {
[BreakdownCardFields.PROJECTS]: StorageDashboardQuery.PROJECTS_TOTAL_USED,
[BreakdownCardFields.PODS]: StorageDashboardQuery.PODS_TOTAL_USED,
[BreakdownCardFields.STORAGE_CLASSES]:
StorageDashboardQuery.STORAGE_CLASSES_TOTAL_USED,
[BreakdownCardFieldsWithParams.PVCS]:
StorageDashboardQuery.PVC_NAMESPACES_TOTAL_USED,
};

const BreakdownCard: React.FC = () => {
const { t } = useCustomTranslation();
const [metricType, setMetricType] = React.useState<BreakdownCardFields>(
BreakdownCardFields.PROJECTS
);
const [metricType, setMetricType] = React.useState<
BreakdownCardFields | BreakdownCardFieldsWithParams
>(BreakdownCardFields.PROJECTS);
const [isOpenBreakdownSelect, setBreakdownSelect] = React.useState(false);
const [pvcNamespace, setPVCNamespace] = React.useState('');
debjyoti-pandit marked this conversation as resolved.
Show resolved Hide resolved

const initialSelection = React.useCallback(
(allNamespace: K8sResourceCommon[]): K8sResourceCommon => {
const initialResource = allNamespace?.sort((a, b) =>
a.metadata.name.localeCompare(b.metadata.name)
)[0];
setPVCNamespace(initialResource?.metadata.name || '');
return initialResource;
},
[]
);

const { queries, model, metric } = breakdownQueryMapCEPH[metricType];
const { queries, model, metric } = React.useMemo(
() => getBreakdownMetricsQuery(metricType, pvcNamespace),
[metricType, pvcNamespace]
);

const [modelByUsed, modelUsedError, modelUsedLoading] =
useCustomPrometheusPoll({
Expand Down Expand Up @@ -99,15 +125,19 @@ const BreakdownCard: React.FC = () => {
name: t('Pods'),
id: BreakdownCardFields.PODS,
},
{
name: t('PersistentVolumeClaims'),
id: BreakdownCardFieldsWithParams.PVCS,
},
];
const breakdownSelectItems = getSelectOptions(dropdownOptions);

return (
<Card>
<CardHeader className="ceph-capacity-breakdown-card__header">
<CardTitle>
{t('Used capacity breakdown')}
<FieldLevelHelp>
<CardTitle id="breakdown-card-title">
{t('Requested capacity')}
<FieldLevelHelp testId="breakdown-card-helper-text">
{t(
'This card shows the used capacity for different Kubernetes resources. The figures shown represent the Usable storage, meaning that data replication is not taken into consideration.'
Comment on lines +138 to 142
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2023-06-26 at 6 29 39 PM here "Requested capacity" has diff meaning than the one we are defining on this Card.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@debjyoti-pandit with UX once...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SanjalKatiyar I have tagged you in a IBM slack thread where discussed the same with UX.

Copy link
Collaborator

@SanjalKatiyar SanjalKatiyar Jun 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw that... thanks for tagging again !
but that seems diff to me to what I pointed here... term "Requested capacity" have 2 diff meaning at 2 diff places, if that's okay with UX we are good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, didn't notice initially that you were part of the thread so tagged you again. and regarding the changes I am not quite clear on what are you suggesting.?

)}
Expand All @@ -125,10 +155,31 @@ const BreakdownCard: React.FC = () => {
})}
aria-label={t('Break By Dropdown')}
isCheckboxSelectionBadgeHidden
id="breakdown-card-metrics-dropdown"
>
{breakdownSelectItems}
</Select>
</CardHeader>
{metricType === BreakdownCardFieldsWithParams.PVCS && (
<div className="odf-capacity-breakdown-card-pvc-namespace__header">
<div
id="odf-capacity-breakdown-card-pvc-namespace-title"
className="odf-capacity-breakdown-card-pvc-namespace__title"
>
{t('Select a namespace:')}
</div>
<ResourceDropdown<K8sResourceCommon>
className="odf-capacity-breakdown-card-pvc-namespace__dropdown"
resource={namespaceResource}
resourceModel={NamespaceModel}
initialSelection={initialSelection}
onSelect={(ns) => {
setPVCNamespace(ns?.metadata.name);
}}
data-test="odf-capacity-breakdown-card-pvc-namespace-dropdown"
/>
</div>
)}
<CardBody className="ceph-capacity-breakdown-card__body">
<BreakdownCardBody
isLoading={!dataLoaded}
Expand All @@ -138,8 +189,17 @@ const BreakdownCard: React.FC = () => {
capacityUsed={cephUsed}
metricModel={model}
humanize={humanize}
isPersistentInternal={true}
/>
</CardBody>
{metricType === BreakdownCardFieldsWithParams.PVCS &&
!queriesLoadError &&
top5MetricsStats.length > 0 &&
cephUsed && (
<CardBody className="odf-capacity-breakdown-card-pvc-description">
{t('Only showing PVCs that are being mounted on an active pod')}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is true for all options (pods/stprageclass/project/pvc)...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I see in the UX, this is what is mentioned https://www.sketch.com/s/c43ed755-7832-4de4-84a0-4b4ce815f366/a/1KbRavk

</CardBody>
)}
</Card>
);
};
Expand Down
25 changes: 23 additions & 2 deletions packages/ocs/queries/ceph-storage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { StorageClassModel, PodModel, ProjectModel } from '@odf/shared/models';
import {
StorageClassModel,
PodModel,
ProjectModel,
PersistentVolumeClaimModel,
} from '@odf/shared/models';
import {
BreakdownCardFields,
BreakdownCardFieldsValues,
BreakdownCardFieldsWithParams,
BreakdownCardQueryMap,
} from '@odf/shared/queries';

Expand Down Expand Up @@ -122,6 +129,20 @@ export const breakdownQueryMapCEPH: BreakdownCardQueryMap = {
},
};

export const getBreakdownMetricsQuery = (
metricType: BreakdownCardFieldsWithParams | BreakdownCardFields,
namespace?: string
): BreakdownCardFieldsValues => {
if (metricType === BreakdownCardFieldsWithParams.PVCS) {
return {
model: PersistentVolumeClaimModel,
metric: 'persistentvolumeclaim',
queries: getPVCNamespaceQuery(namespace),
};
}
return breakdownQueryMapCEPH[metricType];
};

export const CAPACITY_INFO_QUERIES = {
[StorageDashboardQuery.RAW_CAPACITY_TOTAL]: 'ceph_cluster_total_bytes',
[StorageDashboardQuery.RAW_CAPACITY_USED]:
Expand Down Expand Up @@ -192,7 +213,7 @@ export const utilizationPopoverQueryMap = [
},
];

export const getPVCNamespaceQuery = (namespace: string) => {
export const getPVCNamespaceQuery = (namespace: string = '') => {
const queries = {
[StorageDashboardQuery.PVC_NAMESPACES_BY_USED]: `sum by (namespace, persistentvolumeclaim) (kubelet_volume_stats_used_bytes{namespace='${namespace}'} * on (namespace, persistentvolumeclaim) group_left(storageclass, provisioner) (kube_persistentvolumeclaim_info * on (storageclass) group_left(provisioner) kube_storageclass_info {provisioner=~"(.*rbd.csi.ceph.com)|(.*cephfs.csi.ceph.com)|(ceph.rook.io/block)"}))`,
[StorageDashboardQuery.PVC_NAMESPACES_TOTAL_USED]: `sum(sum by (namespace, persistentvolumeclaim) (kubelet_volume_stats_used_bytes{namespace='${namespace}'} * on (namespace, persistentvolumeclaim) group_left(storageclass, provisioner) (kube_persistentvolumeclaim_info * on (storageclass) group_left(provisioner) kube_storageclass_info {provisioner=~"(.*rbd.csi.ceph.com)|(.*cephfs.csi.ceph.com)|(ceph.rook.io/block)"})))`,
Expand Down
6 changes: 6 additions & 0 deletions packages/odf/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
StatefulSetModel,
ReplicaSetModel,
DaemonSetModel,
NamespaceModel,
} from '@odf/shared/models';
import { referenceForModel } from '@odf/shared/utils';
import { WatchK8sResource } from '@openshift-console/dynamic-plugin-sdk';
Expand Down Expand Up @@ -144,3 +145,8 @@ export const namespaceStoreResource = {
isList: true,
namespace: CEPH_STORAGE_NAMESPACE,
};

export const namespaceResource = {
kind: referenceForModel(NamespaceModel),
isList: true,
};
10 changes: 7 additions & 3 deletions packages/shared/src/dashboards/breakdown-card/breakdown-body.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const BreakdownCardBody: React.FC<BreakdownBodyProps> = ({
hasLoadError,
ocsVersion = '',
labelPadding,
isPersistentInternal,
}) => {
const { t } = useCustomTranslation();

Expand Down Expand Up @@ -59,16 +60,18 @@ export const BreakdownCardBody: React.FC<BreakdownBodyProps> = ({
<Grid>
<GridItem span={4}>
<TotalCapacityBody
capacity={humanize(capacityUsed).string}
suffix={t('used')}
prefix={isPersistentInternal && t('Total requests: ')}
capacity={humanize(metricTotal).string}
suffix={!isPersistentInternal && t('used')}
styleCapacityAsBold={isPersistentInternal}
/>
</GridItem>
<GridItem span={4} />
<GridItem span={4}>
{capacityAvailable && (
<TotalCapacityBody
capacity={humanize(capacityAvailable).string}
suffix={t('available')}
suffix={!isPersistentInternal && t('available')}
className="capacity-breakdown-card__available-body text-secondary"
/>
)}
Expand Down Expand Up @@ -97,4 +100,5 @@ export type BreakdownBodyProps = {
humanize: Humanize;
ocsVersion?: string;
labelPadding?: LabelPadding;
isPersistentInternal?: boolean;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import './breakdown-card.scss';

export const TotalCapacityBody: React.FC<TotalCapacityBodyProps> = ({
capacity,
prefix,
suffix,
className,
styleCapacityAsBold,
}) => {
return (
<p
Expand All @@ -14,13 +16,16 @@ export const TotalCapacityBody: React.FC<TotalCapacityBodyProps> = ({
className
)}
>
{capacity} {suffix}
{prefix} {styleCapacityAsBold ? <strong>{capacity}</strong> : capacity}{' '}
{suffix}
</p>
);
};

type TotalCapacityBodyProps = {
capacity: string;
suffix: string;
prefix?: string;
suffix?: string;
className?: string;
styleCapacityAsBold?: boolean;
};
12 changes: 12 additions & 0 deletions packages/shared/src/queries/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ export enum BreakdownCardFields {
PODS = 'Pods',
}

export enum BreakdownCardFieldsWithParams {
PVCS = 'PVCs',
}

export type BreakdownCardQueryMap = {
[key in BreakdownCardFields]: {
model: K8sModel;
Expand All @@ -15,3 +19,11 @@ export type BreakdownCardQueryMap = {
};
};
};

export type BreakdownCardFieldsValues = {
model: K8sModel;
metric: string;
queries: {
[key: string]: string;
};
};