Skip to content
Open
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
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,9 +4,9 @@ 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 { Backup, BackupResponse, CompressionResponse, Timeranges, TimerangesResponse } from './BackupInventory.types';
import { formatDate } from './BackupInventory.utils';

const BASE_URL = '/v1/backups';
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<CompressionResponse, void>(
`${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 All @@ -55,3 +57,7 @@ export interface Timeranges {
export interface TimerangesResponse {
timeranges: RawTimeranges[];
}

export interface CompressionResponse {
compression_methods: Compression[];
}
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();
});
});
Loading