Skip to content

Commit 42ee9a4

Browse files
feat: add storage/groups endpoint (#1273)
1 parent d0ef412 commit 42ee9a4

File tree

21 files changed

+402
-168
lines changed

21 files changed

+402
-168
lines changed

src/components/GroupInfo/GroupInfo.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ export function GroupInfo<T extends Partial<PreparedStorageGroup>>({
1616
data,
1717
...infoViewerProps
1818
}: GroupInfoProps<T>) {
19-
const {GroupID, PoolName, Used, Limit, ErasureSpecies} = data;
19+
const {GroupId, PoolName, Used, Limit, ErasureSpecies} = data;
2020

2121
const groupInfo = [];
2222

23-
if (valueIsDefined(GroupID)) {
24-
groupInfo.push({label: groupInfoKeyset('group-id'), value: GroupID});
23+
if (valueIsDefined(GroupId)) {
24+
groupInfo.push({label: groupInfoKeyset('group-id'), value: GroupId});
2525
}
2626
if (valueIsDefined(PoolName)) {
2727
groupInfo.push({label: groupInfoKeyset('pool-name'), value: PoolName});

src/containers/Storage/Storage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export const Storage = ({additionalNodesProps, database, nodeId}: StorageProps)
9595
},
9696
);
9797
const groupsQuery = storageApi.useGetStorageGroupsInfoQuery(
98-
{database, visibleEntities, nodeId},
98+
{database, with: visibleEntities, nodeId},
9999
{
100100
skip: storageType !== STORAGE_TYPES.groups,
101101
pollingInterval: autoRefreshInterval,

src/containers/Storage/StorageGroups/columns/getStorageGroupsColumns.tsx

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {UsageLabel} from '../../../../components/UsageLabel/UsageLabel';
1010
import {VDiskWithDonorsStack} from '../../../../components/VDisk/VDiskWithDonorsStack';
1111
import {VISIBLE_ENTITIES} from '../../../../store/reducers/storage/constants';
1212
import type {VisibleEntities} from '../../../../store/reducers/storage/types';
13-
import {EFlag} from '../../../../types/api/enums';
1413
import type {NodesMap} from '../../../../types/store/nodesList';
1514
import {cn} from '../../../../utils/cn';
1615
import {stringifyVdiskId} from '../../../../utils/dataFormatters/dataFormatters';
@@ -36,7 +35,7 @@ export const GROUPS_COLUMNS_IDS = {
3635
Used: 'Used',
3736
Limit: 'Limit',
3837
Usage: 'Usage',
39-
UsedSpaceFlag: 'UsedSpaceFlag',
38+
DiskSpace: 'DiskSpace',
4039
Read: 'Read',
4140
Write: 'Write',
4241
VDisks: 'VDisks',
@@ -140,9 +139,9 @@ const groupIdColumn: StorageGroupsColumn = {
140139
header: 'Group ID',
141140
width: 130,
142141
render: ({row}) => {
143-
return <span className={b('group-id')}>{row.GroupID}</span>;
142+
return <span className={b('group-id')}>{row.GroupId}</span>;
144143
},
145-
sortAccessor: (row) => Number(row.GroupID),
144+
sortAccessor: (row) => Number(row.GroupId),
146145
align: DataTable.RIGHT,
147146
};
148147

@@ -167,22 +166,11 @@ const limitColumn: StorageGroupsColumn = {
167166
};
168167

169168
const usedSpaceFlagColumn: StorageGroupsColumn = {
170-
name: GROUPS_COLUMNS_IDS.UsedSpaceFlag,
169+
name: GROUPS_COLUMNS_IDS.DiskSpace,
171170
header: 'Space',
172171
width: 110,
173172
render: ({row}) => {
174-
const value = row.UsedSpaceFlag;
175-
176-
let color = EFlag.Red;
177-
178-
if (value < 100) {
179-
color = EFlag.Green;
180-
} else if (value < 10000) {
181-
color = EFlag.Yellow;
182-
} else if (value < 1000000) {
183-
color = EFlag.Orange;
184-
}
185-
return <EntityStatus status={color} />;
173+
return <EntityStatus status={row.DiskSpace} />;
186174
},
187175
align: DataTable.CENTER,
188176
};
@@ -309,13 +297,12 @@ const filterStorageGroupsColumns = (
309297
}
310298

311299
if (visibleEntities === VISIBLE_ENTITIES.missing) {
312-
return columns.filter((col) => col.name !== GROUPS_COLUMNS_IDS.UsedSpaceFlag);
300+
return columns.filter((col) => col.name !== GROUPS_COLUMNS_IDS.DiskSpace);
313301
}
314302

315303
return columns.filter((col) => {
316304
return (
317-
col.name !== GROUPS_COLUMNS_IDS.Degraded &&
318-
col.name !== GROUPS_COLUMNS_IDS.UsedSpaceFlag
305+
col.name !== GROUPS_COLUMNS_IDS.Degraded && col.name !== GROUPS_COLUMNS_IDS.DiskSpace
319306
);
320307
});
321308
};

src/containers/Storage/StorageGroups/getGroups.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import type {
33
PreparedStorageGroup,
44
PreparedStorageGroupFilters,
55
} from '../../../store/reducers/storage/types';
6-
import {prepareStorageGroupsResponse} from '../../../store/reducers/storage/utils';
7-
import {EVersion} from '../../../types/api/storage';
8-
import type {StorageSortValue} from '../../../utils/storage';
6+
import {prepareStorageResponse} from '../../../store/reducers/storage/utils';
7+
import type {StorageV2Sort} from '../../../types/api/storage';
8+
import {prepareSortValue} from '../../../utils/filters';
99

1010
const getConcurrentId = (limit?: number, offset?: number) => {
1111
return `getStorageGroups|offset${offset}|limit${limit}`;
@@ -19,21 +19,22 @@ export const getStorageGroups: FetchData<
1919
const {sortOrder, columnId} = sortParams ?? {};
2020
const {searchValue, visibleEntities, database, nodeId} = filters ?? {};
2121

22+
const sort = prepareSortValue(columnId, sortOrder) as StorageV2Sort;
23+
2224
const response = await window.api.getStorageInfo(
2325
{
24-
version: EVersion.v2,
26+
version: 'v2',
2527
limit,
2628
offset,
27-
sortOrder,
28-
sortValue: columnId as StorageSortValue,
29+
sort,
2930
filter: searchValue,
30-
visibleEntities,
31+
with: visibleEntities,
3132
database,
3233
nodeId,
3334
},
3435
{concurrentId: getConcurrentId(limit, offset)},
3536
);
36-
const preparedResponse = prepareStorageGroupsResponse(response);
37+
const preparedResponse = prepareStorageResponse(response);
3738

3839
return {
3940
data: preparedResponse.groups || [],

src/containers/Storage/utils/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import type {
1010
import {EFlag} from '../../../types/api/enums';
1111
import {generateEvaluator} from '../../../utils/generateEvaluator';
1212
import {NODES_SORT_VALUES} from '../../../utils/nodes';
13-
import {STORAGE_SORT_VALUES} from '../../../utils/storage';
1413

1514
const defaultDegradationEvaluator = generateEvaluator(1, 2, ['success', 'warning', 'danger']);
1615

@@ -47,17 +46,17 @@ export const defaultSortNode: NodesSortParams = {
4746
};
4847

4948
const defaultSortGroup: StorageSortParams = {
50-
sortValue: STORAGE_SORT_VALUES.PoolName,
49+
sortValue: 'PoolName',
5150
sortOrder: ASCENDING,
5251
};
5352

5453
const defaultSortGroupMissing: StorageSortParams = {
55-
sortValue: STORAGE_SORT_VALUES.Degraded,
54+
sortValue: 'Degraded',
5655
sortOrder: DESCENDING,
5756
};
5857

5958
const defaultSortGroupSpace: StorageSortParams = {
60-
sortValue: STORAGE_SORT_VALUES.Usage,
59+
sortValue: 'Usage',
6160
sortOrder: DESCENDING,
6261
};
6362

src/services/api.ts

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import axiosRetry from 'axios-retry';
55

66
import {backend as BACKEND, metaBackend as META_BACKEND} from '../store';
77
import type {ComputeApiRequestParams, NodesApiRequestParams} from '../store/reducers/nodes/types';
8-
import type {StorageApiRequestParams} from '../store/reducers/storage/types';
98
import type {TMetaInfo} from '../types/api/acl';
109
import type {TQueryAutocomplete} from '../types/api/autocomplete';
1110
import type {CapabilitiesResponse} from '../types/api/capabilities';
@@ -37,7 +36,12 @@ import type {
3736
} from '../types/api/query';
3837
import type {JsonRenderRequestParams, JsonRenderResponse} from '../types/api/render';
3938
import type {TEvDescribeSchemeResult} from '../types/api/schema';
40-
import type {TStorageInfo} from '../types/api/storage';
39+
import type {
40+
GroupsRequestParams,
41+
StorageGroupsResponse,
42+
StorageRequestParams,
43+
TStorageInfo,
44+
} from '../types/api/storage';
4145
import type {TEvSystemStateResponse} from '../types/api/systemState';
4246
import type {
4347
TDomainKey,
@@ -135,6 +139,10 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
135139
getPath(path: string) {
136140
return `${BACKEND ?? ''}${path}`;
137141
}
142+
prepareArrayRequestParam(arr: (string | number)[]) {
143+
return arr.join(',');
144+
}
145+
138146
getClusterCapabilities() {
139147
return this.get<CapabilitiesResponse>(this.getPath('/viewer/capabilities'), {}, {});
140148
}
@@ -234,31 +242,49 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
234242
);
235243
}
236244
getStorageInfo(
237-
{
238-
tenant,
239-
database,
240-
visibleEntities,
241-
nodeId,
242-
poolName,
243-
groupId,
244-
sortOrder,
245-
sortValue,
246-
...params
247-
}: StorageApiRequestParams,
245+
{tenant, database, nodeId, groupId, pDiskId, ...params}: StorageRequestParams,
248246
{concurrentId, signal}: AxiosOptions = {},
249247
) {
250-
const sort = prepareSortValue(sortValue, sortOrder);
251-
252248
return this.get<TStorageInfo>(
253249
this.getPath(`/viewer/json/storage?enums=true`),
254250
{
255251
database: database || tenant,
256252
tenant: tenant || database,
257253
node_id: nodeId,
258-
pool: poolName,
259254
group_id: groupId,
260-
with: visibleEntities,
261-
sort,
255+
pdisk_id: pDiskId,
256+
...params,
257+
},
258+
{concurrentId, requestConfig: {signal}},
259+
);
260+
}
261+
getStorageGroups(
262+
{nodeId, pDiskId, groupId, fieldsRequired = 'all', ...params}: GroupsRequestParams,
263+
{concurrentId, signal}: AxiosOptions = {},
264+
) {
265+
const preparedNodeId = Array.isArray(nodeId)
266+
? this.prepareArrayRequestParam(nodeId)
267+
: nodeId;
268+
269+
const preparedPDiskId = Array.isArray(pDiskId)
270+
? this.prepareArrayRequestParam(pDiskId)
271+
: pDiskId;
272+
273+
const preparedGroupId = Array.isArray(groupId)
274+
? this.prepareArrayRequestParam(groupId)
275+
: groupId;
276+
277+
const preparedFieldsRequired = Array.isArray(fieldsRequired)
278+
? this.prepareArrayRequestParam(fieldsRequired)
279+
: fieldsRequired;
280+
281+
return this.get<StorageGroupsResponse>(
282+
this.getPath('/storage/groups'),
283+
{
284+
node_id: preparedNodeId,
285+
pdisk_id: preparedPDiskId,
286+
group_id: preparedGroupId,
287+
fields_required: preparedFieldsRequired,
262288
...params,
263289
},
264290
{concurrentId, requestConfig: {signal}},

src/store/reducers/nodes/nodes.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import {EVersion} from '../../../types/api/compute';
21
import {api} from '../api';
32

43
import type {ComputeApiRequestParams, NodesApiRequestParams} from './types';
@@ -30,7 +29,7 @@ export const nodesApi = api.injectEndpoints({
3029
try {
3130
const data = await window.api.getCompute(
3231
{
33-
version: EVersion.v2,
32+
version: 'v2',
3433
...params,
3534
},
3635
{signal},

src/store/reducers/pdisk/pdisk.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import {EVersion} from '../../../types/api/storage';
21
import {getPDiskId} from '../../../utils/disks/helpers';
32
import {api} from '../api';
43

@@ -36,7 +35,7 @@ export const pDiskApi = api.injectEndpoints({
3635
queryFn: async ({nodeId, pDiskId}: PDiskParams, {signal}) => {
3736
try {
3837
const response = await window.api.getStorageInfo(
39-
{nodeId, version: EVersion.v1},
38+
{nodeId, version: 'v1'},
4039
{signal},
4140
);
4241
const data = preparePDiskStorageResponse(response, pDiskId, nodeId);

src/store/reducers/storage/selectors.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const filterGroupsByText = (entities: PreparedStorageGroup[], text: string) => {
3232
return entities.filter((entity) => {
3333
return (
3434
entity.PoolName?.toLowerCase().includes(preparedSearch) ||
35-
entity.GroupID?.toString().includes(preparedSearch)
35+
entity.GroupId?.toString().includes(preparedSearch)
3636
);
3737
});
3838
};

src/store/reducers/storage/storage.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import {EVersion} from '../../../types/api/storage';
1+
import type {StorageRequestParams} from '../../../types/api/storage';
22
import {api} from '../api';
33
import type {NodesApiRequestParams} from '../nodes/types';
44

5-
import type {StorageApiRequestParams} from './types';
6-
import {prepareStorageGroupsResponse, prepareStorageNodesResponse} from './utils';
5+
import {prepareStorageNodesResponse, prepareStorageResponse} from './utils';
76

87
export const storageApi = api.injectEndpoints({
98
endpoints: (builder) => ({
@@ -22,13 +21,13 @@ export const storageApi = api.injectEndpoints({
2221
providesTags: ['All'],
2322
}),
2423
getStorageGroupsInfo: builder.query({
25-
queryFn: async (params: StorageApiRequestParams, {signal}) => {
24+
queryFn: async (params: StorageRequestParams, {signal}) => {
2625
try {
2726
const result = await window.api.getStorageInfo(
28-
{version: EVersion.v1, ...params},
27+
{version: 'v1', ...params},
2928
{signal},
3029
);
31-
return {data: prepareStorageGroupsResponse(result)};
30+
return {data: prepareStorageResponse(result)};
3231
} catch (error) {
3332
return {error};
3433
}

0 commit comments

Comments
 (0)