Merge branch 'feature/ingest' into ingest/pipelineIngestAPI

This commit is contained in:
Matthew Bargar 2016-02-04 20:25:39 -05:00
commit 0e707fe72d
50 changed files with 698 additions and 126 deletions

View file

@ -60,11 +60,11 @@ define(function (require) {
};
$scope.toggleDisplay = function (field) {
// inheritted param to fieldChooser
// This is inherited from fieldChooser
$scope.toggle(field.name);
if (field.display) $scope.increaseFieldCounter(field);
// we are now displaying the field, kill it's details
// we are now displaying the field, kill its details
if (field.details) {
$scope.toggleDetails(field);
}

View file

@ -16,7 +16,7 @@
<!-- Settings editors -->
<form
name="forms.configEdit"
ng-if="conf.editting"
ng-if="conf.editing"
ng-submit="save(conf)"
role="form">
@ -65,7 +65,7 @@
</form>
<!-- Setting display formats -->
<span ng-if="!conf.editting" data-test-subj="currentValue">
<span ng-if="!conf.editing" data-test-subj="currentValue">
<span ng-show="(conf.normal || conf.json || conf.select)">{{conf.value || conf.defVal}}</span>
<span ng-show="conf.array">{{(conf.value || conf.defVal).join(', ')}}</span>
<span ng-show="conf.bool">{{conf.value === undefined ? conf.defVal : conf.value}}</span>
@ -74,7 +74,7 @@
</td>
<td class="actions">
<button
ng-if="!conf.editting"
ng-if="!conf.editing"
ng-click="edit(conf)"
class="btn btn-default"
ng-disabled="conf.tooComplex"
@ -85,7 +85,7 @@
</button>
<button
ng-if="conf.editting"
ng-if="conf.editing"
ng-click="save(conf)"
class="btn btn-success"
ng-disabled="conf.loading || conf.tooComplex || forms.configEdit.$invalid"
@ -97,7 +97,7 @@
</button>
<button
ng-if="!conf.editting"
ng-if="!conf.editing"
ng-click="clear(conf)"
ng-hide="conf.value === undefined"
class="btn btn-danger"
@ -108,7 +108,7 @@
</button>
<button
ng-if="conf.editting"
ng-if="conf.editing"
ng-click="cancelEdit(conf)"
class="btn btn-default"
aria-label="Cancel edit"

View file

@ -22,12 +22,12 @@ define(function (require) {
// To allow passing form validation state back
$scope.forms = {};
// setup loading flag, run async op, then clear loading and editting flag (just in case)
// setup loading flag, run async op, then clear loading and editing flag (just in case)
var loading = function (conf, fn) {
conf.loading = true;
fn()
.finally(function () {
conf.loading = conf.editting = false;
conf.loading = conf.editing = false;
})
.catch(notify.fatal);
};
@ -41,7 +41,7 @@ define(function (require) {
$scope.edit = function (conf) {
conf.unsavedValue = conf.value == null ? conf.defVal : conf.value;
$scope.configs.forEach(function (c) {
c.editting = (c === conf);
c.editing = (c === conf);
});
};
@ -56,7 +56,7 @@ define(function (require) {
};
$scope.cancelEdit = function (conf) {
conf.editting = false;
conf.editing = false;
};
$scope.clear = function (conf) {

View file

@ -167,6 +167,7 @@
</div>
<button
data-test-subj="submitCreateIndexPatternFromExistingForm"
ng-disabled="form.$invalid || index.fetchFieldsError"
ng-class="index.fetchFieldsError ? 'btn-default' : 'btn-success'"
type="submit"

View file

@ -7,7 +7,7 @@ define(function (require) {
require('ui/directives/auto_select_if_only_one');
require('ui/routes')
.when('/settings/indices/', {
.when('/settings/indices/create/existing', {
template: require('plugins/kibana/settings/sections/indices/_create.html')
});
@ -70,7 +70,7 @@ define(function (require) {
config.set('defaultIndex', indexPattern.id);
}
indexPatterns.cache.clear(indexPattern.id);
kbnUrl.change('/settings/indices/' + indexPattern.id);
kbnUrl.change('/settings/indices/edit/' + indexPattern.id);
});
}
});

View file

@ -1,6 +1,6 @@
<kbn-settings-app section="indices">
<kbn-settings-indices>
<div ng-controller="settingsIndicesEdit">
<div ng-controller="settingsIndicesEdit" data-test-subj="editIndexPattern">
<div class="page-header">
<kbn-settings-index-header
index-pattern="indexPattern"

View file

@ -5,7 +5,7 @@ define(function (require) {
require('plugins/kibana/settings/sections/indices/_index_header');
require('ui/routes')
.when('/settings/indices/:indexPatternId', {
.when('/settings/indices/edit/:indexPatternId', {
template: require('plugins/kibana/settings/sections/indices/_edit.html'),
resolve: {
indexPattern: function ($route, courier) {

View file

@ -3,9 +3,9 @@ define(function (require) {
require('plugins/kibana/settings/sections/indices/_index_header');
require('ui/routes')
.when('/settings/indices/:indexPatternId/field/:fieldName', { mode: 'edit' })
.when('/settings/indices/:indexPatternId/create-field/', { mode: 'create' })
.defaults(/settings\/indices\/[^\/]+\/(field|create-field)(\/|$)/, {
.when('/settings/indices/edit/:indexPatternId/field/:fieldName', { mode: 'edit' })
.when('/settings/indices/edit/:indexPatternId/create-field/', { mode: 'create' })
.defaults(/settings\/indices\/edit\/[^\/]+\/(field|create-field)(\/|$)/, {
template: require('plugins/kibana/settings/sections/indices/_field_editor.html'),
resolve: {
indexPattern: function ($route, courier) {

View file

@ -18,7 +18,7 @@ define(function (require) {
link: function ($scope) {
var dateScripts = require('plugins/kibana/settings/sections/indices/_date_scripts');
var fieldCreatorPath = '/settings/indices/{{ indexPattern }}/scriptedField';
var fieldCreatorPath = '/settings/indices/edit/{{ indexPattern }}/scriptedField';
var fieldEditorPath = fieldCreatorPath + '/{{ fieldName }}';
$scope.perPage = 25;

View file

@ -0,0 +1,34 @@
<div class="wizard-step-title">
<h3>Follow these instructions to install Filebeat</h3>
Now that you've got a fresh pipeline and index pattern, let's throw some data at it!
</div>
<div>
<ol>
<li>Install Filebeat on all servers on which you want to tail logs
(<a target="_blank" href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-getting-started.html#filebeat-installation">
instructions
</a>)
</li>
<li>
Point Filebeat at the log files you want to tail
(<a target="_blank" href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-getting-started.html#filebeat-configuration">
instructions
</a>)
</li>
<li>Configure Filebeat on each server to send data to your Elasticsearch instances
(<a target="_blank" href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-configuration-details.html#elasticsearch-output">
instructions
</a>)
</li>
<li>Set the index name in filebeat.yml based on the index pattern you configured in the previous step. The Filebeat
config takes a base index name and automatically rotates the target index by appending "-{date}" to the end, so if
your pattern was "foo-*" you would make the index name "foo" in filebeat.yml.
</li>
<li>Run Filebeat on each server
(<a target="_blank" href="https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-getting-started.html#_running_filebeat">
instructions
</a>)
</li>
</ol>
</div>

View file

@ -0,0 +1,16 @@
import modules from 'ui/modules';
import template from 'plugins/kibana/settings/sections/indices/add_data_steps/install_filebeat_step.html';
modules.get('apps/settings')
.directive('installFilebeatStep', function () {
return {
template: template,
scope: {
results: '='
},
controller: function ($scope) {
var results = $scope.results;
}
};
});

View file

@ -0,0 +1,13 @@
<div class="wizard-step-title">
<h3>Provide some sample logs</h3>
Paste in one or more lines from the file you intend to tail. We'll use these samples in the following steps to help
you build an ingest pipeline and configure a Kibana index pattern. Log lines can be raw strings or
formatted as JSON. If your logs are raw strings but you intend to use
<a target="_window" href="https://www.elastic.co/guide/en/beats/filebeat/current/exported-fields.html">Filebeat's metadata</a>,
you'll want to paste the JSON as it will come out of Filebeat.
</div>
<div class="paste-samples">
<textarea ng-model="pasteStep.rawSamples" placeholder="Paste your sample log lines here, separated by a newline"></textarea>
</div>

View file

@ -0,0 +1,37 @@
import modules from 'ui/modules';
import template from 'plugins/kibana/settings/sections/indices/add_data_steps/paste_samples_step.html';
import _ from 'lodash';
modules.get('apps/settings')
.directive('pasteSamplesStep', function () {
return {
template: template,
scope: {
samples: '=',
rawSamples: '='
},
bindToController: true,
controllerAs: 'pasteStep',
controller: function ($scope) {
if (_.isUndefined(this.rawSamples)) {
this.rawSamples = '';
}
$scope.$watch('pasteStep.rawSamples', (newValue) => {
const splitRawSamples = newValue.split('\n');
try {
this.samples = _.map(splitRawSamples, (sample) => {
return JSON.parse(sample);
});
}
catch (error) {
this.samples = _.map(splitRawSamples, (sample) => {
return {message: sample};
});
}
});
}
};
});

View file

@ -0,0 +1,32 @@
<div class="wizard-step-title">
<h3>Review the index pattern</h3>
Here we'll define how and where to store your parsed events. We've made some intellient guesses for you, but most
fields can be changed if we got it wrong!
</div>
<div class="pattern-review">
<div>
<label>Index name or pattern</label>
<kbn-info info="Patterns allow you to define dynamic index names using * as a wildcard. Example: filebeat-*"></kbn-info>
</div>
<input ng-model="reviewStep.indexPattern.id" class="pattern-input"/>
<label>
<input ng-model="reviewStep.isTimeBased" type="checkbox"/>
time based
</label>
<label ng-if="reviewStep.isTimeBased" class="time-field-input">
Time Field
<select ng-model="reviewStep.indexPattern.timeFieldName" name="time_field_name">
<option ng-repeat="field in reviewStep.dateFields" value="{{field}}">
{{field}}
</option>
</select>
</label>
</div>
<div>
<paginated-table
columns="reviewStep.columns"
rows="reviewStep.rows">
</paginated-table>
</div>

View file

@ -0,0 +1,152 @@
const modules = require('ui/modules');
const template = require('plugins/kibana/settings/sections/indices/add_data_steps/pattern_review_step.html');
const _ = require('lodash');
const editFieldTypeHTML = require('plugins/kibana/settings/sections/indices/partials/_edit_field_type.html');
const testData = {
message: '11/24/2015 ip=1.1.1.1 bytes=1234',
clientip: '1.1.1.1',
bytes: 1234,
geoip: {
lat: 37.3894,
lon: 122.0819
},
location: {
lat: 37.3894,
lon: 122.0819
},
'@timestamp': '2015-11-24T00:00:00.000Z',
otherdate: '2015-11-24T00:00:00.000Z',
codes: [1, 2, 3, 4]
};
const testPipeline = [
{
grok: {
match_field: 'message',
match_pattern: 'foo'
}
},
{
geoip: {
source_field: 'ip'
}
},
{
geoip: {
source_field: 'ip',
target_field: 'location'
}
},
{
date: {
match_field: 'initialDate',
match_formats: ['dd/MM/yyyy hh:mm:ss']
}
},
{
date: {
match_field: 'initialDate',
match_formats: ['dd/MM/yyyy hh:mm:ss'],
target_field: 'otherdate'
}
}
];
function pickDefaultTimeFieldName(dateFields) {
if (_.isEmpty(dateFields)) {
return undefined;
}
return _.includes(dateFields, '@timestamp') ? '@timestamp' : dateFields[0];
}
modules.get('apps/settings')
.directive('patternReviewStep', function () {
return {
template: template,
scope: {
sampleDocs: '=',
indexPattern: '=',
pipeline: '='
},
controllerAs: 'reviewStep',
bindToController: true,
controller: function ($scope, Private) {
this.sampleDocs = testData;
this.pipeline = testPipeline;
if (_.isUndefined(this.indexPattern)) {
this.indexPattern = {};
}
const knownFieldTypes = {};
this.dateFields = [];
this.pipeline.forEach((processor) => {
if (processor.geoip) {
const field = processor.geoip.target_field || 'geoip';
knownFieldTypes[field] = 'geo_point';
}
else if (processor.date) {
const field = processor.date.target_field || '@timestamp';
knownFieldTypes[field] = 'date';
this.dateFields.push(field);
}
});
_.defaults(this.indexPattern, {
id: 'filebeat-*',
title: 'filebeat-*',
timeFieldName: pickDefaultTimeFieldName(this.dateFields),
fields: _.map(this.sampleDocs, (value, key) => {
let type = knownFieldTypes[key] || typeof value;
if (type === 'object' && _.isArray(value) && !_.isEmpty(value)) {
type = typeof value[0];
}
return {name: key, type: type};
})
});
this.isTimeBased = !!this.indexPattern.timeFieldName;
$scope.$watch('reviewStep.indexPattern.id', (value) => {
this.indexPattern.title = value;
});
$scope.$watch('reviewStep.isTimeBased', (value) => {
if (value) {
this.indexPattern.timeFieldName = pickDefaultTimeFieldName(this.dateFields);
}
else {
delete this.indexPattern.timeFieldName;
}
});
$scope.$watch('reviewStep.indexPattern.fields', (fields) => {
this.dateFields = _.map(_.filter(fields, {type: 'date'}), 'name');
}, true);
const buildRows = () => {
this.rows = _.map(this.indexPattern.fields, (field) => {
const sampleValue = this.sampleDocs[field.name];
return [
_.escape(field.name),
{
markup: editFieldTypeHTML,
scope: _.assign($scope.$new(), {field: field, knownFieldTypes: knownFieldTypes, buildRows: buildRows}),
value: field.type
},
typeof sampleValue === 'object' ? _.escape(JSON.stringify(sampleValue)) : _.escape(sampleValue)
];
});
};
this.columns = [
{title: 'Field'},
{title: 'Type'},
{title: 'Example', sortable: false}
];
buildRows();
}
};
});

View file

@ -0,0 +1,7 @@
<h2>Build pipeline step</h2>
<div>
Logs: {{samples}}
</div>
<button ng-click="sampleDocs = {results: {os: 'osx'}}; pipeline = {processor: 'I processor'};">Build a pipeline</button>

View file

@ -0,0 +1,15 @@
var modules = require('ui/modules');
var template = require('plugins/kibana/settings/sections/indices/add_data_steps/pipeline_step.html');
modules.get('apps/settings')
.directive('pipelineStep', function () {
return {
template: template,
scope: {
samples: '=',
sampleDocs: '=',
pipeline: '='
}
};
});

View file

@ -0,0 +1,38 @@
<div class="col-md-2 sidebar-container">
<div class="sidebar-list">
<div class="sidebar-list-header">
<h5>
Index Patterns&nbsp;
<a
ng-if="showAddNew"
href="#/settings/indices"
class="btn btn-primary btn-xs"
aria-label="Add New">
<span class="sr-only">Add New</span>
<i aria-hidden="true" class="fa fa-plus"></i> Add New
</a>
</h5>
</div>
<ul class="list-unstyled">
<li
ng-if="!defaultIndex"
class="sidebar-item">
<div class="sidebar-item-title full-title">
<span class="label label-warning">Warning</span> No default index pattern. You must select or create one to continue.
</div>
</li>
<li
ng-repeat="pattern in indexPatternList | orderBy:['-default','id'] track by pattern.id "
class="sidebar-item">
<a href="{{::pattern.url}}">
<div class="{{::pattern.class}}">
<i aria-hidden="true" ng-if="pattern.default" class="fa fa-star"></i>
<span ng-bind="::pattern.id"></span>
</div>
</a>
</li>
</ul>
</div>
</div>
<div class="col-md-10" ng-transclude></div>

View file

@ -0,0 +1,28 @@
// wrapper directive, which sets some global stuff up like the left nav
require('ui/modules').get('apps/settings')
.directive('kbnSettingsIndices', function ($route, config, kbnUrl) {
return {
restrict: 'E',
transclude: true,
template: require('plugins/kibana/settings/sections/indices/directives/kbn_settings_indices.html'),
link: function ($scope) {
$scope.showAddNew = !/^\/settings\/indices$/.test($route.current.$$route.originalPath);
$scope.editingId = $route.current.params.indexPatternId;
config.$bind($scope, 'defaultIndex');
$scope.$watch('defaultIndex', function () {
var ids = $route.current.locals.indexPatternIds;
$scope.indexPatternList = ids.map(function (id) {
return {
id: id,
url: kbnUrl.eval('#/settings/indices/edit/{{id}}', {id: id}),
class: 'sidebar-item-title ' + ($scope.editingId === id ? 'active' : ''),
default: $scope.defaultIndex === id
};
});
});
$scope.$emit('application.load');
}
};
});

View file

@ -0,0 +1,78 @@
<div>
<div class="page-header">
<h1>Tail a File</h1>
Let's send some log data to Elasticsearch.
</div>
</div>
<div>
<div class="wizard-step-headings" ng-class="{complete: wizard.complete}">
<span ng-class="{active: wizard.currentStep === 0}"
class="wizard-step-heading"
ng-click="wizard.setCurrentStep(0)">
1. Paste
</span>
<span ng-class="{active: wizard.currentStep === 1, aheadActive: wizard.currentStep < 1}"
class="wizard-step-heading"
ng-click="wizard.currentStep < 1 || wizard.setCurrentStep(1)">
2. Parse
</span>
<span ng-class="{active: wizard.currentStep === 2, aheadActive: wizard.currentStep < 2}"
class="wizard-step-heading"
ng-click="wizard.currentStep < 2 || wizard.setCurrentStep(2)">
3. Review
</span>
<span ng-class="{active: wizard.currentStep === 3, aheadActive: wizard.currentStep < 3}"
class="wizard-step-heading"
ng-click="wizard.currentStep < 3 || wizard.setCurrentStep(3)">
4. Install Filebeat
</span>
</div>
<div ng-switch="wizard.currentStep">
<div ng-switch-when="0">
<paste-samples-step samples="wizard.stepResults.samples" raw-samples="wizard.stepResults.rawSamples"></paste-samples-step>
<div class="nav-buttons">
<button ng-disabled="!wizard.stepResults.samples" ng-click="wizard.nextStep()">Next</button>
</div>
</div>
<div ng-switch-when="1">
<pipeline-step
samples="wizard.stepResults.samples"
pipeline="wizard.stepResults.pipeline"
sample-docs="wizard.stepResults.sampleDocs">
</pipeline-step>
<div class="nav-buttons">
<button ng-click="wizard.prevStep()">Prev</button>
<button ng-disabled="!wizard.stepResults.pipeline || !wizard.stepResults.sampleDocs" ng-click="wizard.nextStep()">Next</button>
</div>
</div>
<div ng-switch-when="2">
<pattern-review-step
index-pattern="wizard.stepResults.indexPattern"
sample-docs="wizard.stepResults.sampleDocs"
pipeline="wizard.stepResults.pipeline">
</pattern-review-step>
<div class="nav-buttons">
<button ng-click="wizard.prevStep()">Prev</button>
<button ng-disabled="!wizard.stepResults.indexPattern || !wizard.stepResults.indexPattern.id"
ng-click="wizard.nextStep()">
Save
</button>
</div>
</div>
<div ng-switch-when="3">
<install-filebeat-step results="wizard.stepResults"></install-filebeat-step>
<div class="nav-buttons">
Click Done to go explore your data
<button ng-click="wizard.nextStep()">Done</button>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,78 @@
var modules = require('ui/modules');
var template = require('plugins/kibana/settings/sections/indices/filebeat/directives/filebeat_wizard.html');
require('plugins/kibana/settings/sections/indices/add_data_steps/pattern_review_step');
require('plugins/kibana/settings/sections/indices/add_data_steps/paste_samples_step');
require('plugins/kibana/settings/sections/indices/add_data_steps/pipeline_step');
require('plugins/kibana/settings/sections/indices/add_data_steps/install_filebeat_step');
// wrapper directive, which sets up the breadcrumb for all filebeat steps
modules.get('apps/settings')
.directive('filebeatWizard', function () {
return {
restrict: 'E',
template: template,
scope: {},
bindToController: true,
controllerAs: 'wizard',
controller: function ($scope, AppState, safeConfirm, kbnUrl) {
var $state = this.state = new AppState();
var totalSteps = 4;
this.stepResults = {};
this.setCurrentStep = (step) => {
if (!this.complete) {
$state.currentStep = step;
$state.save();
}
};
this.setCurrentStep(0);
this.nextStep = () => {
if ($state.currentStep + 1 < totalSteps) {
this.setCurrentStep($state.currentStep + 1);
}
else if ($state.currentStep + 1 === totalSteps) {
kbnUrl.change('/discover');
}
};
this.prevStep = () => {
if ($state.currentStep > 0) {
this.setCurrentStep($state.currentStep - 1);
}
};
$scope.$watch('wizard.state.currentStep', (newValue, oldValue) => {
if (this.complete) {
$state.currentStep = totalSteps - 1;
$state.save();
return;
}
if (newValue + 1 === totalSteps) {
this.complete = true;
}
if (newValue < oldValue) {
return safeConfirm('Going back will reset any changes you\'ve made to this step, do you want to continue?')
.then(
() => {
if ($state.currentStep < 1) {
delete this.stepResults.pipeline;
}
if ($state.currentStep < 2) {
delete this.stepResults.indexPattern;
}
this.currentStep = newValue;
},
() => {
$state.currentStep = oldValue;
$state.save();
}
);
}
else {
this.currentStep = newValue;
}
});
}
};
});

View file

@ -0,0 +1,5 @@
<kbn-settings-app section="indices">
<kbn-settings-indices>
<filebeat-wizard />
</kbn-settings-indices>
</kbn-settings-app>

View file

@ -0,0 +1,8 @@
var routes = require('ui/routes');
var template = require('plugins/kibana/settings/sections/indices/filebeat/index.html');
require('plugins/kibana/settings/sections/indices/filebeat/directives/filebeat_wizard');
routes.when('/settings/indices/create/filebeat', {
template: template
});

View file

@ -1,38 +1,25 @@
<div class="col-md-2 sidebar-container">
<div class="sidebar-list">
<div class="sidebar-list-header">
<h5>
Index Patterns&nbsp;
<a
ng-if="edittingId"
href="#/settings/indices"
class="btn btn-primary btn-xs"
aria-label="Add New">
<span class="sr-only">Add New</span>
<i aria-hidden="true" class="fa fa-plus"></i> Add New
</a>
</h5>
</div>
<ul class="list-unstyled">
<li
ng-if="!defaultIndex"
class="sidebar-item">
<div class="sidebar-item-title full-title">
<span class="label label-warning">Warning</span> No default index pattern. You must select or create one to continue.
</div>
</li>
<li
ng-repeat="pattern in indexPatternList | orderBy:['-default','id'] track by pattern.id "
class="sidebar-item">
<a href="{{::pattern.url}}">
<div class="{{::pattern.class}}">
<i aria-hidden="true" ng-if="pattern.default" class="fa fa-star"></i>
<span ng-bind="::pattern.id"></span>
</div>
</a>
</li>
</ul>
</div>
</div>
<kbn-settings-app section="indices">
<kbn-settings-indices>
<div data-test-subj="addData">
<div class="page-header">
<h1>Add Data</h1>
Before we can get to the fun stuff, we'll have to get some data into your Elasticsearch cluster.
Pick the option that best suits your use case below, and we'll guide you through the process!
</div>
<div class="col-md-10" ng-transclude></div>
<h4>
<a href="#/settings/indices/create/existing" data-test-subj="existingIndices">Existing Indices</a>
</h4>
<div>
Pick this option if you already have data in Elasticsearch.
</div>
<h4>
<a href="#/settings/indices/create/filebeat">Tail a File</a>
</h4>
<div>
Pick this option if you have log file data you'd like to send to Elasticsearch.
</div>
</div>
</kbn-settings-indices>
</kbn-settings-app>

View file

@ -1,7 +1,9 @@
define(function (require) {
var _ = require('lodash');
require('plugins/kibana/settings/sections/indices/directives/kbn_settings_indices');
require('plugins/kibana/settings/sections/indices/_create');
require('plugins/kibana/settings/sections/indices/filebeat/index');
require('plugins/kibana/settings/sections/indices/_edit');
require('plugins/kibana/settings/sections/indices/_field_editor');
@ -15,37 +17,14 @@ define(function (require) {
}
});
// wrapper directive, which sets some global stuff up like the left nav
require('ui/modules').get('apps/settings')
.directive('kbnSettingsIndices', function ($route, config, kbnUrl) {
return {
restrict: 'E',
transclude: true,
template: require('plugins/kibana/settings/sections/indices/index.html'),
link: function ($scope) {
$scope.edittingId = $route.current.params.indexPatternId;
config.$bind($scope, 'defaultIndex');
$scope.$watch('defaultIndex', function () {
var ids = $route.current.locals.indexPatternIds;
$scope.indexPatternList = ids.map(function (id) {
return {
id: id,
url: kbnUrl.eval('#/settings/indices/{{id}}', {id: id}),
class: 'sidebar-item-title ' + ($scope.edittingId === id ? 'active' : ''),
default: $scope.defaultIndex === id
};
});
});
$scope.$emit('application.load');
}
};
});
require('ui/routes')
.when('/settings/indices', {
template: require('plugins/kibana/settings/sections/indices/index.html')
});
return {
name: 'indices',
display: 'Indices',
url: '#/settings/indices',
url: '#/settings/indices'
};
});

View file

@ -0,0 +1,13 @@
<select ng-if="knownFieldTypes[field.name] !== 'geo_point'" name="field_type" ng-model="field.type" ng-change="buildRows()">
<option value="string">string</option>
<option value="number">number</option>
<option value="boolean">boolean</option>
<option value="date">date</option>
<option value="geo_point">geo_point</option>
<option value="geo_shape">geo_shape</option>
<option value="ip">ip</option>
</select>
<span ng-if="knownFieldTypes[field.name] === 'geo_point'">
geo_point
</span>

View file

@ -186,3 +186,51 @@ kbn-settings-indices {
.kbn-settings-indices-create {
.time-and-pattern > div {}
}
.wizard-step-headings{
margin-top: 1em;
.wizard-step-heading {
font-size: 1.5em;
padding-right: 1.5em;
&.active {
cursor: default;
font-weight: bold;
}
&.aheadActive {
cursor: default;
font-weight: 300;
}
}
&.complete {
.wizard-step-heading:not(.active) {
color: #dddddd;
cursor: default;
}
}
}
.wizard-step-title {
padding-bottom: 1em;
}
.pattern-review {
.time-field-input {
padding-left: 1em;
margin-bottom: 0;
}
.pattern-input {
width: 300px;
}
}
.paste-samples {
textarea {
width: 100%;
height: 250px;
}
}

View file

@ -69,7 +69,7 @@ define(function (require) {
}
Field.prototype.routes = {
edit: '/settings/indices/{{indexPattern.id}}/field/{{name}}'
edit: '/settings/indices/edit/{{indexPattern.id}}/field/{{name}}'
};
return Field;

View file

@ -314,10 +314,10 @@ define(function (require) {
}
IndexPattern.prototype.routes = {
edit: '/settings/indices/{{id}}',
addField: '/settings/indices/{{id}}/create-field',
indexedFields: '/settings/indices/{{id}}?_a=(tab:indexedFields)',
scriptedFields: '/settings/indices/{{id}}?_a=(tab:scriptedFields)'
edit: '/settings/indices/edit/{{id}}',
addField: '/settings/indices/edit/{{id}}/create-field',
indexedFields: '/settings/indices/edit/{{id}}?_a=(tab:indexedFields)',
scriptedFields: '/settings/indices/edit/{{id}}?_a=(tab:scriptedFields)'
};
return IndexPattern;

View file

@ -23,7 +23,7 @@ define(function (require) {
self.fetch();
}),
// begining of full route update, new app will be initialized before
// beginning of full route update, new app will be initialized before
// $routeChangeSuccess or $routeChangeError
$rootScope.$on('$routeChangeStart', function () {
if (self._persistAcrossApps) {
@ -136,8 +136,8 @@ define(function (require) {
* @returns {void}
*/
State.prototype.destroy = function () {
this.off(); // removes all listners
this._cleanUpListeners(); // Removes the $routeUpdate listner
this.off(); // removes all listeners
this._cleanUpListeners(); // Removes the $routeUpdate listener
};
State.prototype.setDefaults = function (defaults) {

View file

@ -88,9 +88,9 @@ define(function (require) {
/**
* Return the current bounds, if we have any.
*
* THIS DOES NOT CLONE THE BOUNDS, so editting them
* THIS DOES NOT CLONE THE BOUNDS, so editing them
* may have unexpected side-effects. Always
* call bounds.min.clone() before editting
* call bounds.min.clone() before editing
*
* @return {object|undefined} - If bounds are not defined, this
* returns undefined, else it returns the bounds

View file

@ -32,7 +32,7 @@ define(function (require) {
})
.then(function (navigateTo) {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -28,7 +28,7 @@ define(function (require) {
})
.then(function (navigateTo) {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -28,7 +28,7 @@ define(function (require) {
})
.then(function (navigateTo) {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -37,7 +37,7 @@ define(function (require) {
})
.then(function (navigateTo) {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -14,7 +14,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
});
});

View file

@ -16,7 +16,7 @@ define(function (require) {
bdd.beforeEach(function () {
return scenarioManager.reload('emptyKibana')
.then(function () {
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
});
});

View file

@ -16,7 +16,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
});
});
@ -81,9 +81,9 @@ define(function (require) {
});
});
bdd.it('should return to index pattern creation page', function returnToPage() {
bdd.it('should return to the add data landing page', function returnToPage() {
return common.tryForTime(5000, function () {
return settingsPage.getCreateButton();
return common.findTestSubject('addData');
})
.catch(common.handleError(this));
});

View file

@ -16,7 +16,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
});
});
@ -25,7 +25,7 @@ define(function (require) {
});
bdd.afterEach(function ae() {
return settingsPage.removeIndexPattern();
return settingsPage.removeIndexPattern().then(settingsPage.clickExistingIndicesAddDataLink);
});
bdd.describe('change popularity', function indexPatternCreation() {

View file

@ -38,7 +38,7 @@ define(function (require) {
columns.forEach(function (col) {
bdd.describe('sort by heading - ' + col.heading, function indexPatternCreation() {
bdd.before(function () {
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
});
bdd.beforeEach(function () {
@ -46,7 +46,7 @@ define(function (require) {
});
bdd.afterEach(function () {
return settingsPage.removeIndexPattern();
return settingsPage.removeIndexPattern().then(settingsPage.clickExistingIndicesAddDataLink);
});
bdd.it('should sort ascending', function pageHeader() {
@ -84,6 +84,7 @@ define(function (require) {
bdd.before(function () {
return settingsPage.navigateTo()
.then(settingsPage.clickExistingIndicesAddDataLink)
.then(function () {
return settingsPage.createIndexPattern();
});

View file

@ -14,7 +14,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
});
});

View file

@ -31,7 +31,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -18,7 +18,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -31,7 +31,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -28,7 +28,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -34,7 +34,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -28,7 +28,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -30,7 +30,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -30,7 +30,7 @@ define(function (require) {
return scenarioManager.reload('emptyKibana')
.then(function () {
common.debug('navigateTo');
return settingsPage.navigateTo();
return settingsPage.navigateTo().then(settingsPage.clickExistingIndicesAddDataLink);
})
.then(function () {
common.debug('createIndexPattern');

View file

@ -20,6 +20,10 @@ define(function (require) {
return common.findTestSubject('settingsNav advanced').click();
},
clickExistingIndicesAddDataLink: function () {
return common.findTestSubject('addData existingIndices').click();
},
setAdvancedSettings: function setAdvancedSettings(propertyName, propertyValue) {
var self = this;
return common.findTestSubject('advancedSetting&' + propertyName + ' editButton')
@ -126,13 +130,11 @@ define(function (require) {
},
getCreateButton: function () {
return this.remote.setFindTimeout(defaultTimeout)
.findByCssSelector('.btn');
return common.findTestSubject('submitCreateIndexPatternFromExistingForm');
},
clickCreateButton: function () {
return this.remote.setFindTimeout(defaultTimeout)
.findByCssSelector('.btn').click();
return common.findTestSubject('submitCreateIndexPatternFromExistingForm').click();
},
clickDefaultIndexButton: function () {
@ -305,17 +307,17 @@ define(function (require) {
return common.tryForTime(defaultTimeout, function () {
return self.selectTimeFieldOption('@timestamp')
.then(function () {
return self.getCreateButton().click();
return self.clickCreateButton();
});
})
.then(function () {
return common.tryForTime(defaultTimeout, function () {
return self.remote.getCurrentUrl()
.then(function (currentUrl) {
if (!currentUrl.match(/indices\/.+\?/)) {
return common.findTestSubject('editIndexPattern')
.then(function (editPatternContainer) {
if (!editPatternContainer) {
throw new Error('Index pattern not created');
} else {
common.debug('Index pattern created: ' + currentUrl);
common.debug('Index pattern created');
}
});
});