mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
Removes support for legacy exports (#110738)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
ed18699e38
commit
66cb058fa7
21 changed files with 32 additions and 1530 deletions
|
@ -238,7 +238,6 @@ exports[`Flyout conflicts should allow conflict resolution 2`] = `
|
|||
"title": undefined,
|
||||
},
|
||||
],
|
||||
"isLegacyFile": false,
|
||||
"loadingMessage": undefined,
|
||||
"status": "loading",
|
||||
"successfulImports": Array [],
|
||||
|
@ -276,278 +275,6 @@ exports[`Flyout conflicts should allow conflict resolution 2`] = `
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`Flyout legacy conflicts should allow conflict resolution 1`] = `
|
||||
<EuiFlyout
|
||||
data-test-subj="importSavedObjectsFlyout"
|
||||
onClose={[MockFunction]}
|
||||
size="s"
|
||||
>
|
||||
<EuiFlyoutHeader
|
||||
hasBorder={true}
|
||||
>
|
||||
<EuiTitle
|
||||
size="m"
|
||||
>
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
defaultMessage="Import saved objects"
|
||||
id="savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
<span>
|
||||
<EuiSpacer
|
||||
size="s"
|
||||
/>
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
data-test-subj="importSavedObjectsLegacyWarning"
|
||||
iconType="help"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Support for JSON files is going away"
|
||||
id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Use our updated export to generate NDJSON files, and you'll be all set."
|
||||
id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer
|
||||
size="m"
|
||||
/>
|
||||
</span>
|
||||
<span>
|
||||
<EuiSpacer
|
||||
size="s"
|
||||
/>
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
data-test-subj="importSavedObjectsConflictsWarning"
|
||||
iconType="help"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Index Pattern Conflicts"
|
||||
id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="The following saved objects use index patterns that do not exist. Please select the index patterns you'd like re-associated with them. You can {indexPatternLink} if necessary."
|
||||
id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription"
|
||||
values={
|
||||
Object {
|
||||
"indexPatternLink": <EuiLink
|
||||
href=""
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="create a new index pattern"
|
||||
id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiLink>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
</span>
|
||||
<EuiInMemoryTable
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
"description": "ID of the index pattern",
|
||||
"field": "existingIndexPatternId",
|
||||
"name": "ID",
|
||||
"sortable": true,
|
||||
},
|
||||
Object {
|
||||
"description": "How many affected objects",
|
||||
"field": "list",
|
||||
"name": "Count",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"description": "Sample of affected objects",
|
||||
"field": "list",
|
||||
"name": "Sample of affected objects",
|
||||
"render": [Function],
|
||||
},
|
||||
Object {
|
||||
"field": "existingIndexPatternId",
|
||||
"name": "New index pattern",
|
||||
"render": [Function],
|
||||
},
|
||||
]
|
||||
}
|
||||
items={
|
||||
Array [
|
||||
Object {
|
||||
"existingIndexPatternId": "MyIndexPattern*",
|
||||
"list": Array [
|
||||
Object {
|
||||
"id": "MyIndexPattern*",
|
||||
"title": "MyIndexPattern*",
|
||||
"type": "index-pattern",
|
||||
},
|
||||
],
|
||||
"newIndexPatternId": undefined,
|
||||
},
|
||||
Object {
|
||||
"existingIndexPatternId": "filterIndex",
|
||||
"list": Array [
|
||||
Object {
|
||||
"id": "filterIndex",
|
||||
"title": "MyIndexPattern*",
|
||||
"type": "index-pattern",
|
||||
},
|
||||
],
|
||||
"newIndexPatternId": undefined,
|
||||
},
|
||||
]
|
||||
}
|
||||
onTableChange={[Function]}
|
||||
pagination={
|
||||
Object {
|
||||
"pageIndex": 0,
|
||||
"pageSize": 5,
|
||||
"pageSizeOptions": Array [
|
||||
5,
|
||||
10,
|
||||
25,
|
||||
],
|
||||
}
|
||||
}
|
||||
responsive={true}
|
||||
tableLayout="fixed"
|
||||
/>
|
||||
</EuiFlyoutBody>
|
||||
<EuiFlyoutFooter>
|
||||
<EuiFlexGroup
|
||||
justifyContent="spaceBetween"
|
||||
>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
>
|
||||
<EuiButtonEmpty
|
||||
data-test-subj="importSavedObjectsCancelBtn"
|
||||
disabled={false}
|
||||
onClick={[MockFunction]}
|
||||
size="s"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Cancel"
|
||||
id="savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
>
|
||||
<EuiButton
|
||||
data-test-subj="importSavedObjectsConfirmBtn"
|
||||
fill={true}
|
||||
isLoading={false}
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Confirm all changes"
|
||||
id="savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlyoutFooter>
|
||||
</EuiFlyout>
|
||||
`;
|
||||
|
||||
exports[`Flyout legacy conflicts should handle errors 2`] = `
|
||||
Array [
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
data-test-subj="importSavedObjectsLegacyWarning"
|
||||
iconType="help"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Support for JSON files is going away"
|
||||
id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Use our updated export to generate NDJSON files, and you'll be all set."
|
||||
id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody"
|
||||
values={Object {}}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>,
|
||||
<EuiCallOut
|
||||
color="warning"
|
||||
data-test-subj="importSavedObjectsConflictsWarning"
|
||||
iconType="help"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Index Pattern Conflicts"
|
||||
id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="The following saved objects use index patterns that do not exist. Please select the index patterns you'd like re-associated with them. You can {indexPatternLink} if necessary."
|
||||
id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription"
|
||||
values={
|
||||
Object {
|
||||
"indexPatternLink": <EuiLink
|
||||
href=""
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="create a new index pattern"
|
||||
id="savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText"
|
||||
values={Object {}}
|
||||
/>
|
||||
</EuiLink>,
|
||||
}
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>,
|
||||
<EuiCallOut
|
||||
color="danger"
|
||||
title={
|
||||
<FormattedMessage
|
||||
defaultMessage="Sorry, there was an error"
|
||||
id="savedObjectsManagement.objectsTable.flyout.errorCalloutTitle"
|
||||
values={Object {}}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<p
|
||||
data-test-subj="importSavedObjectsErrorText"
|
||||
>
|
||||
The file could not be processed due to error: "foobar"
|
||||
</p>
|
||||
</EuiCallOut>,
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Flyout should render import step 1`] = `
|
||||
<EuiFlyout
|
||||
data-test-subj="importSavedObjectsFlyout"
|
||||
|
@ -593,7 +320,7 @@ exports[`Flyout should render import step 1`] = `
|
|||
labelType="label"
|
||||
>
|
||||
<EuiFilePicker
|
||||
accept=".ndjson, .json"
|
||||
accept=".ndjson"
|
||||
compressed={false}
|
||||
display="large"
|
||||
fullWidth={true}
|
||||
|
@ -622,7 +349,6 @@ exports[`Flyout should render import step 1`] = `
|
|||
"overwrite": true,
|
||||
}
|
||||
}
|
||||
isLegacyFile={false}
|
||||
updateSelection={[Function]}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
|
|
@ -16,11 +16,6 @@ jest.doMock('../../../lib/resolve_import_errors', () => ({
|
|||
resolveImportErrors: resolveImportErrorsMock,
|
||||
}));
|
||||
|
||||
export const importLegacyFileMock = jest.fn();
|
||||
jest.doMock('../../../lib/import_legacy_file', () => ({
|
||||
importLegacyFile: importLegacyFileMock,
|
||||
}));
|
||||
|
||||
export const resolveSavedObjectsMock = jest.fn();
|
||||
export const resolveSavedSearchesMock = jest.fn();
|
||||
export const resolveIndexPatternConflictsMock = jest.fn();
|
||||
|
|
|
@ -6,15 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import {
|
||||
importFileMock,
|
||||
importLegacyFileMock,
|
||||
resolveImportErrorsMock,
|
||||
resolveIndexPatternConflictsMock,
|
||||
resolveSavedObjectsMock,
|
||||
resolveSavedSearchesMock,
|
||||
saveObjectsMock,
|
||||
} from './flyout.test.mocks';
|
||||
import { importFileMock, resolveImportErrorsMock } from './flyout.test.mocks';
|
||||
|
||||
import React from 'react';
|
||||
import { shallowWithI18nProvider } from '@kbn/test/jest';
|
||||
|
@ -28,10 +20,6 @@ const mockFile = ({
|
|||
name: 'foo.ndjson',
|
||||
path: '/home/foo.ndjson',
|
||||
} as unknown) as File;
|
||||
const legacyMockFile = ({
|
||||
name: 'foo.json',
|
||||
path: '/home/foo.json',
|
||||
} as unknown) as File;
|
||||
|
||||
describe('Flyout', () => {
|
||||
let defaultProps: FlyoutProps;
|
||||
|
@ -107,31 +95,6 @@ describe('Flyout', () => {
|
|||
expect(component.state('file')).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should handle invalid files', async () => {
|
||||
const component = shallowRender(defaultProps);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
importLegacyFileMock.mockImplementation(() => {
|
||||
throw new Error('foobar');
|
||||
});
|
||||
|
||||
await component.instance().legacyImport();
|
||||
expect(component.state('error')).toBe('The file could not be processed.');
|
||||
|
||||
importLegacyFileMock.mockImplementation(() => ({
|
||||
invalid: true,
|
||||
}));
|
||||
|
||||
await component.instance().legacyImport();
|
||||
expect(component.state('error')).toBe(
|
||||
'Saved objects file format is invalid and cannot be imported.'
|
||||
);
|
||||
});
|
||||
|
||||
describe('conflicts', () => {
|
||||
beforeEach(() => {
|
||||
importFileMock.mockImplementation(() => ({
|
||||
|
@ -169,7 +132,7 @@ describe('Flyout', () => {
|
|||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
component.setState({ file: mockFile, isLegacyFile: false });
|
||||
component.setState({ file: mockFile });
|
||||
await component.instance().import();
|
||||
|
||||
expect(importFileMock).toHaveBeenCalledWith(defaultProps.http, mockFile, {
|
||||
|
@ -207,7 +170,7 @@ describe('Flyout', () => {
|
|||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
component.setState({ file: mockFile, isLegacyFile: false });
|
||||
component.setState({ file: mockFile });
|
||||
await component.instance().import();
|
||||
|
||||
// Ensure it looks right
|
||||
|
@ -250,7 +213,7 @@ describe('Flyout', () => {
|
|||
successfulImports,
|
||||
}));
|
||||
|
||||
component.setState({ file: mockFile, isLegacyFile: false });
|
||||
component.setState({ file: mockFile });
|
||||
|
||||
// Go through the import flow
|
||||
await component.instance().import();
|
||||
|
@ -267,194 +230,4 @@ describe('Flyout', () => {
|
|||
expect(cancelButton.prop('disabled')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('legacy conflicts', () => {
|
||||
const mockData = [
|
||||
{
|
||||
_id: '1',
|
||||
_type: 'search',
|
||||
},
|
||||
{
|
||||
_id: '2',
|
||||
_type: 'index-pattern',
|
||||
},
|
||||
{
|
||||
_id: '3',
|
||||
_type: 'invalid',
|
||||
},
|
||||
];
|
||||
|
||||
const mockConflictedIndexPatterns = [
|
||||
{
|
||||
doc: {
|
||||
_type: 'index-pattern',
|
||||
_id: '1',
|
||||
_source: {
|
||||
title: 'MyIndexPattern*',
|
||||
},
|
||||
},
|
||||
obj: {
|
||||
searchSource: {
|
||||
getOwnField: (field: string) => {
|
||||
if (field === 'index') {
|
||||
return 'MyIndexPattern*';
|
||||
}
|
||||
if (field === 'filter') {
|
||||
return [{ meta: { index: 'filterIndex' } }];
|
||||
}
|
||||
},
|
||||
},
|
||||
_serialize: () => {
|
||||
return { references: [{ id: 'MyIndexPattern*' }, { id: 'filterIndex' }] };
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const mockConflictedSavedObjectsLinkedToSavedSearches = [2];
|
||||
const mockConflictedSearchDocs = [3];
|
||||
|
||||
beforeEach(() => {
|
||||
importLegacyFileMock.mockImplementation(() => mockData);
|
||||
resolveSavedObjectsMock.mockImplementation(() => ({
|
||||
conflictedIndexPatterns: mockConflictedIndexPatterns,
|
||||
conflictedSavedObjectsLinkedToSavedSearches: mockConflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs: mockConflictedSearchDocs,
|
||||
importedObjectCount: 2,
|
||||
confirmModalPromise: () => {},
|
||||
}));
|
||||
});
|
||||
|
||||
it('should figure out unmatchedReferences', async () => {
|
||||
const component = shallowRender(defaultProps);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
component.setState({ file: legacyMockFile, isLegacyFile: true });
|
||||
await component.instance().legacyImport();
|
||||
|
||||
expect(importLegacyFileMock).toHaveBeenCalledWith(legacyMockFile);
|
||||
// Remove the last element from data since it should be filtered out
|
||||
expect(resolveSavedObjectsMock).toHaveBeenCalledWith(
|
||||
mockData.slice(0, 2).map((doc) => ({ ...doc, _migrationVersion: {} })),
|
||||
true,
|
||||
defaultProps.serviceRegistry.all().map((s) => s.service),
|
||||
defaultProps.indexPatterns,
|
||||
defaultProps.overlays.openConfirm
|
||||
);
|
||||
|
||||
expect(component.state()).toMatchObject({
|
||||
conflictedIndexPatterns: mockConflictedIndexPatterns,
|
||||
conflictedSavedObjectsLinkedToSavedSearches: mockConflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs: mockConflictedSearchDocs,
|
||||
importCount: 2,
|
||||
status: 'idle',
|
||||
error: undefined,
|
||||
unmatchedReferences: [
|
||||
{
|
||||
existingIndexPatternId: 'MyIndexPattern*',
|
||||
newIndexPatternId: undefined,
|
||||
list: [
|
||||
{
|
||||
id: 'MyIndexPattern*',
|
||||
title: 'MyIndexPattern*',
|
||||
type: 'index-pattern',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
existingIndexPatternId: 'filterIndex',
|
||||
list: [
|
||||
{
|
||||
id: 'filterIndex',
|
||||
title: 'MyIndexPattern*',
|
||||
type: 'index-pattern',
|
||||
},
|
||||
],
|
||||
newIndexPatternId: undefined,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow conflict resolution', async () => {
|
||||
const component = shallowRender(defaultProps);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
component.setState({ file: legacyMockFile, isLegacyFile: true });
|
||||
await component.instance().legacyImport();
|
||||
|
||||
// Ensure it looks right
|
||||
component.update();
|
||||
expect(component).toMatchSnapshot();
|
||||
|
||||
// Ensure we can change the resolution
|
||||
component.instance().onIndexChanged('MyIndexPattern*', { target: { value: '2' } });
|
||||
expect(component.state('unmatchedReferences')![0].newIndexPatternId).toBe('2');
|
||||
|
||||
// Let's resolve now
|
||||
await component
|
||||
.find('EuiButton[data-test-subj="importSavedObjectsConfirmBtn"]')
|
||||
.simulate('click');
|
||||
// Ensure all promises resolve
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
expect(resolveIndexPatternConflictsMock).toHaveBeenCalledWith(
|
||||
component.instance().resolutions,
|
||||
mockConflictedIndexPatterns,
|
||||
true,
|
||||
{
|
||||
search: defaultProps.search,
|
||||
indexPatterns: defaultProps.indexPatterns,
|
||||
}
|
||||
);
|
||||
expect(saveObjectsMock).toHaveBeenCalledWith(
|
||||
mockConflictedSavedObjectsLinkedToSavedSearches,
|
||||
true
|
||||
);
|
||||
expect(resolveSavedSearchesMock).toHaveBeenCalledWith(
|
||||
mockConflictedSearchDocs,
|
||||
defaultProps.serviceRegistry.all().map((s) => s.service),
|
||||
defaultProps.indexPatterns,
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle errors', async () => {
|
||||
const component = shallowRender(defaultProps);
|
||||
|
||||
// Ensure all promises resolve
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
// Ensure the state changes are reflected
|
||||
component.update();
|
||||
|
||||
resolveIndexPatternConflictsMock.mockImplementation(() => {
|
||||
throw new Error('foobar');
|
||||
});
|
||||
|
||||
component.setState({ file: legacyMockFile, isLegacyFile: true });
|
||||
|
||||
// Go through the import flow
|
||||
await component.instance().legacyImport();
|
||||
component.update();
|
||||
// Set a resolution
|
||||
component.instance().onIndexChanged('MyIndexPattern*', { target: { value: '2' } });
|
||||
await component
|
||||
.find('EuiButton[data-test-subj="importSavedObjectsConfirmBtn"]')
|
||||
.simulate('click');
|
||||
// Ensure all promises resolve
|
||||
await new Promise((resolve) => process.nextTick(resolve));
|
||||
|
||||
expect(component.state('error')).toMatchInlineSnapshot(
|
||||
`"The file could not be processed due to error: \\"foobar\\""`
|
||||
);
|
||||
expect(component.find('EuiFlyoutBody EuiCallOut')).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import React, { Component, Fragment, ReactNode } from 'react';
|
||||
import { take, get as getField } from 'lodash';
|
||||
import { take } from 'lodash';
|
||||
import {
|
||||
EuiFlyout,
|
||||
EuiFlyoutBody,
|
||||
|
@ -39,18 +39,10 @@ import {
|
|||
} from '../../../../../data/public';
|
||||
import {
|
||||
importFile,
|
||||
importLegacyFile,
|
||||
resolveImportErrors,
|
||||
logLegacyImport,
|
||||
processImportResponse,
|
||||
ProcessedImportResponse,
|
||||
} from '../../../lib';
|
||||
import {
|
||||
resolveSavedObjects,
|
||||
resolveSavedSearches,
|
||||
resolveIndexPatternConflicts,
|
||||
saveObjects,
|
||||
} from '../../../lib/resolve_saved_objects';
|
||||
import { ISavedObjectsManagementServiceRegistry } from '../../../services';
|
||||
import { FailedImportConflict, RetryDecision } from '../../../lib/resolve_import_errors';
|
||||
import { OverwriteModal } from './overwrite_modal';
|
||||
|
@ -89,7 +81,6 @@ export interface FlyoutState {
|
|||
indexPatterns?: IndexPattern[];
|
||||
importMode: ImportMode;
|
||||
loadingMessage?: string;
|
||||
isLegacyFile: boolean;
|
||||
status: string;
|
||||
}
|
||||
|
||||
|
@ -129,7 +120,6 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
indexPatterns: undefined,
|
||||
importMode: { createNewCopies: CREATE_NEW_COPIES_DEFAULT, overwrite: OVERWRITE_ALL_DEFAULT },
|
||||
loadingMessage: undefined,
|
||||
isLegacyFile: false,
|
||||
status: 'idle',
|
||||
};
|
||||
}
|
||||
|
@ -152,14 +142,11 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
|
||||
setImportFile = (files: FileList | null) => {
|
||||
if (!files || !files[0]) {
|
||||
this.setState({ file: undefined, isLegacyFile: false });
|
||||
this.setState({ file: undefined });
|
||||
return;
|
||||
}
|
||||
const file = files[0];
|
||||
this.setState({
|
||||
file,
|
||||
isLegacyFile: /\.json$/i.test(file.name) || file.type === 'application/json',
|
||||
});
|
||||
this.setState({ file });
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -246,103 +233,6 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
}
|
||||
};
|
||||
|
||||
legacyImport = async () => {
|
||||
const { serviceRegistry, indexPatterns, overlays, http, allowedTypes } = this.props;
|
||||
const { file, importMode } = this.state;
|
||||
|
||||
this.setState({ status: 'loading', error: undefined });
|
||||
|
||||
// Log warning on server, don't wait for response
|
||||
logLegacyImport(http);
|
||||
|
||||
let contents;
|
||||
try {
|
||||
contents = await importLegacyFile(file!);
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
status: 'error',
|
||||
error: i18n.translate(
|
||||
'savedObjectsManagement.objectsTable.flyout.importLegacyFileErrorMessage',
|
||||
{ defaultMessage: 'The file could not be processed.' }
|
||||
),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Array.isArray(contents)) {
|
||||
this.setState({
|
||||
status: 'error',
|
||||
error: i18n.translate(
|
||||
'savedObjectsManagement.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage',
|
||||
{ defaultMessage: 'Saved objects file format is invalid and cannot be imported.' }
|
||||
),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
contents = contents
|
||||
.filter((content) => allowedTypes.includes(content._type))
|
||||
.map((doc) => ({
|
||||
...doc,
|
||||
// The server assumes that documents with no migrationVersion are up to date.
|
||||
// That assumption enables Kibana and other API consumers to not have to build
|
||||
// up migrationVersion prior to creating new objects. But it means that imports
|
||||
// need to set migrationVersion to something other than undefined, so that imported
|
||||
// docs are not seen as automatically up-to-date.
|
||||
_migrationVersion: doc._migrationVersion || {},
|
||||
}));
|
||||
|
||||
const {
|
||||
conflictedIndexPatterns,
|
||||
conflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs,
|
||||
importedObjectCount,
|
||||
failedImports,
|
||||
} = await resolveSavedObjects(
|
||||
contents,
|
||||
importMode.overwrite,
|
||||
serviceRegistry.all().map((e) => e.service),
|
||||
indexPatterns,
|
||||
overlays.openConfirm
|
||||
);
|
||||
|
||||
const byId: Record<string, any[]> = {};
|
||||
conflictedIndexPatterns
|
||||
.map(({ doc, obj }) => {
|
||||
return { doc, obj: obj._serialize() };
|
||||
})
|
||||
.forEach(({ doc, obj }) =>
|
||||
obj.references.forEach((ref: Record<string, any>) => {
|
||||
byId[ref.id] = byId[ref.id] != null ? byId[ref.id].concat({ doc, obj }) : [{ doc, obj }];
|
||||
})
|
||||
);
|
||||
const unmatchedReferences = Object.entries(byId).reduce(
|
||||
(accum, [existingIndexPatternId, list]) => {
|
||||
accum.push({
|
||||
existingIndexPatternId,
|
||||
newIndexPatternId: undefined,
|
||||
list: list.map(({ doc }) => ({
|
||||
id: existingIndexPatternId,
|
||||
type: doc._type,
|
||||
title: doc._source.title,
|
||||
})),
|
||||
});
|
||||
return accum;
|
||||
},
|
||||
[] as any[]
|
||||
);
|
||||
|
||||
this.setState({
|
||||
conflictedIndexPatterns,
|
||||
conflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs,
|
||||
failedImports,
|
||||
unmatchedReferences,
|
||||
importCount: importedObjectCount,
|
||||
status: unmatchedReferences.length === 0 ? 'success' : 'idle',
|
||||
});
|
||||
};
|
||||
|
||||
public get hasUnmatchedReferences() {
|
||||
return this.state.unmatchedReferences && this.state.unmatchedReferences.length > 0;
|
||||
}
|
||||
|
@ -362,89 +252,6 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
);
|
||||
}
|
||||
|
||||
confirmLegacyImport = async () => {
|
||||
const {
|
||||
conflictedIndexPatterns,
|
||||
importMode,
|
||||
conflictedSavedObjectsLinkedToSavedSearches,
|
||||
conflictedSearchDocs,
|
||||
failedImports,
|
||||
} = this.state;
|
||||
|
||||
const { serviceRegistry, indexPatterns, search } = this.props;
|
||||
|
||||
this.setState({
|
||||
error: undefined,
|
||||
status: 'loading',
|
||||
loadingMessage: undefined,
|
||||
});
|
||||
|
||||
let importCount = this.state.importCount;
|
||||
|
||||
if (this.hasUnmatchedReferences) {
|
||||
try {
|
||||
const resolutions = this.resolutions;
|
||||
|
||||
// Do not Promise.all these calls as the order matters
|
||||
this.setState({
|
||||
loadingMessage: i18n.translate(
|
||||
'savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage',
|
||||
{ defaultMessage: 'Resolving conflicts…' }
|
||||
),
|
||||
});
|
||||
if (resolutions.length) {
|
||||
importCount += await resolveIndexPatternConflicts(
|
||||
resolutions,
|
||||
conflictedIndexPatterns!,
|
||||
importMode.overwrite,
|
||||
{ indexPatterns, search }
|
||||
);
|
||||
}
|
||||
this.setState({
|
||||
loadingMessage: i18n.translate(
|
||||
'savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage',
|
||||
{ defaultMessage: 'Saving conflicts…' }
|
||||
),
|
||||
});
|
||||
importCount += await saveObjects(
|
||||
conflictedSavedObjectsLinkedToSavedSearches!,
|
||||
importMode.overwrite
|
||||
);
|
||||
this.setState({
|
||||
loadingMessage: i18n.translate(
|
||||
'savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage',
|
||||
{ defaultMessage: 'Ensure saved searches are linked properly…' }
|
||||
),
|
||||
});
|
||||
importCount += await resolveSavedSearches(
|
||||
conflictedSearchDocs!,
|
||||
serviceRegistry.all().map((e) => e.service),
|
||||
indexPatterns,
|
||||
importMode.overwrite
|
||||
);
|
||||
this.setState({
|
||||
loadingMessage: i18n.translate(
|
||||
'savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage',
|
||||
{ defaultMessage: 'Retrying failed objects…' }
|
||||
),
|
||||
});
|
||||
importCount += await saveObjects(
|
||||
failedImports!.map(({ obj }) => obj) as any[],
|
||||
importMode.overwrite
|
||||
);
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
status: 'error',
|
||||
error: getErrorMessage(e),
|
||||
loadingMessage: undefined,
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ status: 'success', importCount });
|
||||
};
|
||||
|
||||
onIndexChanged = (id: string, e: any) => {
|
||||
const value = e.target.value;
|
||||
this.setState((state) => {
|
||||
|
@ -613,10 +420,8 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
const {
|
||||
status,
|
||||
loadingMessage,
|
||||
importCount,
|
||||
failedImports = [],
|
||||
successfulImports = [],
|
||||
isLegacyFile,
|
||||
importMode,
|
||||
importWarnings,
|
||||
} = this.state;
|
||||
|
@ -635,7 +440,8 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
);
|
||||
}
|
||||
|
||||
if (!isLegacyFile && status === 'success') {
|
||||
// Import summary for completed import
|
||||
if (status === 'success') {
|
||||
return (
|
||||
<ImportSummary
|
||||
basePath={this.props.http.basePath}
|
||||
|
@ -646,108 +452,7 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
);
|
||||
}
|
||||
|
||||
// Import summary for failed legacy import
|
||||
if (failedImports.length && !this.hasUnmatchedReferences) {
|
||||
return (
|
||||
<EuiCallOut
|
||||
data-test-subj="importSavedObjectsFailedWarning"
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="savedObjectsManagement.objectsTable.flyout.importFailedTitle"
|
||||
defaultMessage="Import failed"
|
||||
/>
|
||||
}
|
||||
color="warning"
|
||||
iconType="help"
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="savedObjectsManagement.objectsTable.flyout.importFailedDescription"
|
||||
defaultMessage="Failed to import {failedImportCount} of {totalImportCount} objects. Import failed"
|
||||
values={{
|
||||
failedImportCount: failedImports.length,
|
||||
totalImportCount: importCount + failedImports.length,
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
<p>
|
||||
{failedImports
|
||||
.map(({ error, obj }) => {
|
||||
if (error.type === 'missing_references') {
|
||||
return error.references.map((reference) => {
|
||||
return i18n.translate(
|
||||
'savedObjectsManagement.objectsTable.flyout.importFailedMissingReference',
|
||||
{
|
||||
defaultMessage: '{type} [id={id}] could not locate {refType} [id={refId}]',
|
||||
values: {
|
||||
id: obj.id,
|
||||
type: obj.type,
|
||||
refId: reference.id,
|
||||
refType: reference.type,
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
} else if (error.type === 'unsupported_type') {
|
||||
return i18n.translate(
|
||||
'savedObjectsManagement.objectsTable.flyout.importFailedUnsupportedType',
|
||||
{
|
||||
defaultMessage: '{type} [id={id}] unsupported type',
|
||||
values: {
|
||||
id: obj.id,
|
||||
type: obj.type,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
return getField(error, 'body.message', (error as any).message ?? '');
|
||||
})
|
||||
.join(' ')}
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
);
|
||||
}
|
||||
|
||||
// Import summary for completed legacy import
|
||||
if (status === 'success') {
|
||||
if (importCount === 0) {
|
||||
return (
|
||||
<EuiCallOut
|
||||
data-test-subj="importSavedObjectsSuccessNoneImported"
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="savedObjectsManagement.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle"
|
||||
defaultMessage="No objects imported"
|
||||
/>
|
||||
}
|
||||
color="primary"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiCallOut
|
||||
data-test-subj="importSavedObjectsSuccess"
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="savedObjectsManagement.objectsTable.flyout.importSuccessfulTitle"
|
||||
defaultMessage="Import successful"
|
||||
/>
|
||||
}
|
||||
color="success"
|
||||
iconType="check"
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="savedObjectsManagement.objectsTable.flyout.importSuccessfulDescription"
|
||||
defaultMessage="Successfully imported {importCount} objects."
|
||||
values={{ importCount }}
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
);
|
||||
}
|
||||
|
||||
// Failed imports
|
||||
if (this.hasUnmatchedReferences) {
|
||||
return this.renderUnmatchedReferences();
|
||||
}
|
||||
|
@ -768,7 +473,7 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
}
|
||||
>
|
||||
<EuiFilePicker
|
||||
accept=".ndjson, .json"
|
||||
accept=".ndjson"
|
||||
fullWidth
|
||||
initialPromptText={
|
||||
<FormattedMessage
|
||||
|
@ -782,7 +487,6 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
<EuiFormRow fullWidth>
|
||||
<ImportModeControl
|
||||
initialValues={importMode}
|
||||
isLegacyFile={isLegacyFile}
|
||||
updateSelection={(newValues: ImportMode) => this.changeImportMode(newValues)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
@ -791,7 +495,7 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
}
|
||||
|
||||
renderFooter() {
|
||||
const { isLegacyFile, status } = this.state;
|
||||
const { status } = this.state;
|
||||
const { done, close } = this.props;
|
||||
|
||||
let confirmButton;
|
||||
|
@ -808,7 +512,7 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
} else if (this.hasUnmatchedReferences) {
|
||||
confirmButton = (
|
||||
<EuiButton
|
||||
onClick={isLegacyFile ? this.confirmLegacyImport : this.resolveImportErrors}
|
||||
onClick={this.resolveImportErrors}
|
||||
size="s"
|
||||
fill
|
||||
isLoading={status === 'loading'}
|
||||
|
@ -823,7 +527,7 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
} else {
|
||||
confirmButton = (
|
||||
<EuiButton
|
||||
onClick={isLegacyFile ? this.legacyImport : this.import}
|
||||
onClick={this.import}
|
||||
size="s"
|
||||
fill
|
||||
isLoading={status === 'loading'}
|
||||
|
@ -843,7 +547,7 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
<EuiButtonEmpty
|
||||
onClick={close}
|
||||
size="s"
|
||||
disabled={status === 'loading' || (isLegacyFile === false && status === 'success')}
|
||||
disabled={status === 'loading' || status === 'success'}
|
||||
data-test-subj="importSavedObjectsCancelBtn"
|
||||
>
|
||||
<FormattedMessage
|
||||
|
@ -862,33 +566,6 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
return null;
|
||||
}
|
||||
|
||||
let legacyFileWarning;
|
||||
if (this.state.isLegacyFile) {
|
||||
legacyFileWarning = (
|
||||
<>
|
||||
<EuiCallOut
|
||||
data-test-subj="importSavedObjectsLegacyWarning"
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle"
|
||||
defaultMessage="Support for JSON files is going away"
|
||||
/>
|
||||
}
|
||||
color="warning"
|
||||
iconType="help"
|
||||
>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody"
|
||||
defaultMessage="Use our updated export to generate NDJSON files, and you'll be all set."
|
||||
/>
|
||||
</p>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer size="m" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
let indexPatternConflictsWarning;
|
||||
if (this.hasUnmatchedReferences) {
|
||||
indexPatternConflictsWarning = (
|
||||
|
@ -925,18 +602,12 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
|
|||
);
|
||||
}
|
||||
|
||||
if (!legacyFileWarning && !indexPatternConflictsWarning) {
|
||||
if (!indexPatternConflictsWarning) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{legacyFileWarning && (
|
||||
<span>
|
||||
<EuiSpacer size="s" />
|
||||
{legacyFileWarning}
|
||||
</span>
|
||||
)}
|
||||
{indexPatternConflictsWarning && (
|
||||
<span>
|
||||
<EuiSpacer size="s" />
|
||||
|
|
|
@ -32,14 +32,9 @@ describe('ImportModeControl', () => {
|
|||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
const props: ImportModeControlProps = { initialValues, updateSelection, isLegacyFile: false };
|
||||
const props: ImportModeControlProps = { initialValues, updateSelection };
|
||||
|
||||
it('returns partial import mode control when used with a legacy file', async () => {
|
||||
const wrapper = shallowWithI18nProvider(<ImportModeControl {...props} isLegacyFile={true} />);
|
||||
expect(wrapper.find('EuiFormFieldset')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('returns full import mode control when used without a legacy file', async () => {
|
||||
it('returns full import mode control', async () => {
|
||||
const wrapper = shallowWithI18nProvider(<ImportModeControl {...props} />);
|
||||
expect(wrapper.find('EuiFormFieldset')).toHaveLength(1);
|
||||
});
|
||||
|
|
|
@ -22,7 +22,6 @@ import { i18n } from '@kbn/i18n';
|
|||
|
||||
export interface ImportModeControlProps {
|
||||
initialValues: ImportMode;
|
||||
isLegacyFile: boolean;
|
||||
updateSelection: (result: ImportMode) => void;
|
||||
}
|
||||
|
||||
|
@ -87,11 +86,7 @@ const createLabel = ({ text, tooltip }: { text: string; tooltip: string }) => (
|
|||
</EuiFlexGroup>
|
||||
);
|
||||
|
||||
export const ImportModeControl = ({
|
||||
initialValues,
|
||||
isLegacyFile,
|
||||
updateSelection,
|
||||
}: ImportModeControlProps) => {
|
||||
export const ImportModeControl = ({ initialValues, updateSelection }: ImportModeControlProps) => {
|
||||
const [createNewCopies, setCreateNewCopies] = useState(initialValues.createNewCopies);
|
||||
const [overwrite, setOverwrite] = useState(initialValues.overwrite);
|
||||
|
||||
|
@ -104,20 +99,6 @@ export const ImportModeControl = ({
|
|||
updateSelection({ createNewCopies, overwrite, ...partial });
|
||||
};
|
||||
|
||||
const overwriteRadio = (
|
||||
<EuiRadioGroup
|
||||
options={[overwriteEnabled, overwriteDisabled]}
|
||||
idSelected={overwrite ? overwriteEnabled.id : overwriteDisabled.id}
|
||||
onChange={(id: string) => onChange({ overwrite: id === overwriteEnabled.id })}
|
||||
disabled={createNewCopies && !isLegacyFile}
|
||||
data-test-subj={'savedObjectsManagement-importModeControl-overwriteRadioGroup'}
|
||||
/>
|
||||
);
|
||||
|
||||
if (isLegacyFile) {
|
||||
return overwriteRadio;
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFormFieldset
|
||||
legend={{
|
||||
|
@ -134,7 +115,13 @@ export const ImportModeControl = ({
|
|||
checked={!createNewCopies}
|
||||
onChange={() => onChange({ createNewCopies: false })}
|
||||
>
|
||||
{overwriteRadio}
|
||||
<EuiRadioGroup
|
||||
options={[overwriteEnabled, overwriteDisabled]}
|
||||
idSelected={overwrite ? overwriteEnabled.id : overwriteDisabled.id}
|
||||
onChange={(id: string) => onChange({ overwrite: id === overwriteEnabled.id })}
|
||||
disabled={createNewCopies}
|
||||
data-test-subj={'savedObjectsManagement-importModeControl-overwriteRadioGroup'}
|
||||
/>
|
||||
</EuiCheckableCard>
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
|
|
@ -12,8 +12,8 @@ import { FtrProviderContext } from '../../ftr_provider_context';
|
|||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const PageObjects = getPageObjects(['dashboard', 'header', 'settings', 'savedObjects', 'common']);
|
||||
const dashboardExpect = getService('dashboardExpect');
|
||||
|
||||
describe('bwc import', function describeIndexTests() {
|
||||
// Legacy imports are no longer supported https://github.com/elastic/kibana/issues/103921
|
||||
describe.skip('bwc import', function describeIndexTests() {
|
||||
before(async function () {
|
||||
await PageObjects.dashboard.initTests();
|
||||
await PageObjects.settings.navigateTo();
|
||||
|
|
|
@ -22,8 +22,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
'common',
|
||||
'savedObjects',
|
||||
]);
|
||||
|
||||
describe('dashboard time zones', function () {
|
||||
// Legacy imports are no longer supported https://github.com/elastic/kibana/issues/103921
|
||||
describe.skip('dashboard time zones', function () {
|
||||
this.tags('includeFirefox');
|
||||
|
||||
before(async () => {
|
||||
|
|
|
@ -11,8 +11,6 @@ import path from 'path';
|
|||
import { keyBy } from 'lodash';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
function uniq<T>(input: T[]): T[] {
|
||||
return [...new Set(input)];
|
||||
}
|
||||
|
@ -210,284 +208,5 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
expect(isSavedObjectImported).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.json file', () => {
|
||||
beforeEach(async function () {
|
||||
await esArchiver.load('test/functional/fixtures/es_archiver/saved_objects_imports');
|
||||
await kibanaServer.uiSettings.replace({});
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await esArchiver.unload('test/functional/fixtures/es_archiver/saved_objects_imports');
|
||||
});
|
||||
|
||||
it('should import saved objects', async function () {
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects.json')
|
||||
);
|
||||
await PageObjects.savedObjects.checkImportSucceeded();
|
||||
await PageObjects.savedObjects.clickImportDone();
|
||||
const objects = await PageObjects.savedObjects.getRowTitles();
|
||||
const isSavedObjectImported = objects.includes('Log Agents');
|
||||
expect(isSavedObjectImported).to.be(true);
|
||||
});
|
||||
|
||||
it('should provide dialog to allow the importing of saved objects with index pattern conflicts', async function () {
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects-conflicts.json')
|
||||
);
|
||||
await PageObjects.savedObjects.checkImportLegacyWarning();
|
||||
await PageObjects.savedObjects.checkImportConflictsWarning();
|
||||
await PageObjects.settings.associateIndexPattern(
|
||||
'd1e4c910-a2e6-11e7-bb30-233be9be6a15',
|
||||
'logstash-*'
|
||||
);
|
||||
await PageObjects.savedObjects.clickConfirmChanges();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await PageObjects.savedObjects.clickImportDone();
|
||||
const objects = await PageObjects.savedObjects.getRowTitles();
|
||||
const isSavedObjectImported = objects.includes('saved object with index pattern conflict');
|
||||
expect(isSavedObjectImported).to.be(true);
|
||||
});
|
||||
|
||||
it('should allow the user to override duplicate saved objects', async function () {
|
||||
// This data has already been loaded by the "visualize" esArchive. We'll load it again
|
||||
// so that we can override the existing visualization.
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_exists.json'),
|
||||
false
|
||||
);
|
||||
|
||||
await PageObjects.savedObjects.checkImportLegacyWarning();
|
||||
await PageObjects.savedObjects.checkImportConflictsWarning();
|
||||
await PageObjects.settings.associateIndexPattern('logstash-*', 'logstash-*');
|
||||
await PageObjects.savedObjects.clickConfirmChanges();
|
||||
|
||||
// Override the visualization.
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
|
||||
const isSuccessful = await testSubjects.exists('importSavedObjectsSuccess');
|
||||
expect(isSuccessful).to.be(true);
|
||||
});
|
||||
|
||||
it('should allow the user to cancel overriding duplicate saved objects', async function () {
|
||||
// This data has already been loaded by the "visualize" esArchive. We'll load it again
|
||||
// so that we can be prompted to override the existing visualization.
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_exists.json'),
|
||||
false
|
||||
);
|
||||
|
||||
await PageObjects.savedObjects.checkImportLegacyWarning();
|
||||
await PageObjects.savedObjects.checkImportConflictsWarning();
|
||||
await PageObjects.settings.associateIndexPattern('logstash-*', 'logstash-*');
|
||||
await PageObjects.savedObjects.clickConfirmChanges();
|
||||
|
||||
// *Don't* override the visualization.
|
||||
await PageObjects.common.clickCancelOnModal();
|
||||
|
||||
const isSuccessful = await testSubjects.exists('importSavedObjectsSuccessNoneImported');
|
||||
expect(isSuccessful).to.be(true);
|
||||
});
|
||||
|
||||
it('should allow the user to confirm overriding multiple duplicate saved objects', async function () {
|
||||
// This data has already been loaded by the "visualize" esArchive. We'll load it again
|
||||
// so that we can override the existing visualization.
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_multiple_exists.json'),
|
||||
false
|
||||
);
|
||||
|
||||
await PageObjects.savedObjects.checkImportLegacyWarning();
|
||||
await PageObjects.savedObjects.checkImportConflictsWarning();
|
||||
|
||||
await PageObjects.settings.associateIndexPattern('logstash-*', 'logstash-*');
|
||||
await PageObjects.savedObjects.clickConfirmChanges();
|
||||
|
||||
// Override the visualizations.
|
||||
await PageObjects.common.clickConfirmOnModal(false);
|
||||
// as the second confirm can pop instantly, we can't wait for it to be hidden
|
||||
// with is why we call clickConfirmOnModal with ensureHidden: false in previous statement
|
||||
// but as the initial popin can take a few ms before fading, we need to wait a little
|
||||
// to avoid clicking twice on the same modal.
|
||||
await delay(1000);
|
||||
await PageObjects.common.clickConfirmOnModal(true);
|
||||
|
||||
const isSuccessful = await testSubjects.exists('importSavedObjectsSuccess');
|
||||
expect(isSuccessful).to.be(true);
|
||||
});
|
||||
|
||||
it('should allow the user to confirm overriding multiple duplicate index patterns', async function () {
|
||||
// This data has already been loaded by the "visualize" esArchive. We'll load it again
|
||||
// so that we can override the existing visualization.
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_index_patterns_multiple_exists.json'),
|
||||
false
|
||||
);
|
||||
|
||||
// Override the index patterns.
|
||||
await PageObjects.common.clickConfirmOnModal(false);
|
||||
// as the second confirm can pop instantly, we can't wait for it to be hidden
|
||||
// with is why we call clickConfirmOnModal with ensureHidden: false in previous statement
|
||||
// but as the initial popin can take a few ms before fading, we need to wait a little
|
||||
// to avoid clicking twice on the same modal.
|
||||
await delay(1000);
|
||||
await PageObjects.common.clickConfirmOnModal(true);
|
||||
|
||||
const isSuccessful = await testSubjects.exists('importSavedObjectsSuccess');
|
||||
expect(isSuccessful).to.be(true);
|
||||
});
|
||||
|
||||
it('should import saved objects linked to saved searches', async function () {
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_saved_search.json')
|
||||
);
|
||||
await PageObjects.savedObjects.checkImportSucceeded();
|
||||
await PageObjects.savedObjects.clickImportDone();
|
||||
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_connected_to_saved_search.json')
|
||||
);
|
||||
await PageObjects.savedObjects.checkImportSucceeded();
|
||||
await PageObjects.savedObjects.clickImportDone();
|
||||
|
||||
const objects = await PageObjects.savedObjects.getRowTitles();
|
||||
const isSavedObjectImported = objects.includes('saved object connected to saved search');
|
||||
expect(isSavedObjectImported).to.be(true);
|
||||
});
|
||||
|
||||
it('should not import saved objects linked to saved searches when saved search does not exist', async function () {
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_connected_to_saved_search.json')
|
||||
);
|
||||
await PageObjects.savedObjects.checkImportFailedWarning();
|
||||
await PageObjects.savedObjects.clickImportDone();
|
||||
|
||||
const objects = await PageObjects.savedObjects.getRowTitles();
|
||||
const isSavedObjectImported = objects.includes('saved object connected to saved search');
|
||||
expect(isSavedObjectImported).to.be(false);
|
||||
});
|
||||
|
||||
it('should not import saved objects linked to saved searches when saved search index pattern does not exist', async function () {
|
||||
// First, import the saved search
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_saved_search.json')
|
||||
);
|
||||
// Wait for all the saves to happen
|
||||
await PageObjects.savedObjects.checkImportSucceeded();
|
||||
await PageObjects.savedObjects.clickImportDone();
|
||||
|
||||
// Second, we need to delete the index pattern
|
||||
await PageObjects.savedObjects.clickCheckboxByTitle('logstash-*');
|
||||
await PageObjects.savedObjects.clickDelete();
|
||||
|
||||
// Last, import a saved object connected to the saved search
|
||||
// This should NOT show the conflicts
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_connected_to_saved_search.json')
|
||||
);
|
||||
// Wait for all the saves to happen
|
||||
await PageObjects.savedObjects.checkNoneImported();
|
||||
await PageObjects.savedObjects.clickImportDone();
|
||||
|
||||
const objects = await PageObjects.savedObjects.getRowTitles();
|
||||
const isSavedObjectImported = objects.includes('saved object connected to saved search');
|
||||
expect(isSavedObjectImported).to.be(false);
|
||||
});
|
||||
|
||||
it('should import saved objects with index patterns when index patterns already exists', async () => {
|
||||
// First, import the objects
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_with_index_patterns.json')
|
||||
);
|
||||
await PageObjects.savedObjects.clickImportDone();
|
||||
|
||||
const objects = await PageObjects.savedObjects.getRowTitles();
|
||||
const isSavedObjectImported = objects.includes('saved object imported with index pattern');
|
||||
expect(isSavedObjectImported).to.be(true);
|
||||
});
|
||||
|
||||
it('should preserve index patterns selection when switching between pages', async () => {
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_objects_missing_all_index_patterns.json')
|
||||
);
|
||||
|
||||
await PageObjects.savedObjects.setOverriddenIndexPatternValue(
|
||||
'missing-index-pattern-1',
|
||||
'index-pattern-test-1'
|
||||
);
|
||||
|
||||
const flyout = await testSubjects.find('importSavedObjectsFlyout');
|
||||
|
||||
await (await flyout.findByTestSubject('pagination-button-next')).click();
|
||||
|
||||
await PageObjects.savedObjects.setOverriddenIndexPatternValue(
|
||||
'missing-index-pattern-7',
|
||||
'index-pattern-test-2'
|
||||
);
|
||||
|
||||
await (await flyout.findByTestSubject('pagination-button-previous')).click();
|
||||
|
||||
const selectedIdForMissingIndexPattern1 = await testSubjects.getAttribute(
|
||||
'managementChangeIndexSelection-missing-index-pattern-1',
|
||||
'value'
|
||||
);
|
||||
|
||||
expect(selectedIdForMissingIndexPattern1).to.eql('f1e4c910-a2e6-11e7-bb30-233be9be6a20');
|
||||
|
||||
await (await flyout.findByTestSubject('pagination-button-next')).click();
|
||||
|
||||
const selectedIdForMissingIndexPattern7 = await testSubjects.getAttribute(
|
||||
'managementChangeIndexSelection-missing-index-pattern-7',
|
||||
'value'
|
||||
);
|
||||
|
||||
expect(selectedIdForMissingIndexPattern7).to.eql('f1e4c910-a2e6-11e7-bb30-233be9be6a87');
|
||||
});
|
||||
|
||||
it('should display an explicit error message when importing object from a higher Kibana version', async () => {
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_higher_version.ndjson')
|
||||
);
|
||||
|
||||
await PageObjects.savedObjects.checkImportError();
|
||||
|
||||
const errorText = await PageObjects.savedObjects.getImportErrorText();
|
||||
|
||||
expect(errorText).to.contain(
|
||||
`has property "visualization" which belongs to a more recent version of Kibana [9.15.82]`
|
||||
);
|
||||
});
|
||||
|
||||
describe('when bigger than savedObjects.maxImportPayloadBytes (not Cloud)', function () {
|
||||
// see --savedObjects.maxImportPayloadBytes in config file
|
||||
this.tags(['skipCloud']);
|
||||
it('should display an explicit error message when importing a file bigger than allowed', async () => {
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_too_big.ndjson')
|
||||
);
|
||||
|
||||
await PageObjects.savedObjects.checkImportError();
|
||||
|
||||
const errorText = await PageObjects.savedObjects.getImportErrorText();
|
||||
|
||||
expect(errorText).to.contain(`Payload content length greater than maximum allowed`);
|
||||
});
|
||||
});
|
||||
|
||||
it('should display an explicit error message when importing an invalid file', async () => {
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', '_import_invalid_format.ndjson')
|
||||
);
|
||||
|
||||
await PageObjects.savedObjects.checkImportError();
|
||||
|
||||
const errorText = await PageObjects.savedObjects.getImportErrorText();
|
||||
|
||||
expect(errorText).to.contain(`Unexpected token T in JSON at position 0`);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
it('should import saved objects mgmt', async function () {
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
await PageObjects.savedObjects.importFile(
|
||||
path.join(__dirname, 'exports', 'mgmt_import_objects.json')
|
||||
path.join(__dirname, 'exports', 'mgmt_import_objects.ndjson')
|
||||
);
|
||||
await PageObjects.settings.associateIndexPattern(
|
||||
'4c3f3c30-ac94-11e8-a651-614b2788174a',
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,19 +0,0 @@
|
|||
[
|
||||
{
|
||||
"_id": "082f1d60-a2e7-11e7-bb30-233be9be6a15",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Log Agents",
|
||||
"visState": "{\"title\":\"Log Agents\",\"type\":\"area\",\"params\":{\"type\":\"area\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{\"text\":\"agent.raw: Descending\"}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"area\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"agent.raw\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\"}}]}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"f1e4c910-a2e6-11e7-bb30-233be9be6a15\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,20 +0,0 @@
|
|||
[
|
||||
{
|
||||
"_id": "saved_object_connected_to_saved_search",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "saved object connected to saved search",
|
||||
"visState": "{\"title\":\"PHP Viz\",\"type\":\"horizontal_bar\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":200},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":75,\"filter\":true,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"histogram\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"savedSearchId": "c45e6c50-ba72-11e7-a8f9-ad70f02e633d",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,19 +0,0 @@
|
|||
[
|
||||
{
|
||||
"_id": "Shared-Item-Visualization-AreaChart",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Shared-Item Visualization AreaChart",
|
||||
"visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "AreaChart",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,121 +0,0 @@
|
|||
[
|
||||
{
|
||||
"_id": "test-vis-1",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Test VIS 1",
|
||||
"visState": "{\"title\":\"test vis 1\",\"type\":\"histogram\"}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"missing-index-pattern-1\",\"query\":{}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "test-vis-2",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Test VIS 2",
|
||||
"visState": "{\"title\":\"test vis 2\",\"type\":\"histogram\"}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"missing-index-pattern-2\",\"query\":{}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "test-vis-3",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Test VIS 3",
|
||||
"visState": "{\"title\":\"test vis 3\",\"type\":\"histogram\"}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"missing-index-pattern-3\",\"query\":{}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "test-vis-4",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Test VIS 4",
|
||||
"visState": "{\"title\":\"test vis 4\",\"type\":\"histogram\"}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"missing-index-pattern-4\",\"query\":{}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "test-vis-5",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Test VIS 5",
|
||||
"visState": "{\"title\":\"test vis 5\",\"type\":\"histogram\"}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"missing-index-pattern-5\",\"query\":{}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "test-vis-6",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Test VIS 6",
|
||||
"visState": "{\"title\":\"test vis 6\",\"type\":\"histogram\"}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"missing-index-pattern-6\",\"query\":{}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "test-vis-7",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Test VIS 7",
|
||||
"visState": "{\"title\":\"test vis 7\",\"type\":\"histogram\"}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"missing-index-pattern-7\",\"query\":{}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,36 +0,0 @@
|
|||
[
|
||||
{
|
||||
"_id": "test-1",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Visualization test 1",
|
||||
"visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "AreaChart",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "test-2",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Visualization test 2",
|
||||
"visState": "{\"title\":\"New Visualization\",\"type\":\"area\",\"params\":{\"shareYAxis\":true,\"addTooltip\":true,\"addLegend\":true,\"smoothLines\":false,\"scale\":\"linear\",\"interpolate\":\"linear\",\"mode\":\"stacked\",\"times\":[],\"addTimeMarker\":false,\"defaultYExtents\":false,\"setYExtents\":false,\"yAxis\":{}},\"aggs\":[{\"id\":\"1\",\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}],\"listeners\":{}}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "AreaChart",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"logstash-*\",\"query\":{\"query_string\":{\"query\":\"*\",\"analyze_wildcard\":true}},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
}
|
||||
]
|
|
@ -1,25 +0,0 @@
|
|||
[
|
||||
{
|
||||
"_id": "c45e6c50-ba72-11e7-a8f9-ad70f02e633d",
|
||||
"_type": "search",
|
||||
"_source": {
|
||||
"title": "PHP saved search",
|
||||
"description": "",
|
||||
"hits": 0,
|
||||
"columns": [
|
||||
"_source"
|
||||
],
|
||||
"sort": [
|
||||
"@timestamp",
|
||||
"desc"
|
||||
],
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"f1e4c910-a2e6-11e7-bb30-233be9be6a15\",\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"php\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
}
|
||||
]
|
File diff suppressed because one or more lines are too long
|
@ -1,37 +0,0 @@
|
|||
[
|
||||
{
|
||||
"_id": "6aea5700-ac94-11e8-a651-614b2788174a",
|
||||
"_type": "search",
|
||||
"_source": {
|
||||
"title": "mysavedsearch",
|
||||
"description": "",
|
||||
"hits": 0,
|
||||
"columns": [
|
||||
"_source"
|
||||
],
|
||||
"sort": [
|
||||
"@timestamp",
|
||||
"desc"
|
||||
],
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"4c3f3c30-ac94-11e8-a651-614b2788174a\",\"highlightAll\":true,\"version\":true,\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "8411daa0-ac94-11e8-a651-614b2788174a",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "mysavedviz",
|
||||
"visState": "{\"title\":\"mysavedviz\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":true,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}}]}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"savedSearchId": "6aea5700-ac94-11e8-a651-614b2788174a",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
|
@ -3302,32 +3302,17 @@
|
|||
"savedObjectsManagement.objectsTable.exportObjectsConfirmModal.exportOptionsLabel": "オプション",
|
||||
"savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel": "関連オブジェクトを含める",
|
||||
"savedObjectsManagement.objectsTable.exportObjectsConfirmModalDescription": "エクスポートするタイプを選択してください",
|
||||
"savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage": "矛盾を解決中…",
|
||||
"savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage": "失敗したオブジェクトを再試行中…",
|
||||
"savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage": "保存された検索が正しくリンクされていることを確認してください…",
|
||||
"savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage": "矛盾を保存中…",
|
||||
"savedObjectsManagement.objectsTable.flyout.errorCalloutTitle": "申し訳ございません、エラーが発生しました",
|
||||
"savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel": "キャンセル",
|
||||
"savedObjectsManagement.objectsTable.flyout.import.confirmButtonLabel": "インポート",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFailedDescription": "{totalImportCount}個中{failedImportCount}個のオブジェクトのインポートに失敗しました。インポート失敗",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFailedMissingReference": "{type} [id={id}]は{refType} [id={refId}]を見つけられませんでした",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFailedTitle": "インポート失敗",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFailedUnsupportedType": "{type} [id={id}]サポートされていないタイプ",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFileErrorMessage": "エラーのためファイルを処理できませんでした:「{error}」",
|
||||
"savedObjectsManagement.objectsTable.flyout.importLegacyFileErrorMessage": "ファイルを処理できませんでした。",
|
||||
"savedObjectsManagement.objectsTable.flyout.importPromptText": "インポート",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle": "保存されたオブジェクトのインポート",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel": "すべての変更を確定",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmButtonLabel": "完了",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle": "オブジェクトがインポートされませんでした",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessfulDescription": "{importCount}個のオブジェクトがインポートされました。",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessfulTitle": "インポート成功",
|
||||
"savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText": "新規インデックスパターンを作成",
|
||||
"savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription": "次の保存されたオブジェクトは、存在しないインデックスパターンを使用しています。関連付け直す別のインデックスパターンを選択してください。必要に応じて、{indexPatternLink}できます。",
|
||||
"savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle": "インデックスパターンの矛盾",
|
||||
"savedObjectsManagement.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage": "保存されたオブジェクトのファイル形式が無効なため、インポートできません。",
|
||||
"savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody": "最新のレポートでNDJSONファイルを作成すれば完了です。",
|
||||
"savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle": "JSONファイルのサポートが終了します",
|
||||
"savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountDescription": "影響されるオブジェクトの数です",
|
||||
"savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountName": "カウント",
|
||||
"savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdDescription": "インデックスパターンのIDです",
|
||||
|
|
|
@ -3320,32 +3320,17 @@
|
|||
"savedObjectsManagement.objectsTable.exportObjectsConfirmModal.includeReferencesDeepLabel": "包括相关对象",
|
||||
"savedObjectsManagement.objectsTable.exportObjectsConfirmModalDescription": "选择要导出的类型",
|
||||
"savedObjectsManagement.objectsTable.exportObjectsConfirmModalTitle": "导出 {filteredItemCount, plural, other {# 个对象}}",
|
||||
"savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.resolvingConflictsLoadingMessage": "正在解决冲突……",
|
||||
"savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.retryingFailedObjectsLoadingMessage": "正在重试失败的对象……",
|
||||
"savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savedSearchAreLinkedProperlyLoadingMessage": "确保已保存搜索已正确链接……",
|
||||
"savedObjectsManagement.objectsTable.flyout.confirmLegacyImport.savingConflictsLoadingMessage": "正在保存冲突……",
|
||||
"savedObjectsManagement.objectsTable.flyout.errorCalloutTitle": "抱歉,有错误",
|
||||
"savedObjectsManagement.objectsTable.flyout.import.cancelButtonLabel": "取消",
|
||||
"savedObjectsManagement.objectsTable.flyout.import.confirmButtonLabel": "导入",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFailedDescription": "{totalImportCount} 个对象中有 {failedImportCount} 个无法导入。导入失败",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFailedMissingReference": "{type} [id={id}] 无法找到 {refType} [id={refId}]",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFailedTitle": "导入失败",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFailedUnsupportedType": "{type} [id={id}] 不受支持的类型",
|
||||
"savedObjectsManagement.objectsTable.flyout.importFileErrorMessage": "由于以下错误,无法处理文件:“{error}”",
|
||||
"savedObjectsManagement.objectsTable.flyout.importLegacyFileErrorMessage": "无法处理该文件。",
|
||||
"savedObjectsManagement.objectsTable.flyout.importPromptText": "导入",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSavedObjectTitle": "导入已保存对象",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmAllChangesButtonLabel": "确认所有更改",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessful.confirmButtonLabel": "完成",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessfulCallout.noObjectsImportedTitle": "未导入任何对象",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessfulDescription": "已成功导入 {importCount} 个对象。",
|
||||
"savedObjectsManagement.objectsTable.flyout.importSuccessfulTitle": "导入成功",
|
||||
"savedObjectsManagement.objectsTable.flyout.indexPatternConflictsCalloutLinkText": "创建新的索引模式",
|
||||
"savedObjectsManagement.objectsTable.flyout.indexPatternConflictsDescription": "以下已保存对象使用不存在的索引模式。请选择要重新关联的索引模式。必要时可以{indexPatternLink}。",
|
||||
"savedObjectsManagement.objectsTable.flyout.indexPatternConflictsTitle": "索引模式冲突",
|
||||
"savedObjectsManagement.objectsTable.flyout.invalidFormatOfImportedFileErrorMessage": "已保存对象文件格式无效,无法导入。",
|
||||
"savedObjectsManagement.objectsTable.flyout.legacyFileUsedBody": "只需使用更新的导出功能生成 NDJSON 文件,便万事俱备。",
|
||||
"savedObjectsManagement.objectsTable.flyout.legacyFileUsedTitle": "将不再支持 JSON 文件",
|
||||
"savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountDescription": "受影响对象数目",
|
||||
"savedObjectsManagement.objectsTable.flyout.renderConflicts.columnCountName": "计数",
|
||||
"savedObjectsManagement.objectsTable.flyout.renderConflicts.columnIdDescription": "索引模式的 ID",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue