diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/repository_add.helpers.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/repository_add.helpers.ts index e53c19f00d1b9..b369b20c122eb 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/repository_add.helpers.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/repository_add.helpers.ts @@ -71,6 +71,13 @@ type TestSubjects = | 'compressToggle' | 'fsRepositoryType' | 'locationInput' + | 'clientInput' + | 'containerInput' + | 'basePathInput' + | 'bucketInput' + | 'pathInput' + | 'uriInput' + | 'bufferSizeInput' | 'maxRestoreBytesInput' | 'maxSnapshotBytesInput' | 'nameInput' diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/repository_add.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/repository_add.test.ts index 9864b18c4b8cb..85d438fc5f3ae 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/repository_add.test.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/repository_add.test.ts @@ -193,7 +193,14 @@ describe('', () => { }); describe('form payload & api errors', () => { - const repository = getRepository(); + const fsRepository = getRepository({ + settings: { + chunkSize: '10mb', + location: '/tmp/es-backups', + maxSnapshotBytesPerSec: '1g', + maxRestoreBytesPerSec: '1g', + }, + }); beforeEach(async () => { httpRequestsMockHelpers.setLoadRepositoryTypesResponse(repositoryTypes); @@ -202,33 +209,237 @@ describe('', () => { }); describe('not source only', () => { - beforeEach(() => { + test('should send the correct payload for FS repository', async () => { + const { form, actions, component } = testBed; + // Fill step 1 required fields and go to step 2 - testBed.form.setInputValue('nameInput', repository.name); - testBed.actions.selectRepositoryType(repository.type); - testBed.actions.clickNextButton(); + form.setInputValue('nameInput', fsRepository.name); + actions.selectRepositoryType(fsRepository.type); + actions.clickNextButton(); + + // Fill step 2 + form.setInputValue('locationInput', fsRepository.settings.location); + form.toggleEuiSwitch('compressToggle'); + form.setInputValue('chunkSizeInput', fsRepository.settings.chunkSize); + form.setInputValue('maxSnapshotBytesInput', fsRepository.settings.maxSnapshotBytesPerSec); + form.setInputValue('maxRestoreBytesInput', fsRepository.settings.maxRestoreBytesPerSec); + form.toggleEuiSwitch('readOnlyToggle'); + + await act(async () => { + actions.clickSubmitButton(); + }); + + component.update(); + + const latestRequest = server.requests[server.requests.length - 1]; + + expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual({ + name: fsRepository.name, + type: fsRepository.type, + settings: { + ...fsRepository.settings, + compress: true, + readonly: true, + }, + }); }); - test('should send the correct payload', async () => { - const { form, actions } = testBed; + test('should send the correct payload for Azure repository', async () => { + const azureRepository = getRepository({ + type: 'azure', + settings: { + chunkSize: '10mb', + maxSnapshotBytesPerSec: '1g', + maxRestoreBytesPerSec: '1g', + client: 'client', + container: 'container', + basePath: 'path', + }, + }); + + const { form, actions, component } = testBed; + + // Fill step 1 required fields and go to step 2 + form.setInputValue('nameInput', azureRepository.name); + actions.selectRepositoryType(azureRepository.type); + actions.clickNextButton(); // Fill step 2 - form.setInputValue('locationInput', repository.settings.location); + form.setInputValue('clientInput', azureRepository.settings.client); + form.setInputValue('containerInput', azureRepository.settings.container); + form.setInputValue('basePathInput', azureRepository.settings.basePath); form.toggleEuiSwitch('compressToggle'); + form.setInputValue('chunkSizeInput', azureRepository.settings.chunkSize); + form.setInputValue( + 'maxSnapshotBytesInput', + azureRepository.settings.maxSnapshotBytesPerSec + ); + form.setInputValue('maxRestoreBytesInput', azureRepository.settings.maxRestoreBytesPerSec); + form.toggleEuiSwitch('readOnlyToggle'); await act(async () => { actions.clickSubmitButton(); - await nextTick(); }); + component.update(); + const latestRequest = server.requests[server.requests.length - 1]; expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual({ - name: repository.name, - type: repository.type, + name: azureRepository.name, + type: azureRepository.type, settings: { - location: repository.settings.location, - compress: true, + ...azureRepository.settings, + compress: false, + readonly: true, + }, + }); + }); + + test('should send the correct payload for GCS repository', async () => { + const gcsRepository = getRepository({ + type: 'gcs', + settings: { + chunkSize: '10mb', + maxSnapshotBytesPerSec: '1g', + maxRestoreBytesPerSec: '1g', + client: 'test_client', + bucket: 'test_bucket', + basePath: 'test_path', + }, + }); + + const { form, actions, component } = testBed; + + // Fill step 1 required fields and go to step 2 + form.setInputValue('nameInput', gcsRepository.name); + actions.selectRepositoryType(gcsRepository.type); + actions.clickNextButton(); + + // Fill step 2 + form.setInputValue('clientInput', gcsRepository.settings.client); + form.setInputValue('bucketInput', gcsRepository.settings.bucket); + form.setInputValue('basePathInput', gcsRepository.settings.basePath); + form.toggleEuiSwitch('compressToggle'); + form.setInputValue('chunkSizeInput', gcsRepository.settings.chunkSize); + form.setInputValue('maxSnapshotBytesInput', gcsRepository.settings.maxSnapshotBytesPerSec); + form.setInputValue('maxRestoreBytesInput', gcsRepository.settings.maxRestoreBytesPerSec); + form.toggleEuiSwitch('readOnlyToggle'); + + await act(async () => { + actions.clickSubmitButton(); + }); + + component.update(); + + const latestRequest = server.requests[server.requests.length - 1]; + + expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual({ + name: gcsRepository.name, + type: gcsRepository.type, + settings: { + ...gcsRepository.settings, + compress: false, + readonly: true, + }, + }); + }); + + test('should send the correct payload for HDFS repository', async () => { + const hdfsRepository = getRepository({ + type: 'hdfs', + settings: { + uri: 'uri', + path: 'test_path', + chunkSize: '10mb', + maxSnapshotBytesPerSec: '1g', + maxRestoreBytesPerSec: '1g', + }, + }); + + const { form, actions, component } = testBed; + + // Fill step 1 required fields and go to step 2 + form.setInputValue('nameInput', hdfsRepository.name); + actions.selectRepositoryType(hdfsRepository.type); + actions.clickNextButton(); + + // Fill step 2 + form.setInputValue('uriInput', hdfsRepository.settings.uri); + form.setInputValue('pathInput', hdfsRepository.settings.path); + form.toggleEuiSwitch('compressToggle'); + form.setInputValue('chunkSizeInput', hdfsRepository.settings.chunkSize); + form.setInputValue('maxSnapshotBytesInput', hdfsRepository.settings.maxSnapshotBytesPerSec); + form.setInputValue('maxRestoreBytesInput', hdfsRepository.settings.maxRestoreBytesPerSec); + form.toggleEuiSwitch('readOnlyToggle'); + + await act(async () => { + actions.clickSubmitButton(); + }); + + component.update(); + + const latestRequest = server.requests[server.requests.length - 1]; + + expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual({ + name: hdfsRepository.name, + type: hdfsRepository.type, + settings: { + ...hdfsRepository.settings, + uri: `hdfs://${hdfsRepository.settings.uri}`, + compress: false, + readonly: true, + }, + }); + }); + + test('should send the correct payload for S3 repository', async () => { + const { form, actions, component } = testBed; + + const s3Repository = getRepository({ + type: 's3', + settings: { + bucket: 'test_bucket', + client: 'test_client', + basePath: 'test_path', + bufferSize: '1g', + chunkSize: '10mb', + maxSnapshotBytesPerSec: '1g', + maxRestoreBytesPerSec: '1g', + }, + }); + + // Fill step 1 required fields and go to step 2 + form.setInputValue('nameInput', s3Repository.name); + actions.selectRepositoryType(s3Repository.type); + actions.clickNextButton(); + + // Fill step 2 + form.setInputValue('bucketInput', s3Repository.settings.bucket); + form.setInputValue('clientInput', s3Repository.settings.client); + form.setInputValue('basePathInput', s3Repository.settings.basePath); + form.setInputValue('bufferSizeInput', s3Repository.settings.bufferSize); + form.toggleEuiSwitch('compressToggle'); + form.setInputValue('chunkSizeInput', s3Repository.settings.chunkSize); + form.setInputValue('maxSnapshotBytesInput', s3Repository.settings.maxSnapshotBytesPerSec); + form.setInputValue('maxRestoreBytesInput', s3Repository.settings.maxRestoreBytesPerSec); + form.toggleEuiSwitch('readOnlyToggle'); + + await act(async () => { + actions.clickSubmitButton(); + }); + + component.update(); + + const latestRequest = server.requests[server.requests.length - 1]; + + expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual({ + name: s3Repository.name, + type: s3Repository.type, + settings: { + ...s3Repository.settings, + compress: false, + readonly: true, }, }); }); @@ -236,7 +447,13 @@ describe('', () => { test('should surface the API errors from the "save" HTTP request', async () => { const { component, form, actions, find, exists } = testBed; - form.setInputValue('locationInput', repository.settings.location); + // Fill step 1 required fields and go to step 2 + form.setInputValue('nameInput', fsRepository.name); + actions.selectRepositoryType(fsRepository.type); + actions.clickNextButton(); + + // Fill step 2 + form.setInputValue('locationInput', fsRepository.settings.location); form.toggleEuiSwitch('compressToggle'); const error = { @@ -249,10 +466,10 @@ describe('', () => { await act(async () => { actions.clickSubmitButton(); - await nextTick(); - component.update(); }); + component.update(); + expect(exists('saveRepositoryApiError')).toBe(true); expect(find('saveRepositoryApiError').text()).toContain(error.message); }); @@ -261,31 +478,32 @@ describe('', () => { describe('source only', () => { beforeEach(() => { // Fill step 1 required fields and go to step 2 - testBed.form.setInputValue('nameInput', repository.name); - testBed.actions.selectRepositoryType(repository.type); + testBed.form.setInputValue('nameInput', fsRepository.name); + testBed.actions.selectRepositoryType(fsRepository.type); testBed.form.toggleEuiSwitch('sourceOnlyToggle'); // toggle source testBed.actions.clickNextButton(); }); test('should send the correct payload', async () => { - const { form, actions } = testBed; + const { form, actions, component } = testBed; // Fill step 2 - form.setInputValue('locationInput', repository.settings.location); + form.setInputValue('locationInput', fsRepository.settings.location); await act(async () => { actions.clickSubmitButton(); - await nextTick(); }); + component.update(); + const latestRequest = server.requests[server.requests.length - 1]; expect(JSON.parse(JSON.parse(latestRequest.requestBody).body)).toEqual({ - name: repository.name, + name: fsRepository.name, type: 'source', settings: { - delegateType: repository.type, - location: repository.settings.location, + delegateType: fsRepository.type, + location: fsRepository.settings.location, }, }); }); diff --git a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/azure_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/azure_settings.tsx index adbbe81176bde..b2657d0bfc0fb 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/azure_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/azure_settings.tsx @@ -17,7 +17,7 @@ import { } from '@elastic/eui'; import { AzureRepository, Repository } from '../../../../../common/types'; import { RepositorySettingsValidation } from '../../../services/validation'; -import { textService } from '../../../services/text'; +import { ChunkSizeField, MaxSnapshotsField, MaxRestoreField } from './common'; interface Props { repository: AzureRepository; @@ -53,6 +53,12 @@ export const AzureSettings: React.FunctionComponent = ({ text: option, })); + const updateSettings = (name: string, value: string) => { + updateRepositorySettings({ + [name]: value, + }); + }; + return ( {/* Client field */} @@ -232,139 +238,28 @@ export const AzureSettings: React.FunctionComponent = ({ {/* Chunk size field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} - error={settingErrors.chunkSize} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - chunkSize: e.target.value, - }); - }} - data-test-subj="chunkSizeInput" - /> - -
+ {/* Max snapshot bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} - error={settingErrors.maxSnapshotBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxSnapshotBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxSnapshotBytesInput" - /> - -
+ {/* Max restore bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} - error={settingErrors.maxRestoreBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxRestoreBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxRestoreBytesInput" - /> - -
+ {/* Location mode field */} void; + error: RepositorySettingsValidation['chunkSize']; +} + +export const ChunkSizeField: React.FunctionComponent = ({ + isInvalid, + error, + defaultValue, + updateSettings, +}) => { + return ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + } + fullWidth + isInvalid={isInvalid} + error={error} + helpText={ + 1g, + example2: 10mb, + example3: 5k, + example4: 1024B, + }} + /> + } + > + updateSettings('chunkSize', e.target.value)} + data-test-subj="chunkSizeInput" + /> + +
+ ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/index.ts new file mode 100644 index 0000000000000..173e13b1b6e17 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { ChunkSizeField } from './chunk_size'; +export { MaxRestoreField } from './max_restore'; +export { MaxSnapshotsField } from './max_snapshots'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/max_restore.tsx b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/max_restore.tsx new file mode 100644 index 0000000000000..281fe26d5b9d3 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/max_restore.tsx @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiDescribedFormGroup, EuiFieldText, EuiFormRow, EuiTitle, EuiCode } from '@elastic/eui'; +import { RepositorySettingsValidation } from '../../../../services/validation'; + +interface Props { + isInvalid: boolean; + defaultValue: string; + updateSettings: (name: string, value: string) => void; + error: RepositorySettingsValidation['maxRestoreBytesPerSec']; +} + +export const MaxRestoreField: React.FunctionComponent = ({ + isInvalid, + error, + defaultValue, + updateSettings, +}) => { + return ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + } + fullWidth + isInvalid={isInvalid} + error={error} + helpText={ + 1g, + example2: 10mb, + example3: 5k, + example4: 1024B, + }} + /> + } + > + updateSettings('maxRestoreBytesPerSec', e.target.value)} + data-test-subj="maxRestoreBytesInput" + /> + +
+ ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/max_snapshots.tsx b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/max_snapshots.tsx new file mode 100644 index 0000000000000..85b9153c711b9 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/common/max_snapshots.tsx @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiDescribedFormGroup, EuiFieldText, EuiFormRow, EuiTitle, EuiCode } from '@elastic/eui'; +import { RepositorySettingsValidation } from '../../../../services/validation'; + +interface Props { + isInvalid: boolean; + defaultValue: string; + updateSettings: (name: string, value: string) => void; + error: RepositorySettingsValidation['maxSnapshotBytesPerSec']; +} + +export const MaxSnapshotsField: React.FunctionComponent = ({ + isInvalid, + error, + defaultValue, + updateSettings, +}) => { + return ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + } + fullWidth + isInvalid={isInvalid} + error={error} + helpText={ + 1g, + example2: 10mb, + example3: 5k, + example4: 1024B, + defaultSize: 40mb, + }} + /> + } + > + updateSettings('maxSnapshotBytesPerSec', e.target.value)} + data-test-subj="maxSnapshotBytesInput" + /> + +
+ ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/fs_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/fs_settings.tsx index 2635cabfa1ef6..af3e6e8231262 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/fs_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/repository_form/type_settings/fs_settings.tsx @@ -17,7 +17,7 @@ import { } from '@elastic/eui'; import { FSRepository, Repository } from '../../../../../common/types'; import { RepositorySettingsValidation } from '../../../services/validation'; -import { textService } from '../../../services/text'; +import { ChunkSizeField, MaxRestoreField, MaxSnapshotsField } from './common'; interface Props { repository: FSRepository; @@ -44,6 +44,11 @@ export const FSSettings: React.FunctionComponent = ({ }, } = repository; const hasErrors: boolean = Boolean(Object.keys(settingErrors).length); + const updateSettings = (name: string, value: string) => { + updateRepositorySettings({ + [name]: value, + }); + }; return ( @@ -141,139 +146,28 @@ export const FSSettings: React.FunctionComponent = ({
{/* Chunk size field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} - error={settingErrors.chunkSize} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - chunkSize: e.target.value, - }); - }} - data-test-subj="chunkSizeInput" - /> - -
+ {/* Max snapshot bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} - error={settingErrors.maxSnapshotBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxSnapshotBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxSnapshotBytesInput" - /> - -
+ {/* Max restore bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} - error={settingErrors.maxRestoreBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxRestoreBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxRestoreBytesInput" - /> - -
+ {/* Readonly field */} = ({ } = repository; const hasErrors: boolean = Boolean(Object.keys(settingErrors).length); + const updateSettings = (name: string, value: string) => { + updateRepositorySettings({ + [name]: value, + }); + }; + return ( {/* Client field */} @@ -220,139 +226,28 @@ export const GCSSettings: React.FunctionComponent = ({ {/* Chunk size field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} - error={settingErrors.chunkSize} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - chunkSize: e.target.value, - }); - }} - data-test-subj="chunkSizeInput" - /> - -
+ {/* Max snapshot bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} - error={settingErrors.maxSnapshotBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxSnapshotBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxSnapshotBytesInput" - /> - -
+ {/* Max restore bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} - error={settingErrors.maxRestoreBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxRestoreBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxRestoreBytesInput" - /> - -
+ {/* Readonly field */} ; @@ -54,6 +54,11 @@ export const HDFSSettings: React.FunctionComponent = ({ }, } = repository; const hasErrors: boolean = Boolean(Object.keys(settingErrors).length); + const updateSettings = (settingName: string, value: string) => { + updateRepositorySettings({ + [settingName]: value, + }); + }; const [additionalConf, setAdditionalConf] = useState(JSON.stringify(rest, null, 2)); const [isConfInvalid, setIsConfInvalid] = useState(false); @@ -244,49 +249,12 @@ export const HDFSSettings: React.FunctionComponent = ({ {/* Chunk size field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} - error={settingErrors.chunkSize} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - chunkSize: e.target.value, - }); - }} - data-test-subj="chunkSizeInput" - /> - -
+ {/* Security principal field */} = ({ {/* Max snapshot bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} - error={settingErrors.maxSnapshotBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxSnapshotBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxSnapshotBytesInput" - /> - -
+ {/* Max restore bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} - error={settingErrors.maxRestoreBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxRestoreBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxRestoreBytesInput" - /> - -
+ {/* Readonly field */} = ({ text: option, })); const hasErrors: boolean = Boolean(Object.keys(settingErrors).length); + const updateSettings = (name: string, value: string) => { + updateRepositorySettings({ + [name]: value, + }); + }; const storageClassOptions = ['standard', 'reduced_redundancy', 'standard_ia'].map((option) => ({ value: option, @@ -249,49 +255,12 @@ export const S3Settings: React.FunctionComponent = ({ {/* Chunk size field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.chunkSize)} - error={settingErrors.chunkSize} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - chunkSize: e.target.value, - }); - }} - data-test-subj="chunkSizeInput" - /> - -
+ {/* Server side encryption field */} = ({ fullWidth isInvalid={Boolean(hasErrors && settingErrors.bufferSize)} error={settingErrors.bufferSize} - helpText={textService.getSizeNotationHelpText()} + helpText={ + 1g, + example2: 10mb, + example3: 5k, + example4: 1024B, + defaultSize: 100mb, + defaultPercentage: 5%, + }} + /> + } > = ({ {/* Max snapshot bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxSnapshotBytesPerSec)} - error={settingErrors.maxSnapshotBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxSnapshotBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxSnapshotBytesInput" - /> - -
+ {/* Max restore bytes field */} - -

- -

- - } - description={ - - } - fullWidth - > - - } - fullWidth - isInvalid={Boolean(hasErrors && settingErrors.maxRestoreBytesPerSec)} - error={settingErrors.maxRestoreBytesPerSec} - helpText={textService.getSizeNotationHelpText()} - > - { - updateRepositorySettings({ - maxRestoreBytesPerSec: e.target.value, - }); - }} - data-test-subj="maxRestoreBytesInput" - /> - -
+ {/* Readonly field */}