From b531c15f9f0140768652a089777edba978737e2a Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Wed, 3 Feb 2016 16:04:05 -0700 Subject: [PATCH 01/70] add tests immediate fire on register --- src/server/status/__tests__/Status.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/server/status/__tests__/Status.js b/src/server/status/__tests__/Status.js index 8563500a34af0a..2068e751937573 100644 --- a/src/server/status/__tests__/Status.js +++ b/src/server/status/__tests__/Status.js @@ -59,6 +59,18 @@ describe('Status class', function () { expect(json.message).to.eql('Ready'); }); + it('should call handler if status is already matched', function (done) { + var status = serverStatus.create('test'); + var msg = 'Test Ready'; + status.green(msg); + + status.on('green', function () { + expect(arguments.length).to.equal(0); + expect(status.message).to.equal(msg); + done(); + }); + }); + function testState(color) { it(`should change the state to ${color} when #${color}() is called`, function () { var status = serverStatus.create('test'); From bc7183ad0c77ebf9366648c43a96149f6b4fd6b9 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Wed, 3 Feb 2016 16:04:30 -0700 Subject: [PATCH 02/70] make tests pass --- src/server/status/Status.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/server/status/Status.js b/src/server/status/Status.js index 430d44d0a114fc..bf9f10d6ca2be4 100644 --- a/src/server/status/Status.js +++ b/src/server/status/Status.js @@ -36,6 +36,14 @@ class Status extends EventEmitter { since: this.since }; } + + on(eventName, handler) { + super.on(eventName, handler); + + if (eventName === this.state) { + setImmediate(handler); + } + } } states.all.forEach(function (state) { From 582937871a081e37e941a8f580ce352d95ea8879 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Wed, 3 Feb 2016 16:19:51 -0700 Subject: [PATCH 03/70] add once handler as well --- src/server/status/Status.js | 8 ++++++++ src/server/status/__tests__/Status.js | 14 +++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/server/status/Status.js b/src/server/status/Status.js index bf9f10d6ca2be4..9e11cf6bc19054 100644 --- a/src/server/status/Status.js +++ b/src/server/status/Status.js @@ -44,6 +44,14 @@ class Status extends EventEmitter { setImmediate(handler); } } + + once(eventName, handler) { + if (eventName === this.state) { + setImmediate(handler); + } else { + super.once(eventName, handler); + } + } } states.all.forEach(function (state) { diff --git a/src/server/status/__tests__/Status.js b/src/server/status/__tests__/Status.js index 2068e751937573..727befb3138901 100644 --- a/src/server/status/__tests__/Status.js +++ b/src/server/status/__tests__/Status.js @@ -59,7 +59,7 @@ describe('Status class', function () { expect(json.message).to.eql('Ready'); }); - it('should call handler if status is already matched', function (done) { + it('should call on handler if status is already matched', function (done) { var status = serverStatus.create('test'); var msg = 'Test Ready'; status.green(msg); @@ -71,6 +71,18 @@ describe('Status class', function () { }); }); + it('should call once handler if status is already matched', function (done) { + var status = serverStatus.create('test'); + var msg = 'Test Ready'; + status.green(msg); + + status.once('green', function () { + expect(arguments.length).to.equal(0); + expect(status.message).to.equal(msg); + done(); + }); + }); + function testState(color) { it(`should change the state to ${color} when #${color}() is called`, function () { var status = serverStatus.create('test'); From f4e3226c4fa8023d4337efe9490132e730988a99 Mon Sep 17 00:00:00 2001 From: Jimmy Jones Date: Sat, 6 Feb 2016 20:09:05 +0000 Subject: [PATCH 04/70] Allow exists filter for unindexed fields, but not meta fields --- .../components/field_chooser/lib/detail_views/string.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html b/src/plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html index d90c7cd1c4b77c..6109d511464390 100644 --- a/src/plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html +++ b/src/plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html @@ -3,8 +3,8 @@
Quick Count ( - {{::field.details.exists}} - {{::field.details.exists}} + {{::field.details.exists}} + {{::field.details.exists}} /{{::field.details.total}} records ) From 82146c222b260fcee42a9737930bf9ac0c780bef Mon Sep 17 00:00:00 2001 From: Jimmy Jones Date: Tue, 9 Feb 2016 19:52:31 +0000 Subject: [PATCH 05/70] Updates as suggested by @spalger --- .../field_chooser/lib/detail_views/string.html | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html b/src/plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html index 6109d511464390..719d1c6ef62f57 100644 --- a/src/plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html +++ b/src/plugins/kibana/public/discover/components/field_chooser/lib/detail_views/string.html @@ -3,8 +3,15 @@
Quick Count ( - {{::field.details.exists}} - {{::field.details.exists}} + + {{::field.details.exists}} + + + {{::field.details.exists}} + /{{::field.details.total}} records ) From 1e0f2174e199fcf13675d78da76f6e42ede64180 Mon Sep 17 00:00:00 2001 From: michaelcheng429 Date: Wed, 20 Jan 2016 19:28:23 -0600 Subject: [PATCH 06/70] fix histogram extended bounds persisting after deselection --- .../public/agg_types/__tests__/buckets/_histogram.js | 12 ++++++++++++ src/ui/public/agg_types/buckets/histogram.js | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ui/public/agg_types/__tests__/buckets/_histogram.js b/src/ui/public/agg_types/__tests__/buckets/_histogram.js index 0aa6a3122bd5bb..ea14171d32e601 100644 --- a/src/ui/public/agg_types/__tests__/buckets/_histogram.js +++ b/src/ui/public/agg_types/__tests__/buckets/_histogram.js @@ -82,6 +82,7 @@ describe('Histogram Agg', function () { describe('extended_bounds', function () { it('writes when only eb.min is set', function () { var output = paramWriter.write({ + min_doc_count: true, extended_bounds: { min: 0 } }); expect(output.params.extended_bounds).to.have.property('min', 0); @@ -90,6 +91,7 @@ describe('Histogram Agg', function () { it('writes when only eb.max is set', function () { var output = paramWriter.write({ + min_doc_count: true, extended_bounds: { max: 0 } }); expect(output.params.extended_bounds).to.have.property('min', undefined); @@ -98,6 +100,7 @@ describe('Histogram Agg', function () { it('writes when both eb.min and eb.max are set', function () { var output = paramWriter.write({ + min_doc_count: true, extended_bounds: { min: 99, max: 100 } }); expect(output.params.extended_bounds).to.have.property('min', 99); @@ -106,10 +109,19 @@ describe('Histogram Agg', function () { it('does not write when nothing is set', function () { var output = paramWriter.write({ + min_doc_count: true, extended_bounds: {} }); expect(output.params).to.not.have.property('extended_bounds'); }); + + it('does not write when min_doc_count is false', function () { + var output = paramWriter.write({ + min_doc_count: false, + extended_bounds: { min: 99, max: 100 } + }); + expect(output.params).to.not.have.property('extended_bounds'); + }); }); }); }); diff --git a/src/ui/public/agg_types/buckets/histogram.js b/src/ui/public/agg_types/buckets/histogram.js index 14d292444b8349..344ab964d005fb 100644 --- a/src/ui/public/agg_types/buckets/histogram.js +++ b/src/ui/public/agg_types/buckets/histogram.js @@ -51,7 +51,7 @@ export default function HistogramAggDefinition(Private) { write: function (aggConfig, output) { var val = aggConfig.params.extended_bounds; - if (val.min != null || val.max != null) { + if (aggConfig.params.min_doc_count && (val.min != null || val.max != null)) { output.params.extended_bounds = { min: val.min, max: val.max From c86ea46f093d27baa47839793a9e6e80a53d856a Mon Sep 17 00:00:00 2001 From: Kevin Kirsche Date: Sun, 21 Feb 2016 11:53:30 -0500 Subject: [PATCH 07/70] Update Bootstrap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CSS #16492: Use @input-border-radius variables on input groups. #16529: Un-style the caret on + + +
+ + +
+
+ + +
+ +
+ + +
diff --git a/src/ui/public/stringify/editors/duration.less b/src/ui/public/stringify/editors/duration.less new file mode 100644 index 00000000000000..bde21dd4da8a44 --- /dev/null +++ b/src/ui/public/stringify/editors/duration.less @@ -0,0 +1,10 @@ +.editor-duration { + display: flex; + > .form-group { + flex: 1 1 1%; + padding-right: 5px; + &:last-child { + padding-right: 0; + } + } +} diff --git a/src/ui/public/stringify/register.js b/src/ui/public/stringify/register.js index b03389afc8c652..7b6657c48688c6 100644 --- a/src/ui/public/stringify/register.js +++ b/src/ui/public/stringify/register.js @@ -2,6 +2,7 @@ import fieldFormats from 'ui/registry/field_formats'; import stringifyUrl from 'ui/stringify/types/Url'; import stringifyBytes from 'ui/stringify/types/Bytes'; import stringifyDate from 'ui/stringify/types/Date'; +import stringifyDuration from 'ui/stringify/types/duration'; import stringifyIp from 'ui/stringify/types/Ip'; import stringifyNumber from 'ui/stringify/types/Number'; import stringifyPercent from 'ui/stringify/types/Percent'; @@ -12,6 +13,7 @@ import stringifyTruncate from 'ui/stringify/types/truncate'; fieldFormats.register(stringifyUrl); fieldFormats.register(stringifyBytes); fieldFormats.register(stringifyDate); +fieldFormats.register(stringifyDuration); fieldFormats.register(stringifyIp); fieldFormats.register(stringifyNumber); fieldFormats.register(stringifyPercent); diff --git a/src/ui/public/stringify/types/duration.js b/src/ui/public/stringify/types/duration.js new file mode 100644 index 00000000000000..719f543da3e4bf --- /dev/null +++ b/src/ui/public/stringify/types/duration.js @@ -0,0 +1,98 @@ +import 'ui/stringify/editors/duration.less'; +import _ from 'lodash'; +import moment from 'moment'; +import IndexPatternsFieldFormatProvider from 'ui/index_patterns/_field_format/FieldFormat'; +import durationTemplate from 'ui/stringify/editors/duration.html'; + +export default function DurationFormatProvider(Private) { + const ratioToSeconds = { + picoseconds: 0.000000000001, + nanoseconds: 0.000000001, + microseconds: 0.000001 + }; + const FieldFormat = Private(IndexPatternsFieldFormatProvider); + const HUMAN_FRIENDLY = 'humanize'; + const DEFAULT_OUTPUT_PRECISION = 2; + const DEFAULT_INPUT_FORMAT = { text: 'Seconds', kind: 'seconds' }; + const inputFormats = [ + { text: 'Picoseconds', kind: 'picoseconds' }, + { text: 'Nanoseconds', kind: 'nanoseconds' }, + { text: 'Microseconds', kind: 'microseconds' }, + { text: 'Milliseconds', kind: 'milliseconds' }, + DEFAULT_INPUT_FORMAT, + { text: 'Minutes', kind: 'minutes' }, + { text: 'Hours', kind: 'hours' }, + { text: 'Days', kind: 'days' }, + { text: 'Weeks', kind: 'weeks' }, + { text: 'Months', kind: 'months' }, + { text: 'Years', kind: 'years' } + ]; + const DEFAULT_OUTPUT_FORMAT = { text: 'Human Readable', method: 'humanize' }; + const outputFormats = [ + DEFAULT_OUTPUT_FORMAT, + { text: 'Milliseconds', method: 'asMilliseconds' }, + { text: 'Seconds', method: 'asSeconds' }, + { text: 'Minutes', method: 'asMinutes' }, + { text: 'Hours', method: 'asHours' }, + { text: 'Days', method: 'asDays' }, + { text: 'Weeks', method: 'asWeeks' }, + { text: 'Months', method: 'asMonths' }, + { text: 'Years', method: 'asYears' } + ]; + + class Duration extends FieldFormat { + isHuman() { + return this.param('outputFormat') === HUMAN_FRIENDLY; + } + _convert(val) { + const inputFormat = this.param('inputFormat'); + const outputFormat = this.param('outputFormat'); + const outputPrecision = this.param('outputPrecision'); + const human = this.isHuman(); + const prefix = val < 0 && human ? 'minus ' : ''; + const duration = parseInputAsDuration(val, inputFormat); + const formatted = duration[outputFormat](); + const precise = human ? formatted : formatted.toFixed(outputPrecision); + return prefix + precise; + } + } + + Duration.id = 'duration'; + Duration.title = 'Duration'; + Duration.fieldType = 'number'; + + Duration.inputFormats = inputFormats; + Duration.outputFormats = outputFormats; + + Duration.editor = { + template: durationTemplate, + controllerAs: 'cntrl', + controller($scope, $interval) { + this.sampleInputs = [ + -123, + 1, + 12, + 123, + 658, + 1988, + 3857, + 123292, + 923528271 + ]; + } + }; + + Duration.paramDefaults = { + inputFormat: DEFAULT_INPUT_FORMAT.kind, + outputFormat: DEFAULT_OUTPUT_FORMAT.method, + outputPrecision: DEFAULT_OUTPUT_PRECISION + }; + + return Duration; + + function parseInputAsDuration(val, inputFormat) { + const ratio = ratioToSeconds[inputFormat] || 1; + const kind = inputFormat in ratioToSeconds ? 'seconds' : inputFormat; + return moment.duration(val * ratio, kind); + } +}; From 1787f7704e3ba30fe0b42482a129f5a6d817c278 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Fri, 11 Mar 2016 13:26:45 -0700 Subject: [PATCH 23/70] Fix typo, re: #6415 --- docs/x-axis-aggs.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/x-axis-aggs.asciidoc b/docs/x-axis-aggs.asciidoc index a39eb8a48a20b1..ee080453b09218 100644 --- a/docs/x-axis-aggs.asciidoc +++ b/docs/x-axis-aggs.asciidoc @@ -28,7 +28,7 @@ remove a range. or bottom _n_ elements of a given field to display, ordered by count or a custom metric. *Filters*:: You can specify a set of {ref}/search-aggregations-bucket-filters-aggregation.html[_filters_] for the data. You can specify a filter as a query string or in JSON format, just as in the Discover search bar. Click *Add Filter* to -add another filter. Click the images:labelbutton.png[] *label* button to open the label field, where you can type in a +add another filter. Click the image:labelbutton.png[] *label* button to open the label field, where you can type in a name to display on the visualization. *Significant Terms*:: Displays the results of the experimental {ref}/search-aggregations-bucket-significantterms-aggregation.html[_significant terms_] aggregation. From fe0ced0f735db96a1d17ca3e8b75a00fb59a0ab1 Mon Sep 17 00:00:00 2001 From: Shelby Sturgis Date: Fri, 11 Mar 2016 14:16:15 -0800 Subject: [PATCH 24/70] Closes #6516. Fixes issue with query string not being added to base path. --- src/ui/public/chrome/api/nav.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/public/chrome/api/nav.js b/src/ui/public/chrome/api/nav.js index 297df1543be3a3..0b630a2eccd148 100644 --- a/src/ui/public/chrome/api/nav.js +++ b/src/ui/public/chrome/api/nav.js @@ -18,7 +18,7 @@ export default function (chrome, internals) { var isUrl = url && isString(url); if (!isUrl) return url; - var parsed = parse(url); + var parsed = parse(url, true); if (!parsed.host && parsed.pathname) { if (parsed.pathname[0] === '/') { parsed.pathname = chrome.getBasePath() + parsed.pathname; From 5a80f1be66c76ca3b3db939131cd08a66bbe6df0 Mon Sep 17 00:00:00 2001 From: Rashid Khan Date: Fri, 11 Mar 2016 15:20:21 -0700 Subject: [PATCH 25/70] Fix link to image --- docs/x-axis-aggs.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/x-axis-aggs.asciidoc b/docs/x-axis-aggs.asciidoc index ee080453b09218..802625b0afac71 100644 --- a/docs/x-axis-aggs.asciidoc +++ b/docs/x-axis-aggs.asciidoc @@ -28,7 +28,7 @@ remove a range. or bottom _n_ elements of a given field to display, ordered by count or a custom metric. *Filters*:: You can specify a set of {ref}/search-aggregations-bucket-filters-aggregation.html[_filters_] for the data. You can specify a filter as a query string or in JSON format, just as in the Discover search bar. Click *Add Filter* to -add another filter. Click the image:labelbutton.png[] *label* button to open the label field, where you can type in a +add another filter. Click the image:images/labelbutton.png[] *label* button to open the label field, where you can type in a name to display on the visualization. *Significant Terms*:: Displays the results of the experimental {ref}/search-aggregations-bucket-significantterms-aggregation.html[_significant terms_] aggregation. From c7d2f89cbcbc3e2150a5efc834c05958dc9333bd Mon Sep 17 00:00:00 2001 From: spalger Date: Fri, 11 Mar 2016 16:01:49 -0700 Subject: [PATCH 26/70] [cli/serve] expand dot-notated keys in yaml arrays --- src/cli/serve/read_yaml_config.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/cli/serve/read_yaml_config.js b/src/cli/serve/read_yaml_config.js index 0c28635eddc769..d5d4c2800af02f 100644 --- a/src/cli/serve/read_yaml_config.js +++ b/src/cli/serve/read_yaml_config.js @@ -48,7 +48,14 @@ module.exports = function (path) { _.forOwn(val, function (subVal, subKey) { apply(config, subVal, key + '.' + subKey); }); - } else { + } + else if (_.isArray(val)) { + config[key] = []; + val.forEach((subVal, i) => { + apply(config, subVal, key + '.' + i); + }); + } + else { _.set(config, key, val); } } From caf7331a484bf100fd84cf9fcaff64f5b17599e4 Mon Sep 17 00:00:00 2001 From: spalger Date: Fri, 11 Mar 2016 16:42:19 -0700 Subject: [PATCH 27/70] [filenames] allow rule-breaking in docs, tasks/config, and webpackShims --- Gruntfile.js | 11 ----------- tasks/check_added_filenames.js | 3 ++- .../{download_selenium.js => downloadSelenium.js} | 2 -- 3 files changed, 2 insertions(+), 14 deletions(-) rename tasks/config/{download_selenium.js => downloadSelenium.js} (90%) diff --git a/Gruntfile.js b/Gruntfile.js index 95582d40d5a150..3f510761549f25 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -82,17 +82,6 @@ module.exports = function (grunt) { config: config, loadGruntTasks: { pattern: ['grunt-*', '@*/grunt-*', 'gruntify-*', '@*/gruntify-*', 'intern'] - }, - preMerge(config, data) { - Object.keys(config).forEach(key => { - const taskConfig = config[key]; - if (taskConfig.__taskName__) { - config[taskConfig.__taskName__] = taskConfig; - - delete config[key]; - delete taskConfig.__taskName__; - } - }); } }); diff --git a/tasks/check_added_filenames.js b/tasks/check_added_filenames.js index be3a2ef2f865de..8d132c4b11e7ce 100644 --- a/tasks/check_added_filenames.js +++ b/tasks/check_added_filenames.js @@ -6,8 +6,9 @@ export default function registerCheckAddedFilenames(grunt) { const invalid = grunt.config .get('filesToCommit') - .filter(isAdded) .map(getFilename) + .filter(isAdded) + .filter(name => !name.match(/([\/\\]|^)(docs|tasks[\/\\]config|webpackShims)([\/\\]|$)/)) .filter(name => name.match(/[A-Z \-]/)) .reduce((all, name) => `${all} ${name}\n`, ''); diff --git a/tasks/config/download_selenium.js b/tasks/config/downloadSelenium.js similarity index 90% rename from tasks/config/download_selenium.js rename to tasks/config/downloadSelenium.js index a403c242fb8290..d69fa8d406276c 100644 --- a/tasks/config/download_selenium.js +++ b/tasks/config/downloadSelenium.js @@ -3,8 +3,6 @@ var path = require('path'); module.exports = function (grunt) { return { - __taskName__: 'downloadSelenium', - options: { selenium: { filename: 'selenium-server-standalone-2.48.2.jar', From 398239840dcb16c57225e9017af1dea6d54c22d7 Mon Sep 17 00:00:00 2001 From: spalger Date: Sun, 13 Mar 2016 14:28:29 -0700 Subject: [PATCH 28/70] [grunt/esvm] remove marvel config now that it is actually being applied --- tasks/config/esvm.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tasks/config/esvm.js b/tasks/config/esvm.js index 89bf4115333b71..0b1618a53981d7 100644 --- a/tasks/config/esvm.js +++ b/tasks/config/esvm.js @@ -14,11 +14,6 @@ module.exports = function (grunt) { }, http: { port: 9200 - }, - marvel: { - agent: { - enabled: false - } } } }, From 5e3ee152703ccd4b7a187f4349fc100c87a09034 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 14 Mar 2016 11:32:35 -0400 Subject: [PATCH 29/70] [npm] update grunt-esvm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 646ddf0823ae2c..10acb41b619586 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "grunt-cli": "0.1.13", "grunt-contrib-clean": "0.6.0", "grunt-contrib-copy": "0.8.1", - "grunt-esvm": "2.1.1", + "grunt-esvm": "3.0.0", "grunt-karma": "0.12.0", "grunt-run": "0.5.0", "grunt-s3": "0.2.0-alpha.3", From c8dfe250510b64322b968082883e6c9e4f4eec19 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 14 Mar 2016 11:34:02 -0400 Subject: [PATCH 30/70] [npm] update libesvm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 10acb41b619586..737e7b70cab7fe 100644 --- a/package.json +++ b/package.json @@ -174,7 +174,7 @@ "karma-ie-launcher": "0.2.0", "karma-mocha": "0.2.0", "karma-safari-launcher": "0.1.1", - "libesvm": "3.3.0", + "libesvm": "3.4.5", "license-checker": "3.1.0", "load-grunt-config": "0.7.2", "makelogs": "3.0.0-beta3", From 79e868c062ea8b8bf3da64a34abe679ac941ca02 Mon Sep 17 00:00:00 2001 From: Patrick Fournier Date: Mon, 14 Mar 2016 12:15:01 -0400 Subject: [PATCH 31/70] Additional tests to document titlecase functionality. --- src/ui/public/stringify/__tests__/_string.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ui/public/stringify/__tests__/_string.js b/src/ui/public/stringify/__tests__/_string.js index 6f39ad199e0bac..22b731a4eb167f 100644 --- a/src/ui/public/stringify/__tests__/_string.js +++ b/src/ui/public/stringify/__tests__/_string.js @@ -23,6 +23,8 @@ describe('String Format', function () { transform: 'title' }); expect(string.convert('PLEASE DO NOT SHOUT')).to.be('Please Do Not Shout'); + expect(string.convert('Mean, variance and standard_deviation.')).to.be('Mean, Variance And Standard_deviation.'); + expect(string.convert('Stay CALM!')).to.be('Stay Calm!'); }); }); From ec037de9be78b08e0e53589a2ca561ff74c8c742 Mon Sep 17 00:00:00 2001 From: Nicolas Bevacqua Date: Mon, 14 Mar 2016 14:06:25 -0300 Subject: [PATCH 32/70] [test] Consolidate elasticsearch URL in configuration file. Fixes #5555 --- .../lib/__tests__/check_es_version.js | 4 +++- .../elasticsearch/lib/__tests__/health_check.js | 16 +++++++++++----- src/ui/public/utils/__tests__/scanner.js | 5 ++++- tasks/config/esvm.js | 6 +++--- test/utils/__tests__/getPage.js | 2 +- test/utils/kbn_server.js | 4 +++- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/plugins/elasticsearch/lib/__tests__/check_es_version.js b/src/plugins/elasticsearch/lib/__tests__/check_es_version.js index 51424a841af4df..1c1ece01c41229 100644 --- a/src/plugins/elasticsearch/lib/__tests__/check_es_version.js +++ b/src/plugins/elasticsearch/lib/__tests__/check_es_version.js @@ -1,7 +1,9 @@ import _ from 'lodash'; import Promise from 'bluebird'; import sinon from 'sinon'; +import url from 'url'; +import serverConfig from '../../../../../test/serverConfig'; import checkEsVersion from '../check_es_version'; describe('plugins/elasticsearch', function () { @@ -23,7 +25,7 @@ describe('plugins/elasticsearch', function () { status: { red: sinon.stub() }, - url: 'http://localhost:9210' + url: url.format(serverConfig.servers.elasticsearch) } } }; diff --git a/src/plugins/elasticsearch/lib/__tests__/health_check.js b/src/plugins/elasticsearch/lib/__tests__/health_check.js index 3292ba67abb08c..5065e7bc59ce96 100644 --- a/src/plugins/elasticsearch/lib/__tests__/health_check.js +++ b/src/plugins/elasticsearch/lib/__tests__/health_check.js @@ -1,9 +1,15 @@ import Promise from 'bluebird'; import sinon from 'sinon'; import expect from 'expect.js'; +import url from 'url'; + const NoConnections = require('elasticsearch').errors.NoConnections; import healthCheck from '../health_check'; +import serverConfig from '../../../../../test/serverConfig'; + +const esPort = serverConfig.servers.elasticsearch.port; +const esUrl = url.format(serverConfig.servers.elasticsearch); describe('plugins/elasticsearch', function () { describe('lib/health_check', function () { @@ -39,7 +45,7 @@ describe('plugins/elasticsearch', function () { nodes: { 'node-01': { version: '1.5.0', - http_address: 'inet[/127.0.0.1:9210]', + http_address: `inet[/127.0.0.1:${esPort}]`, ip: '127.0.0.1' } } @@ -73,7 +79,7 @@ describe('plugins/elasticsearch', function () { it('should set the cluster red if the ping fails, then to green', function () { - get.withArgs('elasticsearch.url').returns('http://localhost:9210'); + get.withArgs('elasticsearch.url').returns(esUrl); get.withArgs('elasticsearch.engineVersion').returns('^1.4.4'); get.withArgs('kibana.index').returns('.my-kibana'); client.ping.onCall(0).returns(Promise.reject(new NoConnections())); @@ -85,7 +91,7 @@ describe('plugins/elasticsearch', function () { expect(plugin.status.yellow.args[0][0]).to.be('Waiting for Elasticsearch'); sinon.assert.calledOnce(plugin.status.red); expect(plugin.status.red.args[0][0]).to.be( - 'Unable to connect to Elasticsearch at http://localhost:9210.' + `Unable to connect to Elasticsearch at ${esUrl}.` ); sinon.assert.calledTwice(client.ping); sinon.assert.calledOnce(client.nodes.info); @@ -97,7 +103,7 @@ describe('plugins/elasticsearch', function () { }); it('should set the cluster red if the health check status is red, then to green', function () { - get.withArgs('elasticsearch.url').returns('http://localhost:9210'); + get.withArgs('elasticsearch.url').returns(esUrl); get.withArgs('elasticsearch.engineVersion').returns('^1.4.4'); get.withArgs('kibana.index').returns('.my-kibana'); client.ping.returns(Promise.resolve()); @@ -120,7 +126,7 @@ describe('plugins/elasticsearch', function () { }); it('should set the cluster yellow if the health check timed_out and create index', function () { - get.withArgs('elasticsearch.url').returns('http://localhost:9210'); + get.withArgs('elasticsearch.url').returns(esUrl); get.withArgs('elasticsearch.engineVersion').returns('^1.4.4'); get.withArgs('kibana.index').returns('.my-kibana'); client.ping.returns(Promise.resolve()); diff --git a/src/ui/public/utils/__tests__/scanner.js b/src/ui/public/utils/__tests__/scanner.js index 9e1c89d8d7c85f..9abc4ca618c779 100644 --- a/src/ui/public/utils/__tests__/scanner.js +++ b/src/ui/public/utils/__tests__/scanner.js @@ -4,6 +4,9 @@ import Bluebird from 'bluebird'; import 'elasticsearch-browser'; import ngMock from 'ngMock'; import sinon from 'sinon'; +import url from 'url'; + +import serverConfig from '../../../../../test/serverConfig'; describe('Scanner', function () { let es; @@ -11,7 +14,7 @@ describe('Scanner', function () { beforeEach(ngMock.module('kibana')); beforeEach(ngMock.inject(function (esFactory) { es = esFactory({ - host: 'http://localhost:9210', + host: url.format(serverConfig.servers.elasticsearch), defer: function () { return Bluebird.defer(); } diff --git a/tasks/config/esvm.js b/tasks/config/esvm.js index 89bf4115333b71..6e740b0bae0573 100644 --- a/tasks/config/esvm.js +++ b/tasks/config/esvm.js @@ -2,7 +2,7 @@ module.exports = function (grunt) { var resolve = require('path').resolve; var directory = resolve(__dirname, '../../esvm'); var dataDir = resolve(directory, 'data_dir'); - var uiConfig = require('../../test/serverConfig'); + var serverConfig = require('../../test/serverConfig'); return { options: { @@ -41,7 +41,7 @@ module.exports = function (grunt) { purge: true, config: { http: { - port: 9210 + port: serverConfig.servers.elasticsearch.port }, cluster: { name: 'esvm-test' @@ -55,7 +55,7 @@ module.exports = function (grunt) { purge: true, config: { http: { - port: uiConfig.servers.elasticsearch.port + port: serverConfig.servers.elasticsearch.port }, cluster: { name: 'esvm-ui' diff --git a/test/utils/__tests__/getPage.js b/test/utils/__tests__/getPage.js index 19ce3a1fae24b7..1c2b0bf2dd871d 100644 --- a/test/utils/__tests__/getPage.js +++ b/test/utils/__tests__/getPage.js @@ -13,7 +13,7 @@ describe('getUrl', function () { expect(url).to.be('http://localhost/foo'); }); - it('should convert to a secure url with port', function () { + it('should convert to a url with port', function () { var url = getUrl({ protocol: 'http', hostname: 'localhost', diff --git a/test/utils/kbn_server.js b/test/utils/kbn_server.js index eb77401615dc34..cc5649669cb190 100644 --- a/test/utils/kbn_server.js +++ b/test/utils/kbn_server.js @@ -1,8 +1,10 @@ +import url from 'url'; import { defaultsDeep, set } from 'lodash'; import { header as basicAuthHeader } from './base_auth'; import { kibanaUser, kibanaServer } from '../shield'; import KbnServer from '../../src/server/KbnServer'; import fromRoot from '../../src/utils/fromRoot'; +import serverConfig from '../serverConfig'; const SERVER_DEFAULTS = { server: { @@ -23,7 +25,7 @@ const SERVER_DEFAULTS = { enabled: false }, elasticsearch: { - url: 'http://localhost:9210', + url: url.format(serverConfig.servers.elasticsearch), username: kibanaServer.username, password: kibanaServer.password } From 7969c8da2b6b8ebea96b6987673acda305b5691c Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 14 Mar 2016 12:28:21 -0400 Subject: [PATCH 33/70] [npm] update grunt-esvm, remove libesvm --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 737e7b70cab7fe..54d63bb954fc31 100644 --- a/package.json +++ b/package.json @@ -156,7 +156,7 @@ "grunt-cli": "0.1.13", "grunt-contrib-clean": "0.6.0", "grunt-contrib-copy": "0.8.1", - "grunt-esvm": "3.0.0", + "grunt-esvm": "3.0.3", "grunt-karma": "0.12.0", "grunt-run": "0.5.0", "grunt-s3": "0.2.0-alpha.3", @@ -174,7 +174,6 @@ "karma-ie-launcher": "0.2.0", "karma-mocha": "0.2.0", "karma-safari-launcher": "0.1.1", - "libesvm": "3.4.5", "license-checker": "3.1.0", "load-grunt-config": "0.7.2", "makelogs": "3.0.0-beta3", From 2618d1aa4db0d6cae6565f57e58943bef1b948ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Bevacqua?= Date: Mon, 14 Mar 2016 16:00:38 -0300 Subject: [PATCH 34/70] Removed typo --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6cbdae5c3e2369..19dffe7114a150 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -218,7 +218,7 @@ So, you've been assigned a pull to review. What's that look like? Remember, someone is blocked by a pull awaiting review, make it count. Be thorough, the more action items you catch in the first review, the less back and forth will be required, and the better chance the pull has of being successful. Don't you like success? -1. **Understand the issue** that is being fixed, or the feature being added. Check the description on the pull, and check out the related issue. If you don't understand something, ask the person the submitter for clarification. +1. **Understand the issue** that is being fixed, or the feature being added. Check the description on the pull, and check out the related issue. If you don't understand something, ask the submitter for clarification. 1. **Reproduce the bug** (or the lack of feature I guess?) in the destination branch, usually `master`. The referenced issue will help you here. If you're unable to reproduce the issue, contact the issue submitter for clarification 1. **Check out the pull** and test it. Is the issue fixed? Does it have nasty side effects? Try to create suspect inputs. If it operates on the value of a field try things like: strings (including an empty string), null, numbers, dates. Try to think of edge cases that might break the code. 1. **Merge the target branch**. It is possible that tests or the linter have been updated in the target branch since the pull was submitted. Merging the pull could cause core to start failing. From 89aff0210ff00bd24e0c915cecb98c5104ff43d7 Mon Sep 17 00:00:00 2001 From: LeeDr Date: Mon, 14 Mar 2016 14:40:53 -0500 Subject: [PATCH 35/70] Changes to methods for getting more specific chart data to cover integration testing. --- test/functional/apps/visualize/_area_chart.js | 2 +- test/functional/apps/visualize/_line_chart.js | 2 +- test/support/pages/visualize_page.js | 124 ++++++++++++------ 3 files changed, 84 insertions(+), 44 deletions(-) diff --git a/test/functional/apps/visualize/_area_chart.js b/test/functional/apps/visualize/_area_chart.js index a456dfec3ed748..4770acd3d726a9 100644 --- a/test/functional/apps/visualize/_area_chart.js +++ b/test/functional/apps/visualize/_area_chart.js @@ -150,7 +150,7 @@ define(function (require) { expect(labels).to.eql(yAxisLabels); }) .then(function getAreaChartData() { - return visualizePage.getAreaChartData(); + return visualizePage.getAreaChartData('count'); }) .then(function (paths) { common.debug('expectedAreaChartData = ' + expectedAreaChartData); diff --git a/test/functional/apps/visualize/_line_chart.js b/test/functional/apps/visualize/_line_chart.js index 539758e69bb6bb..823a34acc51fc5 100644 --- a/test/functional/apps/visualize/_line_chart.js +++ b/test/functional/apps/visualize/_line_chart.js @@ -122,7 +122,7 @@ define(function (require) { // sleep a bit before trying to get the chart data return common.sleep(3000) .then(function () { - return visualizePage.getLineChartData() + return visualizePage.getLineChartData('fill="#57c17b"') .then(function showData(data) { var tolerance = 10; // the y-axis scale is 10000 so 10 is 0.1% for (var x = 0; x < data.length; x++) { diff --git a/test/support/pages/visualize_page.js b/test/support/pages/visualize_page.js index 2ac4fbb2484d68..b7cea331c9588e 100644 --- a/test/support/pages/visualize_page.js +++ b/test/support/pages/visualize_page.js @@ -327,22 +327,71 @@ define(function (require) { }); }, - // saved visualizations are paginated 5 to a page! - loadSavedVisualization: function loadSavedVisualization(vizName) { - var self = this; + + clickLoadSavedVisButton: function clickLoadSavedVisButton() { return this.remote .setFindTimeout(defaultTimeout) .findByCssSelector('button.ng-scope[aria-label="Load Saved Visualization"]') - .click() - .then(function findVizByLinkedText() { - common.debug('Load Saved Vis button clicked'); + .click(); + }, + + filterVisByName: function filterVisByName(vizName) { + var self = this; + return this.remote + .findByCssSelector('input[name="filter"]') + .then(function (filter) { + return self.remote.moveMouseTo(filter); + }) + .then (function () { + return self.remote + .findByCssSelector('input[name="filter"]') + .click() + .type(vizName.replace('-',' ')); + }) + .then (function () { + common.sleep(3000); + }); + }, + + clickVisualizationByLinkText: function clickVisualizationByLinkText(vizName) { + var self = this; + common.debug('clickVisualizationByLinkText(' + vizName + ')'); + return this.remote + .setFindTimeout(defaultTimeout) + .findByLinkText(vizName) + .then(function (link) { + return self.remote.moveMouseTo(link); + }) + .then (function () { return self.remote - .setFindTimeout(defaultTimeout) .findByLinkText(vizName) .click(); }); }, + // this starts by clicking the Load Saved Viz button, not from the + // bottom half of the "Create a new visualization Step 1" page + loadSavedVisualization: function loadSavedVisualization(vizName) { + var self = this; + return this.clickLoadSavedVisButton() + .then(function filterVisualization() { + return self.filterVisByName(vizName); + }) + .then(function clickDashboardByLinkedText() { + return self.clickVisualizationByLinkText(vizName); + }); + }, + + // this starts on the + // bottom half of the "Create a new visualization Step 1" page + openSavedVisualization: function openSavedVisualization(vizName) { + var self = this; + return self.filterVisByName(vizName) + .then(function clickDashboardByLinkedText() { + return self.clickVisualizationByLinkText(vizName); + }); + }, + getXAxisLabels: function getXAxisLabels() { return this.remote .setFindTimeout(defaultTimeout) @@ -385,7 +434,7 @@ define(function (require) { ** This method gets the chart data and scales it based on chart height and label. ** Returns an array of height values */ - getAreaChartData: function getAreaChartData() { + getAreaChartData: function getAreaChartData(aggregateName) { var self = this.remote; var chartData = []; @@ -404,7 +453,7 @@ define(function (require) { return y.getVisibleText(); }) .then(function (yLabel) { - yAxisLabel = yLabel.replace(',', ''); + yAxisLabel = yLabel.replace(',', '').replace('%',''); common.debug('yAxisLabel = ' + yAxisLabel); return yLabel; }) @@ -423,43 +472,27 @@ define(function (require) { }) .then(function () { return self.setFindTimeout(defaultTimeout * 2) - .findAllByCssSelector('path') - .then(function (chartTypes) { - - function getChartType(chart) { - return chart - .getAttribute('data-label') - .then(function (chartString) { - //common.debug('data-label = ' + chartString); - if (chartString === 'Count') { - return chart.getAttribute('d') - .then(function (data) { - common.debug(data); - tempArray = data.split('L'); - chartSections = tempArray.length / 2; - common.debug('chartSections = ' + chartSections + ' height = ' + yAxisHeight + ' yAxisLabel = ' + yAxisLabel); - chartData[0] = Math.round((yAxisHeight - tempArray[0].split(',')[1]) / yAxisHeight * yAxisLabel); - common.debug('chartData[0] =' + chartData[0]); - for (var i = 1; i < chartSections; i++) { - chartData[i] = Math.round((yAxisHeight - tempArray[i].split(',')[1]) / yAxisHeight * yAxisLabel); - common.debug('chartData[i] =' + chartData[i]); - } - return chartData; - }); - } - }); - } - var getChartTypesPromises = chartTypes.map(getChartType); - return Promise.all(getChartTypesPromises); - }); + .findByCssSelector('path[data-label="' + aggregateName + '"]'); + }) + .then(function (chart) { + return chart.getAttribute('d'); }) - .then(function (chartData) { - return chartData[1]; // MAGIC NUMBER - we find multiple 'path's and only one of them is the right one. + .then(function (data) { + common.debug(data); + tempArray = data.replace('M','').split('L'); + chartSections = tempArray.length / 2; + common.debug('chartSections = ' + chartSections + ' height = ' + yAxisHeight + ' yAxisLabel = ' + yAxisLabel); + for (var i = 0; i < chartSections; i++) { + chartData[i] = Math.round((yAxisHeight - tempArray[i].split(',')[1]) / yAxisHeight * yAxisLabel); + common.debug('chartData[i] =' + chartData[i]); + } + return chartData; }); }, + // The current test shows dots, not a line. This function gets the dots and normalizes their height. - getLineChartData: function getLineChartData() { + getLineChartData: function getLineChartData(cssPart) { var self = this.remote; var yAxisLabel = 0; var yAxisHeight; @@ -502,7 +535,7 @@ define(function (require) { // 5). for each chart element, find the green circle, then the cy position function getChartType(chart) { return chart - .findByCssSelector('circle[fill="#57c17b"]') + .findByCssSelector('circle[' + cssPart + ']') .then(function (circleObject) { // common.debug('circleObject = ' + circleObject + ' yAxisHeight= ' + yAxisHeight + ' yAxisLabel= ' + yAxisLabel); return circleObject @@ -636,6 +669,13 @@ define(function (require) { .getVisibleText(); }, + getMarkdownData: function getMarkdownData() { + return this.remote + .setFindTimeout(defaultTimeout) + .findByCssSelector('visualize.ng-isolate-scope') + .getVisibleText(); + }, + clickColumns: function clickColumns() { return this.remote .setFindTimeout(defaultTimeout) From e1168c52194536405568576aba59b5a777bb3399 Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 14 Mar 2016 15:23:49 -0700 Subject: [PATCH 36/70] match arguments of state emit --- src/server/status/Status.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/status/Status.js b/src/server/status/Status.js index 9e11cf6bc19054..2ae32749b958a3 100644 --- a/src/server/status/Status.js +++ b/src/server/status/Status.js @@ -41,13 +41,13 @@ class Status extends EventEmitter { super.on(eventName, handler); if (eventName === this.state) { - setImmediate(handler); + setImmediate(() => handler(this.state, this.message)); } } once(eventName, handler) { if (eventName === this.state) { - setImmediate(handler); + setImmediate(() => handler(this.state, this.message)); } else { super.once(eventName, handler); } From 8b3416e269ad7d997f126ec30821a147e3074f2b Mon Sep 17 00:00:00 2001 From: Joe Fleming Date: Mon, 14 Mar 2016 15:24:16 -0700 Subject: [PATCH 37/70] update tests, check for listener arguments --- src/server/status/__tests__/Status.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/server/status/__tests__/Status.js b/src/server/status/__tests__/Status.js index 727befb3138901..080cfb41163d88 100644 --- a/src/server/status/__tests__/Status.js +++ b/src/server/status/__tests__/Status.js @@ -4,7 +4,6 @@ var Status = require('../Status'); var ServerStatus = require('../ServerStatus'); describe('Status class', function () { - var server; var serverStatus; @@ -64,8 +63,10 @@ describe('Status class', function () { var msg = 'Test Ready'; status.green(msg); - status.on('green', function () { - expect(arguments.length).to.equal(0); + status.on('green', function (prev, prevMsg) { + expect(arguments.length).to.equal(2); + expect(prev).to.be('green'); + expect(prevMsg).to.be(msg); expect(status.message).to.equal(msg); done(); }); @@ -76,8 +77,10 @@ describe('Status class', function () { var msg = 'Test Ready'; status.green(msg); - status.once('green', function () { - expect(arguments.length).to.equal(0); + status.once('green', function (prev, prevMsg) { + expect(arguments.length).to.equal(2); + expect(prev).to.be('green'); + expect(prevMsg).to.be(msg); expect(status.message).to.equal(msg); done(); }); From 57b09c5b9964a1539a5373eb0ccc242dc97374de Mon Sep 17 00:00:00 2001 From: Matthew Bargar Date: Mon, 14 Mar 2016 18:45:00 -0400 Subject: [PATCH 38/70] Fix #6490 ingest API should respect kibana.index config --- .../kibana/server/routes/api/ingest/register_delete.js | 3 ++- src/plugins/kibana/server/routes/api/ingest/register_post.js | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/kibana/server/routes/api/ingest/register_delete.js b/src/plugins/kibana/server/routes/api/ingest/register_delete.js index 92a020d8435ddb..fb81655f1da047 100644 --- a/src/plugins/kibana/server/routes/api/ingest/register_delete.js +++ b/src/plugins/kibana/server/routes/api/ingest/register_delete.js @@ -7,9 +7,10 @@ module.exports = function registerDelete(server) { path: '/api/kibana/ingest/{id}', method: 'DELETE', handler: function (req, reply) { + const kibanaIndex = server.config().get('kibana.index'); const callWithRequest = server.plugins.elasticsearch.callWithRequest; const deletePatternParams = { - index: '.kibana', + index: kibanaIndex, type: 'index-pattern', id: req.params.id }; diff --git a/src/plugins/kibana/server/routes/api/ingest/register_post.js b/src/plugins/kibana/server/routes/api/ingest/register_post.js index b36b778232fddf..fe944f53070557 100644 --- a/src/plugins/kibana/server/routes/api/ingest/register_post.js +++ b/src/plugins/kibana/server/routes/api/ingest/register_post.js @@ -17,6 +17,7 @@ module.exports = function registerPost(server) { } }, handler: function (req, reply) { + const kibanaIndex = server.config().get('kibana.index'); const callWithRequest = server.plugins.elasticsearch.callWithRequest; const requestDocument = _.cloneDeep(req.payload); const indexPatternId = requestDocument.id; @@ -36,7 +37,7 @@ module.exports = function registerPost(server) { } const patternCreateParams = { - index: '.kibana', + index: kibanaIndex, type: 'index-pattern', id: indexPatternId, body: indexPattern @@ -74,7 +75,7 @@ module.exports = function registerPost(server) { return callWithRequest(req, 'indices.putTemplate', templateParams) .catch((templateError) => { const deleteParams = { - index: '.kibana', + index: kibanaIndex, type: 'index-pattern', id: indexPatternId }; From d12e2990bed0d3fa53a3cd1faed92202bf03deed Mon Sep 17 00:00:00 2001 From: Matthew Bargar Date: Mon, 14 Mar 2016 17:13:32 -0400 Subject: [PATCH 39/70] Count API - count the number of documents in an index pattern --- src/plugins/kibana/index.js | 2 + .../routes/api/search/count/register_count.js | 25 ++++++++ .../kibana/server/routes/api/search/index.js | 5 ++ test/api_intern.js | 3 +- test/unit/api/search/_count.js | 64 +++++++++++++++++++ test/unit/api/search/index.js | 23 +++++++ 6 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 src/plugins/kibana/server/routes/api/search/count/register_count.js create mode 100644 src/plugins/kibana/server/routes/api/search/index.js create mode 100644 test/unit/api/search/_count.js create mode 100644 test/unit/api/search/index.js diff --git a/src/plugins/kibana/index.js b/src/plugins/kibana/index.js index b1ea675fd1057e..88ab65eb3d38a8 100644 --- a/src/plugins/kibana/index.js +++ b/src/plugins/kibana/index.js @@ -1,4 +1,5 @@ import ingest from './server/routes/api/ingest'; +import search from './server/routes/api/search'; module.exports = function (kibana) { return new kibana.Plugin({ @@ -38,6 +39,7 @@ module.exports = function (kibana) { init: function (server, options) { ingest(server); + search(server); } }); diff --git a/src/plugins/kibana/server/routes/api/search/count/register_count.js b/src/plugins/kibana/server/routes/api/search/count/register_count.js new file mode 100644 index 00000000000000..6e1592a2b0cb16 --- /dev/null +++ b/src/plugins/kibana/server/routes/api/search/count/register_count.js @@ -0,0 +1,25 @@ +import _ from 'lodash'; +import handleESError from '../../../../lib/handle_es_error'; + +export default function registerCount(server) { + server.route({ + path: '/api/kibana/{id}/_count', + method: 'POST', + handler: function (req, reply) { + const boundCallWithRequest = _.partial(server.plugins.elasticsearch.callWithRequest, req); + + boundCallWithRequest('count', { + allowNoIndices: false, + index: req.params.id + }) + .then( + function (res) { + reply({count: res.count}); + }, + function (error) { + reply(handleESError(error)); + } + ); + } + }); +} diff --git a/src/plugins/kibana/server/routes/api/search/index.js b/src/plugins/kibana/server/routes/api/search/index.js new file mode 100644 index 00000000000000..2dfea0d380d4f5 --- /dev/null +++ b/src/plugins/kibana/server/routes/api/search/index.js @@ -0,0 +1,5 @@ +import registerCount from './count/register_count'; + +export default function (server) { + registerCount(server); +} diff --git a/test/api_intern.js b/test/api_intern.js index c8b9b9aee40401..c30303e96c593f 100644 --- a/test/api_intern.js +++ b/test/api_intern.js @@ -1,6 +1,7 @@ define({ suites: [ - 'test/unit/api/ingest/index' + 'test/unit/api/ingest/index', + 'test/unit/api/search/index' ], excludeInstrumentation: /(fixtures|node_modules)\//, loaderOptions: { diff --git a/test/unit/api/search/_count.js b/test/unit/api/search/_count.js new file mode 100644 index 00000000000000..eb27d941830f15 --- /dev/null +++ b/test/unit/api/search/_count.js @@ -0,0 +1,64 @@ +define(function (require) { + var Promise = require('bluebird'); + var _ = require('intern/dojo/node!lodash'); + var expect = require('intern/dojo/node!expect.js'); + + return function (bdd, scenarioManager, request) { + bdd.describe('Count API', function postIngest() { + + bdd.before(function () { + return scenarioManager.client.create({ + index: 'foo-1', + type: 'bar', + id: '1', + body: { + foo: 'bar' + } + }) + .then(function () { + return scenarioManager.client.create({ + index: 'foo-2', + type: 'bar', + id: '2', + body: { + foo: 'bar' + } + }); + }) + .then(function () { + return scenarioManager.client.indices.refresh({ + index: ['foo-1', 'foo-2'] + }); + }); + }); + + bdd.after(function () { + return scenarioManager.reload('emptyKibana') + .then(function () { + scenarioManager.client.indices.delete({ + index: 'foo*' + }); + }); + }); + + bdd.it('should return 200 with a document count for existing indices', function () { + return request.post('/kibana/foo-*/_count') + .expect(200) + .then(function (response) { + expect(response.body.count).to.be(2); + }); + }); + + bdd.it('should return 404 if a pattern matches no indices', function () { + return request.post('/kibana/doesnotexist-*/_count') + .expect(404); + }); + + bdd.it('should return 404 if a concrete index does not exist', function () { + return request.post('/kibana/concrete/_count') + .expect(404); + }); + + }); + }; +}); diff --git a/test/unit/api/search/index.js b/test/unit/api/search/index.js new file mode 100644 index 00000000000000..4da8df89441dda --- /dev/null +++ b/test/unit/api/search/index.js @@ -0,0 +1,23 @@ +define(function (require) { + var bdd = require('intern!bdd'); + var serverConfig = require('intern/dojo/node!../../../serverConfig'); + var ScenarioManager = require('intern/dojo/node!../../../fixtures/scenario_manager'); + var request = require('intern/dojo/node!supertest-as-promised'); + var url = require('intern/dojo/node!url'); + var count = require('./_count'); + + bdd.describe('search API', function () { + var scenarioManager = new ScenarioManager(url.format(serverConfig.servers.elasticsearch)); + request = request(url.format(serverConfig.servers.kibana) + '/api'); + + bdd.before(function () { + return scenarioManager.load('emptyKibana'); + }); + + bdd.after(function () { + return scenarioManager.unload('emptyKibana'); + }); + + count(bdd, scenarioManager, request); + }); +}); From 41fe73e57e7bdaf53596d4071f7095625ee7c4d1 Mon Sep 17 00:00:00 2001 From: Matthew Bargar Date: Tue, 15 Mar 2016 10:59:45 -0400 Subject: [PATCH 40/70] Support both GET and POST in the count API --- .../routes/api/search/count/register_count.js | 29 ++++++++++++------- test/unit/api/search/_count.js | 8 +++++ test/unit/api/search/index.js | 2 +- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/plugins/kibana/server/routes/api/search/count/register_count.js b/src/plugins/kibana/server/routes/api/search/count/register_count.js index 6e1592a2b0cb16..969906efb34840 100644 --- a/src/plugins/kibana/server/routes/api/search/count/register_count.js +++ b/src/plugins/kibana/server/routes/api/search/count/register_count.js @@ -2,16 +2,14 @@ import _ from 'lodash'; import handleESError from '../../../../lib/handle_es_error'; export default function registerCount(server) { - server.route({ - path: '/api/kibana/{id}/_count', - method: 'POST', - handler: function (req, reply) { - const boundCallWithRequest = _.partial(server.plugins.elasticsearch.callWithRequest, req); + const path = '/api/kibana/{id}/_count'; + const handler = function (req, reply) { + const boundCallWithRequest = _.partial(server.plugins.elasticsearch.callWithRequest, req); - boundCallWithRequest('count', { - allowNoIndices: false, - index: req.params.id - }) + boundCallWithRequest('count', { + allowNoIndices: false, + index: req.params.id + }) .then( function (res) { reply({count: res.count}); @@ -20,6 +18,17 @@ export default function registerCount(server) { reply(handleESError(error)); } ); - } + }; + + server.route({ + path, + method: 'POST', + handler + }); + + server.route({ + path, + method: 'GET', + handler }); } diff --git a/test/unit/api/search/_count.js b/test/unit/api/search/_count.js index eb27d941830f15..239a936cfd1edd 100644 --- a/test/unit/api/search/_count.js +++ b/test/unit/api/search/_count.js @@ -49,6 +49,14 @@ define(function (require) { }); }); + bdd.it('should support GET requests as well', function () { + return request.get('/kibana/foo-*/_count') + .expect(200) + .then(function (response) { + expect(response.body.count).to.be(2); + }); + }); + bdd.it('should return 404 if a pattern matches no indices', function () { return request.post('/kibana/doesnotexist-*/_count') .expect(404); diff --git a/test/unit/api/search/index.js b/test/unit/api/search/index.js index 4da8df89441dda..85fd81bc12253c 100644 --- a/test/unit/api/search/index.js +++ b/test/unit/api/search/index.js @@ -1,6 +1,6 @@ define(function (require) { var bdd = require('intern!bdd'); - var serverConfig = require('intern/dojo/node!../../../serverConfig'); + var serverConfig = require('intern/dojo/node!../../../server_config'); var ScenarioManager = require('intern/dojo/node!../../../fixtures/scenario_manager'); var request = require('intern/dojo/node!supertest-as-promised'); var url = require('intern/dojo/node!url'); From aeecf17b552da91ba93e0ae633c3bb0289e938ae Mon Sep 17 00:00:00 2001 From: Nicolas Bevacqua Date: Tue, 15 Mar 2016 13:43:51 -0300 Subject: [PATCH 41/70] [ui/toast] Added a "Less Info" button to toast messages. Fixes #5190 --- src/ui/public/notify/partials/toaster.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ui/public/notify/partials/toaster.html b/src/ui/public/notify/partials/toaster.html index 52a2e83a067dba..b1679f1082a25a 100644 --- a/src/ui/public/notify/partials/toaster.html +++ b/src/ui/public/notify/partials/toaster.html @@ -16,6 +16,13 @@ ng-class="'btn-' + notif.type" ng-click="notif.showStack = true" >More Info +