Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
20 changes: 15 additions & 5 deletions public/app/percona/backup/Backup.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { api } from 'app/percona/shared/helpers/api';

import { getCronStringFromValues } from '../shared/helpers/cron/cron';

import { BackupMode, BackupType, DataModel, RetryMode } from './Backup.types';
import { BackupMode, BackupType, Compression, DataModel, RetryMode } from './Backup.types';
import { AddBackupFormProps } from './components/AddBackupPage/AddBackupPage.types';

const BASE_URL = '/v1/backups';
Expand Down Expand Up @@ -32,6 +32,7 @@ export const BackupService = {
type,
dataModel,
folder,
compression,
} = values;
const strRetryInterval = `${retryInterval}s`;
const resultRetryTimes = retryMode === RetryMode.MANUAL ? 0 : retryTimes;
Expand All @@ -46,6 +47,7 @@ export const BackupService = {
resultRetryTimes!,
dataModel,
folder,
compression.value!,
token
);
} else {
Expand All @@ -66,7 +68,8 @@ export const BackupService = {
description ?? '',
strRetryInterval,
resultRetryTimes!,
retention!
retention!,
compression.value!
);
} else {
return this.scheduleBackup(
Expand All @@ -81,7 +84,8 @@ export const BackupService = {
active!,
mode,
dataModel,
folder
folder,
compression.value!
);
}
}
Expand All @@ -95,6 +99,7 @@ export const BackupService = {
retryTimes: number,
dataModel: DataModel,
folder: string,
compression: Compression,
token?: CancelToken
) {
return api.post(
Expand All @@ -108,6 +113,7 @@ export const BackupService = {
retries: retryTimes,
data_model: dataModel,
folder,
compression,
},
false,
token
Expand All @@ -125,7 +131,8 @@ export const BackupService = {
enabled: boolean,
mode: BackupMode,
dataModel: DataModel,
folder: string
folder: string,
compression: Compression
) {
return api.post(`${BASE_URL}:schedule`, {
service_id: serviceId,
Expand All @@ -140,6 +147,7 @@ export const BackupService = {
mode,
data_model: dataModel,
folder,
compression,
});
},
async changeScheduleBackup(
Expand All @@ -150,7 +158,8 @@ export const BackupService = {
description: string,
retryInterval: string,
retryTimes: number,
retention: number
retention: number,
compression: Compression
) {
return api.put(`${BASE_URL}:changeScheduled`, {
scheduled_backup_id: id,
Expand All @@ -161,6 +170,7 @@ export const BackupService = {
retry_interval: retryInterval,
retries: retryTimes,
retention,
compression,
});
},
};
12 changes: 12 additions & 0 deletions public/app/percona/backup/Backup.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ export enum BackupType {
SCHEDULED = 'SCHEDULED',
}

export enum Compression {
DEFAULT = 'BACKUP_COMPRESSION_DEFAULT',
NONE = 'BACKUP_COMPRESSION_NONE',
QUICKLZ = 'BACKUP_COMPRESSION_QUICKLZ',
ZSTD = 'BACKUP_COMPRESSION_ZSTD',
LZ4 = 'BACKUP_COMPRESSION_LZ4',
S2 = 'BACKUP_COMPRESSION_S2',
GZIP = 'BACKUP_COMPRESSION_GZIP',
SNAPPY = 'BACKUP_COMPRESSION_SNAPPY',
PGZIP = 'BACKUP_COMPRESSION_PGZIP',
}

export interface RawBackupLog {
chunk_id: number;
data: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,4 @@ export const MIN_RETENTION = 0;
export const MAX_RETENTION = 99;

export const MAX_BACKUP_NAME = 100;

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export const Messages = {
folder: 'Folder',
location: 'Location',
retryMode: 'Retry mode',
compression: 'Compression',
compressionTooltip:
'Choose the compression algorithm for the backup. Different algorithms offer different trade-offs between compression ratio and speed.',
selectCompression: 'Select compression type',
cancelAction: 'Cancel',
retryTimes: 'Retry, times',
retryInterval: 'Retry interval, seconds',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { FC, PropsWithChildren } from 'react';
import { act, FC, PropsWithChildren } from 'react';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom-v5-compat';

Expand Down Expand Up @@ -154,4 +154,26 @@ describe('AddBackupPage', () => {
await fireEvent.click(button);
expect(screen.getByText('Create Backup on demand')).toBeInTheDocument();
});

it('should render compression field in advanced settings', async () => {
render(
<AddBackupPageWrapper>
<MemoryRouter>
<AddBackupPage />
</MemoryRouter>
</AddBackupPageWrapper>
);

await waitFor(() => expect(screen.getAllByText('Choose')).toHaveLength(2));

const advancedSettingsButton = screen.getByTestId('add-backup-advanced-settings');
act(() => {
fireEvent.click(advancedSettingsButton);
});

await waitFor(() => {
expect(screen.getByTestId('compression-select-input')).toBeInTheDocument();
expect(screen.getByText(Messages.compression)).toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { PageSwitcherCard } from '../../../shared/components/Elements/PageSwitch
import { BACKUP_INVENTORY_URL, BACKUP_SCHEDULED_URL } from '../../Backup.constants';
import { Messages as MessagesBackup } from '../../Backup.messages';
import { BackupService } from '../../Backup.service';
import { BackupMode, BackupType, DataModel } from '../../Backup.types';
import { BackupMode, BackupType, Compression, DataModel } from '../../Backup.types';
import { BackupErrorSection } from '../BackupErrorSection/BackupErrorSection';
import { BACKUP_CANCEL_TOKEN, LIST_ARTIFACTS_CANCEL_TOKEN } from '../BackupInventory/BackupInventory.constants';
import { BackupInventoryService } from '../BackupInventory/BackupInventory.service';
Expand All @@ -49,6 +49,7 @@ import { getStyles } from './AddBackupPage.styles';
import { AddBackupFormProps, SelectableService } from './AddBackupPage.types';
import {
getBackupModeOptions,
getCompressionOptionFromValue,
getDataModelFromVendor,
getLabelForStorageOption,
isDataModelDisabled,
Expand Down Expand Up @@ -113,6 +114,14 @@ const AddBackupPage: FC = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const loadCompressionOptions = useCallback(async (serviceId?: string) => {
if (!serviceId) {
return [getCompressionOptionFromValue(Compression.DEFAULT)];
}
const methods = await BackupInventoryService.listServiceCompressions(serviceId);
return methods.map((m) => getCompressionOptionFromValue(m));
}, []);

const handleBackup = async (values: AddBackupFormProps) => {
try {
await BackupService.backup(values, generateToken(BACKUP_CANCEL_TOKEN));
Expand Down Expand Up @@ -356,6 +365,23 @@ const AddBackupPage: FC = () => {
buttonDataTestId="add-backup-advanced-settings"
>
<RetryModeSelector retryMode={values.retryMode} />
<span className={cx(styles.wideField, styles.SelectFieldWrap)}>
<Field name="compression">
{({ input }) => (
<AsyncSelectField
label={Messages.compression}
key={values.service?.value?.id || 'no-service'}
defaultOptions
cacheOptions
isSearchable={false}
loadOptions={() => loadCompressionOptions(values.service?.value?.id)}
className={styles.selectField}
data-testid="compression-select-input"
{...input}
/>
)}
</Field>
</span>
<TextInputField
fieldClassName={styles.textAreaField}
name="folder"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SelectableValue } from '@grafana/data';
import { BackupMode, BackupType, DataModel, RetryMode } from 'app/percona/backup/Backup.types';
import { BackupMode, BackupType, Compression, DataModel, RetryMode } from 'app/percona/backup/Backup.types';
import { ApiVerboseError, Databases } from 'app/percona/shared/core';

import { Backup } from '../BackupInventory/BackupInventory.types';
Expand Down Expand Up @@ -39,4 +39,5 @@ export interface AddBackupFormProps extends ScheduledSectionFieldsValuesProps {
mode: BackupMode;
type: BackupType;
folder: string;
compression: SelectableValue<Compression>;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/consistent-type-assertions */
import { SelectableValue } from '@grafana/data';
import { BackupMode, BackupType, DataModel, RetryMode } from 'app/percona/backup/Backup.types';
import { BackupMode, BackupType, DataModel, RetryMode, Compression } from 'app/percona/backup/Backup.types';
import { Databases } from 'app/percona/shared/core';
import { getPeriodFromCronparts, parseCronString } from 'app/percona/shared/helpers/cron/cron';
import { PeriodType } from 'app/percona/shared/helpers/cron/types';
Expand Down Expand Up @@ -54,6 +54,16 @@ const getBackupType = (backup: Backup | ScheduledBackup | null): BackupType => {
return BackupType.DEMAND;
};

const compressionValueToKeyMap: Record<string, string> = Object.fromEntries(
Object.entries(Compression).map(([key, val]) => [val, key])
);

export const getCompressionOptionFromValue = (value: Compression): SelectableValue<Compression> => ({
value,
label: compressionValueToKeyMap[value] ?? value,
});


export const toFormBackup = (backup: Backup | ScheduledBackup | null, scheduleMode?: boolean): AddBackupFormProps => {
if (!backup) {
return {
Expand All @@ -79,6 +89,7 @@ export const toFormBackup = (backup: Backup | ScheduledBackup | null, scheduleMo
mode: BackupMode.SNAPSHOT,
type: scheduleMode ? BackupType.SCHEDULED : getBackupType(backup),
folder: '',
compression: getCompressionOptionFromValue(Compression.DEFAULT),
};
}

Expand Down Expand Up @@ -130,6 +141,7 @@ export const toFormBackup = (backup: Backup | ScheduledBackup | null, scheduleMo
mode,
type: BackupType.SCHEDULED,
folder,
compression: getCompressionOptionFromValue(backup.compression),
};
} else {
return {
Expand All @@ -146,6 +158,7 @@ export const toFormBackup = (backup: Backup | ScheduledBackup | null, scheduleMo
retryInterval: 30,
type: BackupType.DEMAND,
folder,
compression: getCompressionOptionFromValue(backup.compression),
};
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SelectableValue } from '@grafana/data';
import { DBServiceList, CompatibleServiceListPayload } from 'app/percona/inventory/Inventory.types';
import { api } from 'app/percona/shared/helpers/api';

import { BackupLogResponse, BackupLogs, DataModel } from '../../Backup.types';
import { BackupLogResponse, BackupLogs, Compression, DataModel } from '../../Backup.types';

import { Backup, BackupResponse, Timeranges, TimerangesResponse } from './BackupInventory.types';
import { formatDate } from './BackupInventory.utils';
Expand All @@ -28,6 +28,7 @@ export const BackupInventoryService = {
vendor,
mode,
folder,
compression,
}): Backup => ({
id: artifact_id,
name,
Expand All @@ -41,6 +42,7 @@ export const BackupInventoryService = {
vendor,
mode,
folder,
compression,
})
);
},
Expand Down Expand Up @@ -122,4 +124,10 @@ export const BackupInventoryService = {

return result;
},
async listServiceCompressions(serviceId: string): Promise<Compression[]> {
const { compression_methods = [] } = await api.get<{ compression_methods?: Compression[] }, void>(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you create a response type at BackupInventory.types.ts (something along the lines of ListCompressionsResponse)

Copy link
Author

Choose a reason for hiding this comment

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

@matejkubinec updated with the type as requested

`${BASE_URL}/services/${serviceId}/compression`
);
return compression_methods;
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ export const BackupInventory: FC = () => {
status={row.original.status}
dataModel={row.original.dataModel}
folder={row.original.folder}
compression={row.original.compression}
/>
),
[]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Databases } from 'app/percona/shared/core';

import { DataModel, BackupStatus, BackupMode } from '../../Backup.types';
import { DataModel, BackupStatus, BackupMode, Compression } from '../../Backup.types';
import { StorageLocation } from '../StorageLocations/StorageLocations.types';

export interface Backup {
Expand All @@ -17,6 +17,7 @@ export interface Backup {
mode: BackupMode;
folder: string;
type?: Databases | 'external';
compression: Compression;
}

export interface BackupRow extends Backup {
Expand All @@ -36,6 +37,7 @@ export interface RawBackup {
vendor: Databases;
mode: BackupMode;
folder: string;
compression: Compression;
}

export interface BackupResponse {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export const Messages = {
testResuts: 'Test results',
dataModel: 'Data model',
folder: 'Folder',
compression: 'Compression',
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { render, screen } from '@testing-library/react';

import { DataModel, BackupStatus } from 'app/percona/backup/Backup.types';
import { Compression, DataModel, BackupStatus } from 'app/percona/backup/Backup.types';

import { BackupInventoryDetails } from './BackupInventoryDetails';

Expand All @@ -12,10 +12,12 @@ describe('BackupInventoryDetails', () => {
status={BackupStatus.BACKUP_STATUS_PAUSED}
dataModel={DataModel.LOGICAL}
folder="folder1"
compression={Compression.NONE}
/>
);
expect(screen.getByTestId('backup-artifact-details-name')).toBeInTheDocument();
expect(screen.getByTestId('backup-artifact-details-data-model')).toBeInTheDocument();
expect(screen.getByTestId('backup-artifact-details-folder')).toBeInTheDocument();
expect(screen.getByTestId('backup-artifact-details-compression')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Messages } from './BackupInventoryDetails.messages';
import { getStyles } from './BackupInventoryDetails.styles';
import { BackupInventoryDetailsProps } from './BackupInventoryDetails.types';

export const BackupInventoryDetails: FC<BackupInventoryDetailsProps> = ({ name, folder, dataModel }) => {
export const BackupInventoryDetails: FC<BackupInventoryDetailsProps> = ({ name, folder, dataModel, compression }) => {
const styles = useStyles(getStyles);
const dataModelMsg = formatDataModel(dataModel);

Expand All @@ -24,6 +24,11 @@ export const BackupInventoryDetails: FC<BackupInventoryDetailsProps> = ({ name,
<span className={styles.detailLabel}>{Messages.folder}</span> <span>{folder}</span>
</span>
)}
{compression && (
<span data-testid="backup-artifact-details-compression">
<span className={styles.detailLabel}>{Messages.compression}</span> <span>{compression}</span>
</span>
)}
</div>
);
};
Loading
Loading