mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
This commit is contained in:
parent
cbe69ab156
commit
0a0ca43fc4
14 changed files with 763 additions and 58 deletions
|
@ -11,6 +11,7 @@
|
|||
<div class="kuiBarSection">
|
||||
<button
|
||||
class="kuiButton kuiButton--basic kuiButton--iconText"
|
||||
data-test-subj="exportAllObjects"
|
||||
ng-click="exportAll()"
|
||||
>
|
||||
<span class="kuiButton__inner">
|
||||
|
@ -49,6 +50,7 @@
|
|||
ng-class="{ 'kuiTab-isSelected': state.tab === service.title }"
|
||||
ng-repeat="service in services"
|
||||
ng-click="changeTab(service)"
|
||||
data-test-subj="objectsTab-{{ service.title }}"
|
||||
>
|
||||
{{ service.title }}
|
||||
<small aria-label="{{:: service.data.length + ' of ' + service.total + ' ' + service.title }}">
|
||||
|
@ -126,7 +128,7 @@
|
|||
</div>
|
||||
|
||||
<!-- Table -->
|
||||
<table class="kuiTable" ng-if="service.data.length">
|
||||
<table class="kuiTable" ng-if="service.data.length" data-test-subj="objectsTable-{{service.title}}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="kuiTableHeaderCell kuiTableHeaderCell--checkBox">
|
||||
|
@ -148,6 +150,7 @@
|
|||
<tr
|
||||
ng-repeat="item in service.data | orderBy:'title'"
|
||||
class="kuiTableRow"
|
||||
data-test-subj="objectsTableRow"
|
||||
>
|
||||
<td class="kuiTableRowCell kuiTableRowCell--checkBox">
|
||||
<div class="kuiTableRowCell__liner">
|
||||
|
|
|
@ -7,10 +7,25 @@ import 'ui/directives/file_upload';
|
|||
import uiRoutes from 'ui/routes';
|
||||
import { SavedObjectsClientProvider } from 'ui/saved_objects';
|
||||
import { uiModules } from 'ui/modules';
|
||||
import { showChangeIndexModal } from './show_change_index_modal';
|
||||
import { SavedObjectNotFound } from 'ui/errors';
|
||||
|
||||
const indexPatternsResolutions = {
|
||||
indexPatterns: function (Private) {
|
||||
const savedObjectsClient = Private(SavedObjectsClientProvider);
|
||||
|
||||
return savedObjectsClient.find({
|
||||
type: 'index-pattern',
|
||||
fields: ['title'],
|
||||
perPage: 10000
|
||||
}).then(response => response.savedObjects);
|
||||
}
|
||||
};
|
||||
|
||||
uiRoutes
|
||||
.when('/management/kibana/objects', {
|
||||
template: objectIndexHTML
|
||||
template: objectIndexHTML,
|
||||
resolve: indexPatternsResolutions
|
||||
});
|
||||
|
||||
uiRoutes
|
||||
|
@ -19,7 +34,7 @@ uiRoutes
|
|||
});
|
||||
|
||||
uiModules.get('apps/management')
|
||||
.directive('kbnManagementObjects', function (kbnIndex, Notifier, Private, kbnUrl, Promise, confirmModal) {
|
||||
.directive('kbnManagementObjects', function ($route, kbnIndex, Notifier, Private, kbnUrl, Promise, confirmModal) {
|
||||
const savedObjectsClient = Private(SavedObjectsClientProvider);
|
||||
|
||||
return {
|
||||
|
@ -188,61 +203,92 @@ uiModules.get('apps/management')
|
|||
}
|
||||
);
|
||||
})
|
||||
.then((overwriteAll) => {
|
||||
function importDocument(doc) {
|
||||
const { service } = find($scope.services, { type: doc._type }) || {};
|
||||
.then((overwriteAll) => {
|
||||
const conflictedIndexPatterns = [];
|
||||
|
||||
if (!service) {
|
||||
const msg = `Skipped import of "${doc._source.title}" (${doc._id})`;
|
||||
const reason = `Invalid type: "${doc._type}"`;
|
||||
function importDocument(doc) {
|
||||
const { service } = find($scope.services, { type: doc._type }) || {};
|
||||
|
||||
notify.warning(`${msg}, ${reason}`, {
|
||||
lifetime: 0,
|
||||
});
|
||||
if (!service) {
|
||||
const msg = `Skipped import of "${doc._source.title}" (${doc._id})`;
|
||||
const reason = `Invalid type: "${doc._type}"`;
|
||||
|
||||
return;
|
||||
notify.warning(`${msg}, ${reason}`, {
|
||||
lifetime: 0,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return service.get()
|
||||
.then(function (obj) {
|
||||
obj.id = doc._id;
|
||||
return obj.applyESResp(doc)
|
||||
.then(() => {
|
||||
return obj.save({ confirmOverwrite : !overwriteAll });
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err instanceof SavedObjectNotFound && err.savedObjectType === 'index-pattern') {
|
||||
conflictedIndexPatterns.push({ obj, doc });
|
||||
return;
|
||||
}
|
||||
|
||||
// swallow errors here so that the remaining promise chain executes
|
||||
err.message = `Importing ${obj.title} (${obj.id}) failed: ${err.message}`;
|
||||
notify.error(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function groupByType(docs) {
|
||||
const defaultDocTypes = {
|
||||
searches: [],
|
||||
other: [],
|
||||
};
|
||||
|
||||
return docs.reduce((types, doc) => {
|
||||
switch (doc._type) {
|
||||
case 'search':
|
||||
types.searches.push(doc);
|
||||
break;
|
||||
default:
|
||||
types.other.push(doc);
|
||||
}
|
||||
return types;
|
||||
}, defaultDocTypes);
|
||||
}
|
||||
|
||||
return service.get()
|
||||
.then(function (obj) {
|
||||
obj.id = doc._id;
|
||||
return obj.applyESResp(doc)
|
||||
.then(() => {
|
||||
return obj.save({ confirmOverwrite : !overwriteAll });
|
||||
})
|
||||
.catch((err) => {
|
||||
// swallow errors here so that the remaining promise chain executes
|
||||
err.message = `Importing ${obj.title} (${obj.id}) failed: ${err.message}`;
|
||||
notify.error(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
const docTypes = groupByType(docs);
|
||||
|
||||
function groupByType(docs) {
|
||||
const defaultDocTypes = {
|
||||
searches: [],
|
||||
other: [],
|
||||
};
|
||||
|
||||
return docs.reduce((types, doc) => {
|
||||
switch (doc._type) {
|
||||
case 'search':
|
||||
types.searches.push(doc);
|
||||
break;
|
||||
default:
|
||||
types.other.push(doc);
|
||||
}
|
||||
return types;
|
||||
}, defaultDocTypes);
|
||||
}
|
||||
|
||||
const docTypes = groupByType(docs);
|
||||
|
||||
return Promise.map(docTypes.searches, importDocument)
|
||||
.then(() => Promise.map(docTypes.other, importDocument))
|
||||
.then(refreshData)
|
||||
.catch(notify.error);
|
||||
});
|
||||
return Promise.map(docTypes.searches, importDocument)
|
||||
.then(() => Promise.map(docTypes.other, importDocument))
|
||||
.then(() => {
|
||||
if (conflictedIndexPatterns.length) {
|
||||
showChangeIndexModal(
|
||||
(objs) => {
|
||||
return Promise.map(
|
||||
conflictedIndexPatterns,
|
||||
({ obj }) => {
|
||||
const oldIndexId = obj.searchSource.getOwn('index');
|
||||
const newIndexId = objs.find(({ oldId }) => oldId === oldIndexId).newId;
|
||||
if (newIndexId === oldIndexId) {
|
||||
// Skip
|
||||
return;
|
||||
}
|
||||
return obj.hydrateIndexPattern(newIndexId)
|
||||
.then(() => obj.save({ confirmOverwrite : !overwriteAll }));
|
||||
}
|
||||
).then(refreshData);
|
||||
},
|
||||
conflictedIndexPatterns,
|
||||
$route.current.locals.indexPatterns,
|
||||
);
|
||||
} else {
|
||||
return refreshData();
|
||||
}
|
||||
})
|
||||
.catch(notify.error);
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: Migrate all scope methods to the controller.
|
||||
|
|
|
@ -0,0 +1,215 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { groupBy, mapValues, take, get } from 'lodash';
|
||||
|
||||
import {
|
||||
KuiModal,
|
||||
KuiModalHeader,
|
||||
KuiModalHeaderTitle,
|
||||
KuiModalBody,
|
||||
KuiModalBodyText,
|
||||
KuiModalFooter,
|
||||
KuiButton,
|
||||
KuiModalOverlay,
|
||||
KuiTable,
|
||||
KuiTableBody,
|
||||
KuiTableHeader,
|
||||
KuiTableHeaderCell,
|
||||
KuiTableRow,
|
||||
KuiTableRowCell,
|
||||
KuiControlledTable,
|
||||
KuiToolBar,
|
||||
KuiToolBarSection,
|
||||
KuiPager,
|
||||
} from 'ui_framework/components';
|
||||
|
||||
import { ESC_KEY_CODE } from 'ui_framework/services';
|
||||
|
||||
export class ChangeIndexModal extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const byId = groupBy(props.conflictedObjects, ({ obj }) => obj.searchSource.getOwn('index'));
|
||||
this.state = {
|
||||
page: 0,
|
||||
perPage: 10,
|
||||
objects: mapValues(byId, (list, indexPatternId) => {
|
||||
return {
|
||||
newIndexPatternId: get(props, 'indices[0].id'),
|
||||
list: list.map(({ doc }) => {
|
||||
return {
|
||||
id: indexPatternId,
|
||||
type: doc._type,
|
||||
name: doc._source.title,
|
||||
};
|
||||
})
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
changeIndex = () => {
|
||||
const result = Object.keys(this.state.objects).map(indexPatternId => ({
|
||||
oldId: indexPatternId,
|
||||
newId: this.state.objects[indexPatternId].newIndexPatternId,
|
||||
}));
|
||||
this.props.onChange(result);
|
||||
};
|
||||
|
||||
onIndexChange = (id, event) => {
|
||||
event.persist();
|
||||
this.setState(state => {
|
||||
return {
|
||||
objects: {
|
||||
...state.objects,
|
||||
[id]: {
|
||||
...state.objects[id],
|
||||
newIndexPatternId: event.target.value,
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
onKeyDown = (event) => {
|
||||
if (event.keyCode === ESC_KEY_CODE) {
|
||||
this.props.onClose();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { page, perPage } = this.state;
|
||||
const totalIndexPatterns = Object.keys(this.state.objects).length;
|
||||
const indexPatternIds = Object.keys(this.state.objects).slice(page, page + perPage);
|
||||
const rows = indexPatternIds.map((indexPatternId, key) => {
|
||||
const objects = this.state.objects[indexPatternId].list;
|
||||
const sample = take(objects, 5).map((obj, key) => <span key={key}>{obj.name}<br/></span>);
|
||||
|
||||
return (
|
||||
<KuiTableRow key={key}>
|
||||
<KuiTableRowCell>
|
||||
{indexPatternId}
|
||||
</KuiTableRowCell>
|
||||
<KuiTableRowCell>
|
||||
{objects.length}
|
||||
</KuiTableRowCell>
|
||||
<KuiTableRowCell>
|
||||
{sample}
|
||||
</KuiTableRowCell>
|
||||
<KuiTableRowCell>
|
||||
<select
|
||||
className="kuiSelect kuiSelect--medium"
|
||||
data-test-subj="managementChangeIndexSelection"
|
||||
value={this.state.objects[indexPatternId].newIndexPatternId}
|
||||
onChange={this.onIndexChange.bind(this, indexPatternId)}
|
||||
>
|
||||
<option value={indexPatternId}>Skip import</option>
|
||||
{this.props.indices.map((index, i) => {
|
||||
return (
|
||||
<option key={i} value={index.id}>
|
||||
{index.get('title')}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</select>
|
||||
</KuiTableRowCell>
|
||||
</KuiTableRow>
|
||||
);
|
||||
});
|
||||
|
||||
const TableComponent = () => (
|
||||
<KuiTable className="kuiVerticalRhythm">
|
||||
<KuiTableHeader>
|
||||
<KuiTableHeaderCell width="300">
|
||||
ID
|
||||
</KuiTableHeaderCell>
|
||||
<KuiTableHeaderCell width="50">
|
||||
Count
|
||||
</KuiTableHeaderCell>
|
||||
<KuiTableHeaderCell>
|
||||
Sample of affected objects
|
||||
</KuiTableHeaderCell>
|
||||
<KuiTableHeaderCell width="200">
|
||||
New index pattern
|
||||
</KuiTableHeaderCell>
|
||||
</KuiTableHeader>
|
||||
<KuiTableBody>
|
||||
{rows}
|
||||
</KuiTableBody>
|
||||
</KuiTable>
|
||||
);
|
||||
|
||||
return (
|
||||
<KuiModalOverlay>
|
||||
<KuiModal
|
||||
data-tests-subj="managementChangeIndexModal"
|
||||
aria-label="Index does not exist"
|
||||
className="managementChangeIndexModal"
|
||||
onKeyDown={this.onKeyDown}
|
||||
>
|
||||
<KuiModalHeader>
|
||||
<KuiModalHeaderTitle>
|
||||
Index Pattern Conflicts
|
||||
</KuiModalHeaderTitle>
|
||||
</KuiModalHeader>
|
||||
<KuiModalBody>
|
||||
<KuiModalBodyText>
|
||||
<p>
|
||||
The following saved objects use index patterns that do not exist.
|
||||
Please select the index patterns you'd like re-associated them with.
|
||||
</p>
|
||||
</KuiModalBodyText>
|
||||
{ totalIndexPatterns > perPage
|
||||
?
|
||||
<KuiControlledTable>
|
||||
<KuiToolBar>
|
||||
<KuiToolBarSection>
|
||||
<KuiPager
|
||||
startNumber={page + 1}
|
||||
hasPreviousPage={page >= 1}
|
||||
hasNextPage={page < totalIndexPatterns}
|
||||
endNumber={Math.min(totalIndexPatterns, page + perPage)}
|
||||
totalItems={totalIndexPatterns}
|
||||
onNextPage={() => this.setState({ page: page + 1 })}
|
||||
onPreviousPage={() => this.setState({ page: page - 1 })}
|
||||
/>
|
||||
</KuiToolBarSection>
|
||||
</KuiToolBar>
|
||||
<TableComponent/>
|
||||
</KuiControlledTable>
|
||||
:
|
||||
<TableComponent/>
|
||||
}
|
||||
</KuiModalBody>
|
||||
|
||||
<KuiModalFooter>
|
||||
<KuiButton
|
||||
buttonType="hollow"
|
||||
data-test-subj="changeIndexCancelButton"
|
||||
onClick={this.props.onClose}
|
||||
>
|
||||
Cancel
|
||||
</KuiButton>
|
||||
<KuiButton
|
||||
buttonType="primary"
|
||||
data-test-subj="changeIndexConfirmButton"
|
||||
onClick={this.changeIndex}
|
||||
>
|
||||
Confirm all changes
|
||||
</KuiButton>
|
||||
</KuiModalFooter>
|
||||
</KuiModal>
|
||||
</KuiModalOverlay>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChangeIndexModal.propTypes = {
|
||||
onChange: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
conflictedObjects: PropTypes.arrayOf(PropTypes.shape({
|
||||
obj: PropTypes.object.isRequired,
|
||||
doc: PropTypes.object.isRequired,
|
||||
})).isRequired,
|
||||
indices: PropTypes.array
|
||||
};
|
|
@ -0,0 +1,28 @@
|
|||
import { ChangeIndexModal } from './change_index_modal';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
export function showChangeIndexModal(onChange, conflictedObjects, indices = []) {
|
||||
const container = document.createElement('div');
|
||||
const closeModal = () => {
|
||||
document.body.removeChild(container);
|
||||
};
|
||||
|
||||
const onIndexChangeConfirmed = (newIndex) => {
|
||||
onChange(newIndex);
|
||||
closeModal();
|
||||
};
|
||||
|
||||
document.body.appendChild(container);
|
||||
|
||||
const element = (
|
||||
<ChangeIndexModal
|
||||
onChange={onIndexChangeConfirmed}
|
||||
onClose={closeModal}
|
||||
conflictedObjects={conflictedObjects}
|
||||
indices={indices}
|
||||
/>
|
||||
);
|
||||
|
||||
ReactDOM.render(element, container);
|
||||
}
|
|
@ -125,6 +125,10 @@ kbn-management-objects {
|
|||
}
|
||||
}
|
||||
|
||||
.managementChangeIndexModal {
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
kbn-management-advanced {
|
||||
// super specific rule to override bootstrap's equally specific rule
|
||||
// https://github.com/twbs/bootstrap/blob/1f329f8f17aa989eabc6e94bdcab93e69ef0e463/less/tables.less#L35
|
||||
|
|
|
@ -118,7 +118,7 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm
|
|||
*
|
||||
* @return {Promise<IndexPattern | null>}
|
||||
*/
|
||||
const hydrateIndexPattern = () => {
|
||||
this.hydrateIndexPattern = (id) => {
|
||||
if (!this.searchSource) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm
|
|||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
let index = config.indexPattern || this.searchSource.getOwn('index');
|
||||
let index = id || config.indexPattern || this.searchSource.getOwn('index');
|
||||
|
||||
if (!index) {
|
||||
return Promise.resolve(null);
|
||||
|
@ -163,7 +163,7 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm
|
|||
if (!this.id) {
|
||||
// just assign the defaults and be done
|
||||
_.assign(this, this.defaults);
|
||||
return hydrateIndexPattern().then(() => {
|
||||
return this.hydrateIndexPattern().then(() => {
|
||||
return afterESResp.call(this);
|
||||
});
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm
|
|||
|
||||
return Promise.try(() => {
|
||||
parseSearchSource(meta.searchSourceJSON);
|
||||
return hydrateIndexPattern();
|
||||
return this.hydrateIndexPattern();
|
||||
}).then(() => {
|
||||
return Promise.cast(afterESResp.call(this, resp));
|
||||
});
|
||||
|
|
93
test/functional/apps/management/_import_objects.js
Normal file
93
test/functional/apps/management/_import_objects.js
Normal file
|
@ -0,0 +1,93 @@
|
|||
import expect from 'expect.js';
|
||||
import path from 'path';
|
||||
|
||||
export default function ({ getService, getPageObjects }) {
|
||||
const retry = getService('retry');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const PageObjects = getPageObjects(['common', 'settings']);
|
||||
|
||||
describe('import objects', function describeIndexTests() {
|
||||
before(async function () {
|
||||
// delete .kibana index and then wait for Kibana to re-create it
|
||||
await kibanaServer.uiSettings.replace({});
|
||||
await PageObjects.settings.navigateTo();
|
||||
await esArchiver.load('management');
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await esArchiver.unload('management');
|
||||
});
|
||||
|
||||
it('should import saved objects normally', async function () {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects.json'));
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
await PageObjects.settings.clickVisualizationsTab();
|
||||
const rowCount = await retry.try(async () => {
|
||||
const rows = await PageObjects.settings.getVisualizationRows();
|
||||
if (rows.length !== 2) {
|
||||
throw 'Not loaded yet';
|
||||
}
|
||||
return rows.length;
|
||||
});
|
||||
expect(rowCount).to.be(2);
|
||||
});
|
||||
|
||||
it('should import conflicts using a confirm modal', async function () {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects-conflicts.json'));
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
await PageObjects.settings.setImportIndexFieldOption(2);
|
||||
await PageObjects.settings.clickChangeIndexConfirmButton();
|
||||
await PageObjects.settings.clickVisualizationsTab();
|
||||
const rowCount = await retry.try(async () => {
|
||||
const rows = await PageObjects.settings.getVisualizationRows();
|
||||
if (rows.length !== 2) {
|
||||
throw 'Not loaded yet';
|
||||
}
|
||||
return rows.length;
|
||||
});
|
||||
expect(rowCount).to.be(2);
|
||||
});
|
||||
|
||||
it('should allow for overrides', async function () {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects.json'));
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects.json'));
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
await PageObjects.settings.clickVisualizationsTab();
|
||||
const rowCount = await retry.try(async () => {
|
||||
const rows = await PageObjects.settings.getVisualizationRows();
|
||||
if (rows.length !== 2) {
|
||||
throw 'Not loaded yet';
|
||||
}
|
||||
return rows.length;
|
||||
});
|
||||
expect(rowCount).to.be(2);
|
||||
});
|
||||
|
||||
it('should allow for cancelling overrides', async function () {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaSavedObjects();
|
||||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects.json'));
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
await PageObjects.settings.importFile(path.join(__dirname, 'exports', '_import_objects.json'));
|
||||
await PageObjects.common.clickCancelOnModal(true);
|
||||
await PageObjects.common.clickConfirmOnModal();
|
||||
await PageObjects.settings.clickVisualizationsTab();
|
||||
const rowCount = await retry.try(async () => {
|
||||
const rows = await PageObjects.settings.getVisualizationRows();
|
||||
if (rows.length !== 2) {
|
||||
throw 'Not loaded yet';
|
||||
}
|
||||
return rows.length;
|
||||
});
|
||||
expect(rowCount).to.be(2);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
{
|
||||
"_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\":\"d1e4c910-a2e6-11e7-bb30-233be9be6a15\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
}
|
||||
]
|
19
test/functional/apps/management/exports/_import_objects.json
Normal file
19
test/functional/apps/management/exports/_import_objects.json
Normal file
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
{
|
||||
"_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
|
||||
}
|
||||
}
|
||||
]
|
|
@ -24,6 +24,7 @@ export default function ({ getService, loadTestFile }) {
|
|||
loadTestFile(require.resolve('./_scripted_fields'));
|
||||
loadTestFile(require.resolve('./_index_pattern_filter'));
|
||||
loadTestFile(require.resolve('./_scripted_fields_filter'));
|
||||
loadTestFile(require.resolve('./_import_objects'));
|
||||
});
|
||||
|
||||
}
|
||||
|
|
BIN
test/functional/fixtures/es_archiver/management/data.json.gz
Normal file
BIN
test/functional/fixtures/es_archiver/management/data.json.gz
Normal file
Binary file not shown.
246
test/functional/fixtures/es_archiver/management/mappings.json
Normal file
246
test/functional/fixtures/es_archiver/management/mappings.json
Normal file
|
@ -0,0 +1,246 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"index": ".kibana",
|
||||
"settings": {
|
||||
"index": {
|
||||
"number_of_shards": "1",
|
||||
"number_of_replicas": "1"
|
||||
}
|
||||
},
|
||||
"mappings": {
|
||||
"doc": {
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"server": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"uuid": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"accessCount": {
|
||||
"type": "long"
|
||||
},
|
||||
"accessDate": {
|
||||
"type": "date"
|
||||
},
|
||||
"createDate": {
|
||||
"type": "date"
|
||||
},
|
||||
"url": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 2048
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"columns": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sort": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualization": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"savedSearchId": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"uiStateJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
},
|
||||
"visState": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"index-pattern": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"fieldFormatMap": {
|
||||
"type": "text"
|
||||
},
|
||||
"fields": {
|
||||
"type": "text"
|
||||
},
|
||||
"intervalName": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"notExpandable": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"sourceFilters": {
|
||||
"type": "text"
|
||||
},
|
||||
"timeFieldName": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"dynamic": "true",
|
||||
"properties": {
|
||||
"buildNum": {
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dashboard": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"optionsJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"panelsJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"refreshInterval": {
|
||||
"properties": {
|
||||
"display": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"pause": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"section": {
|
||||
"type": "integer"
|
||||
},
|
||||
"value": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeFrom": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timeRestore": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"timeTo": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"uiStateJSON": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timelion-sheet": {
|
||||
"dynamic": "strict",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "text"
|
||||
},
|
||||
"hits": {
|
||||
"type": "integer"
|
||||
},
|
||||
"kibanaSavedObjectMeta": {
|
||||
"properties": {
|
||||
"searchSourceJSON": {
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timelion_chart_height": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_columns": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_interval": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timelion_other_interval": {
|
||||
"type": "keyword"
|
||||
},
|
||||
"timelion_rows": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timelion_sheet": {
|
||||
"type": "text"
|
||||
},
|
||||
"title": {
|
||||
"type": "text"
|
||||
},
|
||||
"version": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -230,10 +230,14 @@ export function CommonPageProvider({ getService, getPageObjects }) {
|
|||
await remote.pressKeys('\uE007');
|
||||
}
|
||||
|
||||
async clickCancelOnModal() {
|
||||
// pass in true if your test will show multiple modals
|
||||
// in succession
|
||||
async clickCancelOnModal(overlayWillStay = false) {
|
||||
log.debug('Clicking modal cancel');
|
||||
await testSubjects.click('confirmModalCancelButton');
|
||||
await this.ensureModalOverlayHidden();
|
||||
if (!overlayWillStay) {
|
||||
await this.ensureModalOverlayHidden();
|
||||
}
|
||||
}
|
||||
|
||||
async isConfirmModalOpen() {
|
||||
|
|
|
@ -27,6 +27,10 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
|
|||
await this.clickLinkText('Advanced Settings');
|
||||
}
|
||||
|
||||
async clickKibanaSavedObjects() {
|
||||
await this.clickLinkText('Saved Objects');
|
||||
}
|
||||
|
||||
async clickKibanaIndices() {
|
||||
log.debug('clickKibanaIndices link');
|
||||
await this.clickLinkText('Index Patterns');
|
||||
|
@ -484,6 +488,29 @@ export function SettingsPageProvider({ getService, getPageObjects }) {
|
|||
log.debug('set scripted field script = ' + script);
|
||||
await testSubjects.setValue('editorFieldScript', script);
|
||||
}
|
||||
|
||||
async importFile(path) {
|
||||
log.debug(`importFile(${path})`);
|
||||
await remote.findById('testfile').type(path);
|
||||
}
|
||||
|
||||
async setImportIndexFieldOption(child) {
|
||||
await remote.setFindTimeout(defaultFindTimeout)
|
||||
.findByCssSelector(`select[data-test-subj="managementChangeIndexSelection"] > option:nth-child(${child})`)
|
||||
.click();
|
||||
}
|
||||
|
||||
async clickChangeIndexConfirmButton() {
|
||||
await (await testSubjects.find('changeIndexConfirmButton')).click();
|
||||
}
|
||||
|
||||
async clickVisualizationsTab() {
|
||||
await (await testSubjects.find('objectsTab-visualizations')).click();
|
||||
}
|
||||
|
||||
async getVisualizationRows() {
|
||||
return await testSubjects.findAll(`objectsTableRow`);
|
||||
}
|
||||
}
|
||||
|
||||
return new SettingsPage();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue